2012-08-14 95 views
14

對,所以我有一個多態關聯,允許不同的對象類型被收藏。所以一個人可以喜歡一個產品,或一個人,或其他什麼。我想要做的是防止有人在最喜歡的模型中使用驗證唯一性來複制最愛。驗證多態關聯模型中的作用域唯一性

class Favorite < ActiveRecord::Base 
belongs_to :favoritable, :polymorphic => true 
belongs_to :user 

attr_accessible :user 

validates_presence_of :user 
validates :user_id, :uniqueness => { :scope => [:favoritable_type, :favoritable_id] } 
end 

驗證似乎是工作,但無論出於何種原因新寵行仍然與USER_ID創建時,試圖複製的條目。

enter image description here

有沒有辦法制止這種初始救?

看來,Rails正在創建數據庫條目,然後與favoritable_id和favoritable_type更新,如下所示:

SQL (28.3ms) INSERT INTO "favorites" ("created_at", "favoritable_id", "favoritable_type", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Tue, 14 Aug 2012 10:26:31 UTC +00:00], ["favoritable_id", nil], ["favoritable_type", nil], ["updated_at", Tue, 14 Aug 2012 10:26:31 UTC +00:00], ["user_id", 23]] 
    (7.8ms) COMMIT 
    (0.1ms) BEGIN 
    Favorite Exists (0.3ms) SELECT 1 AS one FROM "favorites" WHERE ("favorites"."user_id" = 23 AND "favorites"."id" != 123 AND "favorites"."favoritable_type" = 'Style' AND "favorites"."favoritable_id" = 29) LIMIT 1 
    (0.2ms) UPDATE "favorites" SET "favoritable_id" = 29, "favoritable_type" = 'Style', "updated_at" = '2012-08-14 10:26:31.943937' WHERE "favorites"."id" = 123 
    (6.7ms) COMMIT 
    (0.1ms) BEGIN 
+0

亞伯蘭:你有沒有想出解決辦法? – MAckerman 2014-03-20 17:55:39

回答

21

如果你仔細觀察,你能找到的唯一性驗證就好了工作:)

validates :user_id, :uniqueness => { :scope => [:favoritable_type, :favoritable_id] } 

看你添加的數據圖像。你可以發現第二條記錄沒有favouritable,而第一條有不同,因此2條記錄是uniq,它不是uniqueness的問題,但是它與你的邏輯差距很大。

如果嚴格想要避免第二項則保持favouritable爲必填字段

validates :favoritable_type, :favoritable_id, :presence => true 
+0

對不起,這個結果存在最愛存在(0.4ms)SELECT 1 AS one FROM「favorites」WHERE(「favorites」。「user_id」= 36 AND「favorites」。「favoritable_type」IS NULL AND「favorites」。「favoritable_id」IS NULL )LIMIT 1 (0.1毫秒)ROLLBACK 完成在243ms 的ActiveRecord :: RecordInvalid 500內部服務器錯誤(驗證失敗:Favoritable類型不能爲空,Favoritable不能爲空): – Abram 2012-08-14 11:12:29

+1

您還可以添加獨特性通過遷移限制你的表格: 'add_index(:favorite,[:user_id,:favoritable_type,:favoritable_id],:unique => true,:name =>'allowed_one_favorite')' – Darme 2014-07-03 10:02:34

0

你經歷了類似的帖子

Rails 3 uniqueness validation with scope on polymorphic table

似乎add_index確實很重要。

+0

真棒,是的。在允許的情況下,幾分鐘後會給你打勾。 – Abram 2012-08-14 10:39:46

+0

Argh。不,我收回。它沒有工作。我試過add_index(:favorites,[:user_id,:favoritable_id,:favoritable_type],:unique => true,:name =>'cannot_duplicate_favorite') – Abram 2012-08-14 10:42:25

+0

正如在參考文獻中提到的那樣 - 如果你已經有了這個模型,通過SQL手動。通常索引將在遷移時添加。檢查一次。 – pdpMathi 2012-08-14 10:47:28

5
class Favorite < ActiveRecord::Base 

    belongs_to :user 
    belongs_to :favoritable, polymorphic: true 

    validates :user_id, :favoritable_id, presence: true, 
    numericality: { only_integer: true } 

    validates :favoritable_type, presence: true, 
    inclusion: { 
     in: %w(FirstModelName SecondModelName), 
     message: "%{value} is not a valid" 
    } 

    validates :user_id, uniqueness: { scope: [ :favoritable_type, :favoritable_id ] } 
end