ruby-on-rails - 如何根据父对象的状态验证嵌套模型对象?

标签 ruby-on-rails ruby ruby-on-rails-3 validation activerecord

我正在用 Rails 写一个向导表单;例如一个模型对象的多个输入页面。

我的方法的基础是 Ryan Bates 的 Multistep form railscast 中描述的方法:http://railscasts.com/episodes/217-multistep-forms (如果有人想知道下面某些代码背后的原因)。

这里关注的对象是“Participant”,它有一个“Address”

我的问题是,当用户试图通过地址输入屏幕时,我只想验证嵌套对象(地址)。目前,这是通过参与者模型上名为“current_step”的属性进行跟踪的

所以我有一个参与者:

class Participant < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address
  validates_presence_of :first_name, :last_name, :if => self.current_step == "name"
  ...
  def steps = %w[ name address confirm ] # the steps the wizard will follow
end

还有一个地址:

class Address < ActiveRecord::Base
  belongs_to :participant
  validates_presence_of :address1, :state, :suburb, :postcode #, :if => participant.current_step == "address"
end

此方法的原理是在向导的每个步骤的 Controller (未显示)上调用“创建”操作,并且在处理每个步骤时它仅验证模型的一个子集。

目前,当我完成第一个屏幕(“姓名”)并尝试进入地址步骤时,地址验证被触发,我被送回“姓名”屏幕,并显示空白地址详细信息的验证错误.

所以我在这里尝试了多种方法,最后一部分是上面显示的地址验证的注释掉条件——我发现这不起作用,因为我只构建了参与者->地址对象,但没有拯救他们。因此 @participant.address 为我提供了地址对象,但是 @participant.address.participant 为空,因为地址还没有用于查找其父对象的 participant_id 外键。

我挣扎的原因似乎是包含 super 方便的 accepts_nested_attributes_for 方法。我期望使用 validates_associated 来进行验证,但我看到 accepts_nested_attributes_for 标签既可以很好地传播表单参数来创建嵌套模型对象,又可以确保 participant#valid? 方法在所有情况下调用地址验证。

所以我的难题是如何根据参与者中的 current_step 参数,最好地使用 participant#valid? 方法来验证部分完整的模型?

编辑 - 更新以删除额外信息,并提炼出核心问题

最佳答案

在您的 Address 模型上添加一个虚拟属性:

class Address < ActiveRecord::Base
  belongs_to :participant
  attr_accessor :skip_validation
  validates_presence_of :address1, :state, :suburb, :postcode, 
                           :unless => :skip_validation 
end

设置current_step时,在地址对象上设置虚拟属性。

class Participant < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address
  attr_accessor :current_step
  validates_presence_of :first_name, :last_name, 
                         :if => lambda {|r| r.current_step == "name"}


  def current_step=(value)
    unless (value == "address")
      address.skip_validation = true
    end    
    @current_step = value 
  end    
end

关于ruby-on-rails - 如何根据父对象的状态验证嵌套模型对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5975047/

相关文章:

ruby-on-rails - 如何隐藏 submit_tag 按钮

ruby-on-rails - 使用 button_to 更新多个值 - Rails 4

ruby - 职位总数?

ruby - 在类上动态定义单例方法,以便与子类正确评估

javascript - 在javascript中加载动态CSS

ruby-on-rails - 使用 file_field 时 Railsnested_form_for 不起作用

jquery - Rails 3 使用链接呈现不同的部分

ruby-on-rails - rails :before_save upcase private method

sql - updated_at 和 creatd_at 之间的差异的事件记录子集

javascript - Summernote 字体系列和颜色不起作用