Рельсы образуют с тремя моделями и пространством имен - PullRequest
1 голос
/ 16 сентября 2009

Долго бьюсь головой об это. На 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 создало новые экземпляры всех трех моделей с указанными ассоциациями. Однако, хотя кажется, что мой хэш params передается контроллеру, как и должно (на основе журналов обратной трассировки в браузере, когда он взрывается), объект 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

Я не уверен, как модели пространства имен переводятся в свои идентификаторы символов. Спасибо!

1 Ответ

2 голосов
/ 16 сентября 2009

Ну, я впервые играю с 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, какой тип модели использовать.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...