Форма Rails с тремя моделями и пространством имен
-
07-07-2019 - |
Вопрос
Долго стучал головой об это.На Rails 2.3.2, Ruby 1.9.1.
Попытка использовать одну форму для создания трех объектов, имеющих следующие отношения:
class Person
has_one :goat
end
class Goat
belongs_to :person
has_many :kids
end
class Goat::Kid
belongs_to :goat
end
Вот краткое изложение схемы:
Person
first_name
last_name
Goat
name
color
Goat::Kid
nickname
age
мне бы хотелось, чтобы мой #create
действие для создания новых экземпляров всех трех моделей с указанными ассоциациями.Однако, хотя кажется, что мой хэш параметров передается контроллеру, как и должно (на основе журналов обратной трассировки в браузере, когда он взрывается), Goat::Kid
объект не собирает параметры.
irb (сеанс irb — это всего лишь псевдопредставление того, что я пытаюсь выполнить, поэтому, если он не вызывает #save!
или любые другие потребности, это не совсем правильно.Я пытаюсь сделать это через браузер/веб-форму.)
a = Person.new :first_name => 'Leopold', :last_name => 'Bloom'
b = Goat.new :name => 'Billy', :color => 'white'
c = Goat::Kid.new :nickname => 'Jr.', :age => 2
a.goat.kids
>> []
Теперь я не могу понять, как заставить представление передавать параметры каждому объекту и заставить контроллер сохранять эти параметры в базе данных.
Мои вопросы:А) хорошее ли это место для использования nested_attributes_for
и если да, то как мне объявить это с помощью пространства имен?Б) есть ли более простой и понятный способ сделать это?
Передача параметров трем моделям была для меня очень сложной задачей, и сколько бы документации я ни читал, я не могу уяснить это (#form_for
и #fields_for
).Пространство имен еще больше усложняет ситуацию.Спасибо за любую помощь!
Приложение:если я в конечном итоге объявлю
accepts_nested_attributes_for
как правильно использовать аргумент символа для модели с пространством имен?
accepts_nested_attributes_for :kids, :through => :goats
или
accepts_nested_attributes_for :goats_kids, :through => :goats
или
accepts_nested_attributes_for :goats::kids, :through => :goats
Я не уверен, как модели с пространством имен преобразуются в их идентификаторы символов.Спасибо!
Решение
Ну, я впервые играю с accepts_nested_attributes_for
, но, немного поигравшись, мне удалось заставить что-то работать.
Сначала настройка модели:
class Person < ActiveRecord::Base
has_one :goat
accepts_nested_attributes_for :goat
end
class Goat < ActiveRecord::Base
belongs_to :person
has_many :kids
accepts_nested_attributes_for :kids
end
class Goat::Kid < ActiveRecord::Base
belongs_to :goat
end
С помощью простого спокойного контроллера:
ActionController::Routing::Routes.draw do |map|
map.resources :farm
end
class FarmController < ApplicationController
def new
end
def create
person = Person.new params[:person]
person.save
render :text => person.inspect
end
end
Затем идет полусложная форма:
Далее настройка формы:
<% form_for :person, :url => farm_index_path do |p| %>
<%= p.label :first_name %>: <%= p.text_field :first_name %><br />
<%= p.label :last_name %>: <%= p.text_field :last_name %><br />
<% p.fields_for :goat_attributes do |g| %>
<%= g.label :name %>: <%= g.text_field :name %><br />
<%= g.label :color %>: <%= g.text_field :color %><br />
<% g.fields_for 'kids_attributes[]', Goat::Kid.new do |k| %>
<%= k.label :nickname %>: <%= k.text_field :nickname %><br />
<%= k.label :age %>: <%= k.text_field :age %><br />
<% end %>
<% end %>
<%= p.submit %>
<% end %>
Судя по источнику accepts_nested_attributes_for
, похоже, он создаст для вас метод под названием #{attr_name}_attributes=
, поэтому мне нужно было настроить fields_for
чтобы отразить это (Rails 2.3.3).Далее, получив has_many :kids
работать с accepts_nested_attributes_for
.А kids_attributes=
метод искал массив объектов, поэтому мне нужно было указать ассоциацию массива в форме вручную и сообщить fields_for
какой тип модели использовать.
Надеюсь это поможет.