Rails 4.模型中的国家和地区/州验证

时间:2014-07-31 17:33:50

标签: ruby-on-rails validation ruby-on-rails-4 model

我有一张表User

create_table :users  do |t|
   t.string :first_name
   t.string :last_name
   t.string :country
   t.string :region
   t.string :city

   t.timestamps
end

我需要验证国家和地区,还要检查区域是否属于国家/地区。 我使用gem countries进行国家验证。

#user.rb

class User < ActiveRecord::Base

  validates_inclusion_of :country, in:Country.all.map(&:pop), :message => "wrong country format"

end

如何对区域&#39;进行验证?并检查区域是否属于国家

更新

使用@ engineersmnky的建议

#user.rb

  validates :country, :region, presence: true
  validate :location

  def location
      current_country = Country[country]
      if current_country
         errors.add(:region, "incorrect state for country #{current_country.name}.") unless current_country.map{ |k,v| v["name"]}.include?(region)
      else
         errors.add(:country, "must be a 2 character country representation (ISO 3166-1).")
      end
  end

在控制台中测试:

2.1.2 :001 > u = User.new(country:"US", region:"SomeState")
 => #<User id: nil, first_name: nil, last_name: nil, country: "US", region: "SomeRegion", city: nil, address: nil, zip: nil, phone: nil, company: nil, created_at: nil, updated_at: nil>
2.1.2 :002 > u.valid?
NoMethodError: undefined method `map' for #<Country:0x007fefb16dd140>

哪里出错?或者我理解错误:(

1 个答案:

答案 0 :(得分:3)

已从我之前的帖子Here移出

虽然现在我按区域看到你的意思是状态

你也可以这样做

#optionally in:lambda{|user| Country[user.country].states.map{ |k,v| v["name"]}}
#for named states see below for further explanation

validate_inclusion_of :region, in:lambda{ |user| Country[user.country].states.keys}, if: lambda{ |user| Country[user.country]}

对于国家和地区/州,您可以像这样同时验证两者。

validates :country, :region, presence: true
validate :location_by_country


def location_by_country
  current_country = Country[country]
  if current_country
    #this will work for short codes like "CA" or "01" etc.
    #for named regions use:
    #   current_country.states.map{ |k,v| v["name"]}.include?(region)
    #which would work for "California" Or "Lusaka"(it's in Zambia learn something new every day)
    #for Either/Or use:
    #   current_country.states.map{|k,v| [k,v["name"]]}.flatten
    #this will match "California" OR "CA"

    errors.add(:region, "incorrect region for country #{current_country.name}.") unless current_country.states.keys.include?(region)
  else
    #optionally you could add an error here for :region as well 
    #since it can't find the country

    errors.add(:country, "has wrong country format")
  end
end