Rails 3. Как правильно создать ресурс с вложенными атрибутами?

Я создаю свадебный веб-сайт, который позволит гостям входить в систему с кодом приглашения и отвечать на вопросы онлайн. Мои модели следующие:

Приглашение

class Invitation < ActiveRecord::Base

  attr_accessible # None are accessible

  # Validation 
  code_regex = /\A[A-Z0-9]{8}\z/

  validates :code, :presence => true, 
                   :length => { :is => 8 },
                   :uniqueness => true,
                   :format => { :with => code_regex }

  validates :guest_count, :presence => true,
                          :inclusion => { :in => 1..2 }

  has_one :rsvp, :dependent => :destroy
end

Ответить

class Rsvp < ActiveRecord::Base

  attr_accessible :guests_attributes

  belongs_to :invitation
  has_many   :guests, :dependent => :destroy
  accepts_nested_attributes_for :guests

  validates :invitation_id, :presence => true
end

Гость

class Guest < ActiveRecord::Base

  attr_accessible :name, :email, :phone, :message, :attending_wedding, :attending_bbq, :meal_id

  belongs_to :rsvp
  belongs_to :meal

  email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name,    :presence => true
  validates :email,   :allow_blank => true, :format => { :with => email_regex }
  validates :attending_wedding, :inclusion => {:in => [true, false]}
  validates :attending_bbq, :inclusion => {:in => [true, false]}
  validates :rsvp_id, :presence => true
  validates :meal_id, :presence => true
end

Моя логика заключается в том, что я заполню базу данных приглашениями, и когда гости войдут на сайт, им будет представлена ​​форма RSVP с разделом для каждого гостя (используя form_for в представлении).

Действия new и create в моем rsvps_controller:

def new
    @title = "Edit RSVP"
    @rsvp = current_invitation.build_rsvp
    current_invitation.guest_count.times { @rsvp.guests.build }
    @meals = Meal.all
  end

  def create
    @rsvp = current_invitation.build_rsvp(params[:rsvp])
    if @rsvp.save
      flash[:success] = "RSVP Updated."
      redirect_to :rsvp
    else
      @title = "Edit RSVP"
      @meals = Meal.all
      render 'new'
    end
  end

В нынешнем виде этот код не сохранит RSVP, так как он жалуется, что «RSVP для гостей не может быть пустым». Я понимаю, что это (вероятно) потому, что запись rsvp еще не сохранена в БД, следовательно, еще не имеет идентификатора. Я могу заставить это работать, удалив проверку rsvp_id, но это кажется неправильным — в конце концов, все гостевые записи должны иметь связь с RSVP, поэтому я думаю, что проверка должна остаться. С другой стороны, без проверки ассоциации записей верны, если я смотрю через консоль.

Каков стандартный (идиоматический рельс) способ справиться с этой ситуацией?

Спасибо, Ноэль


person noelob    schedule 31.01.2012    source источник


Ответы (1)


Вы в значительной степени попали в точку, «потому что запись rsvp еще не была сохранена в БД». Ассоциация есть, rsvp_id нет.

Однако вы можете создать собственный валидатор. Что-то типа...

class Guest < ActiveRecord::Base
  ...
  validate :associated_to_rsvp
  ...
private
  def associated_to_rsvp
    self.errors.add(:rsvp, "does not exist.") unless self.rsvp
  end
end
person Azolo    schedule 07.02.2012
comment
Привет Азоло, спасибо за ваш ответ. К сожалению, это не решает проблему. Я получаю ту же ошибку, что и при использовании validates :rsvp_id, :presence => true - person noelob; 22.02.2012