我是Rails和Ruby的新手。在我看来,我有2个单选按钮,询问这个人是否是美国居民。如果是,则显示状态选择。如果不是,则显示国家选择。
如果该人是美国居民,我试图验证是否已选定州。
如何创建验证并从addresses_attributes中访问状态?
这是我的模特:
class Person < ActiveRecord::Base
has_many :addresses, :as => :addressable
has_one :user
accepts_nested_attributes_for :user, :allow_destroy => true
accepts_nested_attributes_for :addresses
attr_accessor :resident
attr_accessible :campaign_id,
:first_name,
:last_name,
:user_attributes,
:addresses_attributes,
:resident
validates :first_name, :presence => true
validates :last_name, :presence => true
validates_presence_of :resident, :message => "must be selected"
end
这些是发送的相关参数:
"resident"=>"true",
"addresses_attributes"=>{"0"=>{"country_code"=>"",
"state"=>""}}
答案 0 :(得分:1)
您需要自定义验证方法。
validate :check_state_presence
def check_state_presence
if self.resident && !self.addresses.state.present?
self.errors[:base] << "You need to Select State if you are a US resident."
end
end
答案 1 :(得分:1)
您可以使用validates_inclusion_of对其进行排序。
Ruby API说:
如果要验证是否存在布尔字段(实际值为true且&gt;为false),则需要使用validates_inclusion_of:field_name,:in =&gt; [true,false]。
这是由于Object#blank的方式?处理布尔值:false.blank? #=&gt;真。
答案 2 :(得分:0)
+1给@VelLes帮助我指向正确的方向。我正在回答我自己的问题,因为我必须更改@VelLes示例以使其工作,我希望其他人看到完整的解决方案。
由于我使用attr_accessor作为虚拟属性,当真/假值来自单选按钮时,它将被存储为字符串。因此,如果self.resident
=“false”,它将被评估为true。
您可以执行self.resident == 'false'
或转换为布尔值并添加新的self.resident?方法。我选择了后者。
布尔转换来自this blog post,添加到config / initializers
中的文件class String
def to_bool
return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
end
end
我的最终代码是:
validate :check_state_presence
def resident?
resident.to_bool
end
def check_state_presence
if self.resident? && !self.addresses[0].state.present?
#the inline version of the error message
self.addresses[0].errors.add(:state, "must be selected")
end
end
如果有更好的'轨道'方式,请告诉我!