Rails — одновременное создание родительского и дочернего элементов в has_one created_to

Я уверен, что делаю это неправильно, но я не вижу, где. У меня есть две модели:

Subscription.rb (дочерняя)

class Subscription < ActiveRecord::Base
  attr_accessible :state, :subscriber_id, :subscriber_type, :last_payment

  belongs_to :subscriber, polymorphic: true

  validates :subscriber_id, presence: true
  validates :subscriber_type, presence: true
end

restorer.rb (родительский)

class Restorer < User
  attr_accessible :firstname, :lastname, :restaurant_attributes, :subscription_attributes

  has_one :restaurant, dependent: :destroy, :autosave => true
  has_one :subscription, as: :subscriber, :autosave => true

  accepts_nested_attributes_for :restaurant
  accepts_nested_attributes_for :subscription

end

Когда я хочу создать два новых реставратора и новую подписку (одновременно), это не работает:

  def create
    @restorer = Restorer.create params[:restorer]
    @restaurant = @restorer.build_restaurant params[:restorer][:restaurant_attributes]
    @subscription = @restorer.build_subscription params[:restorer][:subscription_attributes]

    if @restorer.save
      ...
    else
      ...
    end
  end

person p0k3    schedule 09.09.2014    source источник
comment
если вы используете save, вы должны заменить create на new, также вам не нужно использовать build_.. вручную (оно должно работать автоматически) и попробовать save!, которое вызовет сообщение, если что-то не так.   -  person Igor Guzak    schedule 09.09.2014
comment
это вызывает ошибку record_invalid ... кажется, с этой ошибкой «subscriber_id не должен быть пустым»   -  person p0k3    schedule 09.09.2014
comment
Это связано с тем, что вы не можете проверить наличие id для nested_attributes, поскольку они, по сути, создаются почти asynchronously, id не будут присутствовать в сохранении до завершения сохранения. Если вы действительно должны проверить это, что, как мне кажется, вы не делаете с вложенными атрибутами, вам придется создавать эти объекты в пошаговой процедуре, например. создайте подписчика, затем создайте ассоциации. Вы можете справиться с этим в транзакции, но у меня мало опыта в этом.   -  person engineersmnky    schedule 09.09.2014
comment
Хорошо, как я могу подтвердить наличие ребенка?   -  person p0k3    schedule 09.09.2014
comment
Я мог бы объяснить это, но эта запись в блоге делает это намного лучше. более кратко, чем я мог на SO.   -  person engineersmnky    schedule 09.09.2014


Ответы (1)


Глядя на комментарии и ваш код, похоже, что причина, по которой он не работает, связана с проверками на Subscriber. Restorer имеет один Subscription, а Subscription принадлежит Subscriber. Нигде вы не создаете подписчика, поэтому подписка не проходит проверку. Вам нужно либо удалить проверки, либо установить эти проверенные свойства (subscriber_id и subscriber_type) на Subscriber.

Это немного грубо то, что вы пытаетесь сделать в своем творении, но это должно выглядеть примерно так, если вы собираетесь сделать это таким образом:

def create
  @restorer = Restorer.create params[:restorer]

  # These two lines aren't needed if you are accepting nested attributes
  @restaurant = @restorer.build_restaurant params[:restorer][:restaurant_attributes]
  @subscription = @restorer.build_subscription params[:restorer][:subscription_attributes]

  subscriber = Subscriber.new params[:subscriber]
  @subscription.subscriber = subscriber

  if @restorer.save
    ...
  else
    ...
  end
end

Кстати, лучше проверить отношение subscriber, а не идентификатор subscriber_id:

validates :subscriber, presence: true
person dnatoli    schedule 10.09.2014