2016-12-01 154 views
1

唯一性驗證這是當前的代碼,我有:上嵌套屬性

class Parent < ActiveRecord::Base 
    has_many :children 
end 

class Child < ActiveRecord::Base 
    belongs_to :parent 

    validates :name, :presence => true, :uniqueness => { :scope => :parent_id, :case_sensitive => false } 
end 

我的問題是,當我做的:創建任何子只有

Parent.create(params) 

唯一性驗證檢查之前。它不會在每個孩子被添加後再次檢查。有沒有辦法在每個被添加的孩子之間調用驗證?

如果沒有ActiveRecord的方式來做到這一點,我會寫我自己的驗證方法在父。但我想知道是否有一種「更容易」的方式。

這是日誌:

Child Exists (0.4ms) 
Child Exists (0.2ms) 
Parent Exists (0.3ms) 
SQL (0.6ms) INSERT INTO "parents" 
SQL (0.3ms) INSERT INTO "children" 
SQL (0.3ms) INSERT INTO "children" 
+0

實際上,它在每個「Child」實例創建之前執行驗證。假如你已經有保存在數據庫中的名爲「foo」的孩子,你將沒有機會保存另一個具有相同名字的記錄(作用域爲'parent_id')。在數據庫級別添加uniq索引是一種很好的做法。 –

+0

我已經試過這個,我更新了OP來顯示日誌。 我刪除了所有額外的東西,但您可以看到在添加任何子項之前,驗證會一次全部檢查。所以如果你同時創建兩個孩子,它會通過驗證。是的,我可以在數據庫級別添加uniq索引,但我想要一致的錯誤消息。 – Dragonfly

回答

1

你僅僅指剛試試這個。東西看起來像

# app/validators/products_name_uniqueness_validator.rb 
class ProductsNameUniquenessValidator < ActiveModel::EachValidator 
    def validate_each(record, attribute, value) 
    record.errors[attribute] << "Products names must be unique" unless value.map(&:name).uniq.size == value.size 
    end 
end 

# app/models/shop.rb 
class Shop < ActiveRecord::Base 
    validates :products, :products_name_uniqueness => true 
end 
+0

有沒有辦法做到這一點,而不創建另一個文件?我可以將該方法添加到Shop類嗎? –