2015-07-19 3 views
0

Я пытаюсь использовать http://rom-rb.org/ и не могу понять, как получить подтверждение присутствия для передачи в присутствии нескольких исходных моделей. Я ожидаю, что следующий скрипт сохранит новое событие и организатор, но вместо этого он говорит, что event_name нет.Проверка формы ro-rb при использовании нескольких отношений

Что мне не хватает?

require 'bundler/inline' 

gemfile do 
    source 'https://rubygems.org' 
    gem 'rom' 
    gem 'rom-sql' 
    gem 'rom-rails' 
    gem 'activemodel' 
    gem 'sqlite3' 
    gem 'activesupport' 
end 

require 'rom' 
require 'rom-rails' 

`rm -Rf /tmp/romtest.sqlite` 
ROM.setup(:sql, 'sqlite:///tmp/romtest.sqlite') 

class Events < ROM::Relation[:sql] 
end 

class Organisers < ROM::Relation[:sql] 
end 

class CreateEvent < ROM::Commands::Create[:sql] 
    relation :events 
    register_as :create 
    result :one 

    associates :organiser, key: [:organiser_id, :id] 
end 

class CreateOrganiser < ROM::Commands::Create[:sql] 
    relation :organisers 
    register_as :create 
    result :one 
end 

class CreateEventWithOrganiser < ROM::Model::Form 
    commands organisers: :create, events: :create 

    input do 
    attribute :email 
    attribute :event_name 
    end 

    validations do 
    validates :event_name, presence: true 
    end 

    def commit! 
    command = organisers.create.with(
     email: email, 
    ) >> events.create.with(
     name: event_name, 
    ) 

    command.transaction do 
     command.call 
    end 
    end 
end 

ROM.finalize 
rom = ROM.env 
gateway = rom.gateways.fetch(:default) 
migration = gateway.migration do 
    change do 
    create_table :organisers do 
     primary_key :id 
     column :email, String, null: false 
    end 

    create_table :events do 
     primary_key :id 
     column :name, String, null: false 
     column :organiser_id, Integer, null: false 
    end 
    end 
end 

migration.apply(gateway.connection, :up) 

f = CreateEventWithOrganiser.build(
    email:  '[email protected]', 
    event_name: 'Test Event' 
) 

# Unexpectedly fails 
f.save 
puts f.errors.full_messages 
# => "Event name can't be blank" 
+0

я могу сделать эту работу явного вызова 'проверки !; return false, если только не успех? 'в верхней части' commit! '. Это предполагаемый API? –

+0

Из чтения источника я также думаю, что я хочу 'inject_commands_for: events, organisers', а не' команды организаторов:: create, events:: create', хотя этот метод не отображается в руководствах. –

ответ

1

Вот обновленная версия вашего скрипта, который работает:

require 'rom' 
require 'rom-rails' 

`rm -Rf /tmp/romtest.sqlite` 
ROM.setup(:sql, 'sqlite:///tmp/romtest.sqlite') 

class Events < ROM::Relation[:sql] 
end 

class Organisers < ROM::Relation[:sql] 
end 

class CreateEvent < ROM::Commands::Create[:sql] 
    relation :events 
    register_as :create 
    result :one 

    associates :organiser, key: [:organiser_id, :id] 
end 

class CreateOrganiser < ROM::Commands::Create[:sql] 
    relation :organisers 
    register_as :create 
    result :one 
end 

class CreateEventWithOrganiser < ROM::Model::Form 
    inject_commands_for :organisers, :events 

    input do 
    attribute :email 
    attribute :event_name 
    end 

    validations do 
    validates :event_name, presence: true 
    end 

    def commit! 
    validate! 

    return if errors.any? 

    command = organisers.create.with(
     email: email 
    ) >> events.create.with(
     name: event_name 
    ) 

    command.transaction do 
     command.call 
    end 
    end 
end 

ROM.finalize 
rom = ROM.env 
gateway = rom.gateways.fetch(:default) 
migration = gateway.migration do 
    change do 
    create_table :organisers do 
     primary_key :id 
     column :email, String, null: false 
    end 

    create_table :events do 
     primary_key :id 
     column :name, String, null: false 
     column :organiser_id, Integer, null: false 
    end 
    end 
end 

migration.apply(gateway.connection, :up) 

f = CreateEventWithOrganiser.build(
    email:  '[email protected]', 
    event_name: 'Test Event' 
) 

puts f.save.result.inspect 
# #<ROM::Commands::Result::Success:0x007fa92b589ea0 @value={:id=>1, :name=>"Test Event", :organiser_id=>1}> 

Причина, почему он не работает с commands потому, что этот метод будет генерировать командные объекты для вашей формы и набора при условии валидаций для каждая команда, которая будет работать только правильно, если вы используете одну команду. В противном случае для каждой команды используется тот же валидатор, который не имеет смысла. Когда вы используете inject_commands_for, он будет захватывать ваши собственные команды, где валидаторы не установлены, поэтому вы можете самостоятельно обрабатывать проверки.

Я думаю, мы должны прекратить установку валидаторов на команды, которые сделают ваш оригинальный образец работы, но заметьте, что вам нужно позвонить validate! самостоятельно.

Надеюсь, это поможет.

Я также создал суть, показывающую, как сделать то же самое без формы: https://gist.github.com/solnic/3b68342482cf1414f719

+0

спасибо! Пример без формы действительно помог мне понять, как все сочетается :) –