我正在为省份和国家/地区创建Rails迁移。我们的想法是,对于每个国家/地区,我们不能允许多个同名的省份。
我的create_provinces迁移是:
class CreateProvinces < ActiveRecord::Migration
def change
create_table :provinces do |t|
t.string :name
t.references :country, index: true, foreign_key: true
end
end
我的country.rb是:
class Country < ActiveRecord::Base
has_many :provinces, :uniq => true
end
我的省份.rb是:
class Province < ActiveRecord::Base
belongs_to :country
private
validates_presence_of :country
validate :canada_or_usa?
validates_presence_of :name
validate :in_right_country?
validates_associated :country
def canada_or_usa?
errors.add(:country, "can only add province for Canada or the United States") unless (country.name == "Canada" || country.name == "United States")
end
def in_right_country?
if country.name == "Canada"
errors.add(:name, "Name must be the name of a province in Canada") unless (DataHelper::canada_provinces_with_caption.include? name)
end
if country.name == "United States"
errors.add(:name, "Name must be the name of a province in the United States") unless (DataHelper::usa_provinces_with_caption.include? name)
end
end
end
在country.rb中使用:uniq => true
,我收到的错误是:uniq不是已知密钥。请注意,我也没有按照其他问题使用through
。有没有办法确保每个国家都有两个同名的省份?
答案 0 :(得分:0)
在您的省份模型中,您需要添加
validates uniqueness: { scope: :country }
这将允许您拥有相同名称但不在一个国家/地区内的省份。
答案 1 :(得分:0)
首先,:uniq => true
除了伪造数据的唯一性外什么都不做。当按some_country_instance.provinces
获取省份时,会在查询中添加DISTINCT子句。有了它,您可以为一个国家/地区插入两个具有相同名称的省份。我建议你删除它。你不会被欺骗。
您实际应该做的是将对[country_id,province_name]列添加为表省的主键。
您可以使用以下代码进行迁移:
...
def change
add_index :provinces, [:country_id, :name], unique: true
end
...
我假设您的表格provinces
有country_id
作为countries
的外键列,name
列保留省份&#39}名。
要验证模型中的数据,我建议:
...
validates :name, uniqueness: { scope: :country_id,
message: "My world my rules. Country cannot have provinces with same name." }
...
通过这种方式,您只需几行代码并充分利用Rails框架即可优雅地完成工作。
答案 2 :(得分:0)
正确的语法是
has_many :provinces, -> { uniq }
然而,这只是定义关联而不是实际验证数据库的输入。如果你看看sql,你会看到类似的东西。
Select distinct provinces from provinces where provinces.country_id = '';