0

我是 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"=>""}}
4

3 回答 3

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 
于 2012-04-03T23:55:11.683 回答
1

您可以改用 validates_inclusion_of 对其进行排序。

Ruby API 说:

如果要验证布尔字段的存在(其中真实值为 true 和 >false),您将需要使用 validates_inclusion_of :field_name, :in => [true, false]。

这是由于 Object#blank? 处理布尔值:false.blank? # => 真的。

于 2012-06-07T02:28:31.647 回答
0

向@VelLes +1 以帮助我指出正确的方向。我正在回答我自己的问题,因为我必须稍微更改@VelLes 示例才能使其正常工作,并且我希望其他人看到完整的解决方案。

由于我使用 attr_accessor 作为虚拟属性,当真/假值来自单选按钮时,它会存储为字符串。因此,如果self.resident= "false",它将被评估为 true。

您可以执行self.resident == 'false'或转换为布尔值并添加新的 self.resident?方法。我选择了后者。

布尔转换来自此博客文章,添加到 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 

请让我知道是否有更好的“rails”方法来做到这一点!

于 2012-04-04T15:48:25.613 回答