Rails 3 - 创建具有嵌套属性的资源的正确方法是什么?

时间:2012-01-31 20:38:47

标签: ruby-on-rails ruby-on-rails-3 model idiomatic

我正在建立一个婚礼网站,允许访客使用邀请码登录并在线回复。我的模型如下:

邀请

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

RSVP

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)。

我的rsvps_controller中的new和create动作是:

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记录尚未保存到数据库,因此还没有ID。我可以通过删除rsvp_id上的验证来解决这个问题,但这感觉不对 - 毕竟,所有访客记录应该与RSVP有关联,所以我认为验证应该保留。另一方面,如果没有验证,如果我通过控制台查看记录关联是正确的。

处理这种情况的标准(惯用轨道)方式是什么?

谢谢, 诺尔

1 个答案:

答案 0 :(得分:0)

你几乎击中头部“因为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