Подтвердить что ты не робот

Как создать вложенные объекты с помощью accepts_nested_attributes_for

Я обновил до Rails 2.3.3 (от 2.1.x), и я пытаюсь выяснить метод accepts_nested_attributes_for. Я могу использовать этот метод для обновления существующих вложенных объектов, но я не могу использовать его для создания новых вложенных объектов. Учитывая надуманный пример:

class Product < ActiveRecord::Base
  has_many :notes
  accepts_nested_attributes_for :notes
end

class Note < ActiveRecord::Base
  belongs_to :product
  validates_presence_of :product_id, :body
end

Если я попытаюсь создать новый Product с вложенным Note следующим образом:

params = {:name => 'Test', :notes_attributes => {'0' => {'body' => 'Body'}}}
p = Product.new(params)
p.save!

Не удалось выполнить проверку с сообщением:

ActiveRecord::RecordInvalid: Validation failed: Notes product can't be blank

Я понимаю, почему это происходит - из-за validates_presence_of :product_id в классе Note, и поскольку во время сохранения новой записи объект Product не имеет id. Однако я не хочу удалять эту проверку; Я думаю, было бы неправильно удалить его.

Я мог бы также решить проблему, создав сначала Product, а затем добавив Note, но это победит простоту accepts_nested_attributes_for.

Существует ли стандартный способ Rails для создания вложенных объектов в новых записях?

4b9b3361

Ответ 1

Это общая проблема с круговой зависимостью. Существует существующий билет LightHouse, который стоит проверить.

Я ожидаю, что это значительно улучшится в Rails 3, но пока вам придется сделать обходной путь. Одним из решений является настройка виртуального атрибута, который вы устанавливаете при вложенности, чтобы сделать проверку правильной.

class Note < ActiveRecord::Base
  belongs_to :product
  validates_presence_of :product_id, :unless => :nested
  attr_accessor :nested
end

И тогда вы должны установить этот атрибут как скрытое поле в своей форме.

<%= note_form.hidden_field :nested %>

Этого должно быть достаточно, чтобы атрибут nested устанавливался при создании заметки через вложенную форму. Непроверенные.

Ответ 3

Решение Ryan на самом деле действительно круто. Я пошел и сделал мой контроллер толще, чтобы это гнездо не должно было появляться в представлении. В основном потому, что мой взгляд иногда бывает json, поэтому я хочу быть в состоянии как можно меньше уйти.

class Product < ActiveRecord::Base
  has_many :notes
  accepts_nested_attributes_for :note
end

class Note < ActiveRecord::Base
  belongs_to :product
  validates_presence_of :product_id  unless :nested
  attr_accessor :nested
end

class ProductController < ApplicationController

def create
    if params[:product][:note_attributes]
       params[:product][:note_attributes].each { |attribute| 
          attribute.merge!({:nested => true})
    }
    end
    # all the regular create stuff here  
end
end