【问题标题】:Rails 3 - What is the correct way to create a resource that has nested attributes?Rails 3 - 创建具有嵌套属性的资源的正确方法是什么?
【发布时间】:2012-01-31 20:38:46
【问题描述】:

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

邀请

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

我的 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,因为它会抱怨“Guests rsvp can't be blank”。我知道这是(可能)因为 rsvp 记录尚未保存到数据库中,因此还没有 ID。我可以通过删除 rsvp_id 上的验证来使其工作,但这感觉不对 - 毕竟,所有访客记录应该与 RSVP 有关联,所以我认为验证应该保留。另一方面,在没有验证的情况下,如果我通过控制台查看,记录关联是正确的。

处理这种情况的标准(惯用的rails)方法是什么?

谢谢, 诺埃尔

【问题讨论】:

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


    【解决方案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
    

    【讨论】:

    • 您好 Azolo,感谢您的回答。不幸的是,它并不能解决问题。我得到与使用 validates :rsvp_id, :presence =&gt; true 时相同的错误