2012-08-14 9 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

वहाँ इस प्रारंभिक बचाने को रोकने के लिए कोई तरीका है?

ऐसा लगता है कि रेल डीबी प्रविष्टि बनाने और फिर 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

उत्तर

21

तुम करीब से आपको लगता है कि विशिष्टता मान्यता पा सकते हैं दिखाई देती है तो बस अच्छा काम :) डेटा छवि आपके द्वारा जोड़े पर

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

देखो। छवि के अंदर आप यह पता लगा सकते हैं कि दूसरे रिकॉर्ड में favouritable नहीं है, जबकि पहले अलग है इसलिए 2 रिकॉर्ड यूनिक हैं और uniqueness के साथ यह समस्या नहीं है लेकिन यह आपका तार्किक अंतर है।

आप सख्ती से दूसरी प्रविष्टि से बचना चाहते थे तो रख favouritable अनिवार्य रूप क्षेत्र

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

क्षमा करें इस परिणाम में पसंदीदा Exists (0.4ms) SELECT 1 "पसंदीदा" से एक के रूप में चुनें ("पसंदीदा"। "User_id" = 36 और "पसंदीदा"। "Favoritable_type" पूर्ण और "पसंदीदा" है। "Favoritable_id" IS NULL) सीमा 1 (0.1ms) ROLLBACK पूरे 243ms ActiveRecord :: RecordInvalid में 500 आंतरिक सर्वर त्रुटि (सत्यापन विफल: Favoritable प्रकार खाली नहीं हो सकता, Favoritable खाली नहीं हो सकता): – Abram

+1

तुम भी एक विशिष्टता जोड़ सकता है माइग्रेशन के माध्यम से अपनी तालिका में बाधा: 'add_index (: पसंदीदा, [: user_id,: favoritable_type,: favoritable_id],: unique => true,: name => 'allow_one_favorite')' – Darme

0

आप समान पद

Rails 3 uniqueness validation with scope on polymorphic table

ऐसा लगता है के माध्यम से जाना था कि add_index मायने रखता है।

+0

बहुत बढ़िया हाँ, उसने ऐसा किया। अनुमति मिलने पर आपको कुछ मिनटों में टिक देगा। – Abram

+0

अरग। नहीं, मैं उसे वापस लेता हूं। यह काम नहीं किया। मैंने add_index (: पसंदीदा, [: user_id,: favoritable_id,: favoritable_type],: unique => true,: name => 'cannot_duplicate_favorite') – Abram

+0

संदर्भ में उल्लिखित - यदि आपके पास पहले से ही मॉडल है तो आपको इंडेक्स करने की आवश्यकता है मैन्युअल रूप से एसक्यूएल द्वारा। आमतौर पर माइग्रेशन माइग्रेशन के समय जोड़ा जाएगा। एक बार जांचें। – pdpMathi

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 
संबंधित मुद्दे