Как создать вложенные объекты, используя accepts_nested_attributes_for - PullRequest
22 голосов
/ 31 июля 2009

Я обновился до 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 для создания вложенных объектов в новых записях?

Ответы [ 4 ]

16 голосов
/ 01 августа 2009

Это распространенная круговая проблема зависимости. Существует существующий билет 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 при создании заметки через вложенную форму. Непроверенные.

7 голосов
/ 26 сентября 2012

проверьте этот документ, если вы используете Rails3.

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#label-Validating+the+presence+of+a+parent+model

3 голосов
/ 22 января 2010

Решение Райана действительно круто. Я пошел и сделал свой контроллер толще, чтобы это вложение не появлялось на виде. Главным образом потому, что иногда я смотрю на 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
0 голосов
/ 19 ноября 2009

Лучшее решение - использовать плагин parental_control: http://github.com/h-lame/parental_control

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