2016-07-20 24 views
0

我正在爲省和國家創建Rails遷移。這個想法是,對於每個國家,我們不能允許一個以上的同名省份。
我create_provinces遷移:has_many on Rails遷移的唯一性(不通過)

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 

我province.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

首先,:uniq => true什麼都不做,只是假冒你的數據的唯一性。在通過some_country_instance.provinces獲得省份時,在查詢中添加了DISTINCT子句。有了這個,你可以爲一個國家插入兩個同名的省份。我建議你刪除它。你不會想被欺騙。

你實際上應該做的是添加一對[country_id,province_name]列作爲你的表省份的主鍵。

可以完成與此代碼遷移:

... 
def change 
    add_index :provinces, [:country_id, :name], unique: true 
end 
... 

我假設你的表provincescountry_id作爲外鍵列countries,並name列保存省份的名字。

到模型中的我建議驗證數據:

... 
validates :name, uniqueness: { scope: :country_id, 
      message: "My world my rules. Country cannot have provinces with same name." } 
... 

有了,你會用優雅的幾行代碼,並採取Rails框架的充分利用完成你的工作。

0

在你省模型,你需要添加

validates uniqueness: { scope: :country } 

這將讓你有相同的名稱,但沒有任何一個國家內的省份。

0

正確的語法是

has_many :provinces, -> { uniq } 

然而,這僅僅是定義的關聯,而不是實際驗證輸入到數據庫。如果你看看sql,你會看到類似的東西。

Select distinct provinces from provinces where provinces.country_id = '';