2010-05-23 20 views
31

क्या ActiveRecord एसोसिएशन द्वारा प्रदान की गई विधियों में से एक को ओवरराइड करने का कोई तरीका है?रेल: ActiveRecord एसोसिएशन विधि ओवरराइडिंग

कहते हैं, उदाहरण के लिए मैं निम्नलिखित ठेठ बहुरूपी has_many है: संघ के माध्यम से:

class Story < ActiveRecord::Base 
    has_many :taggings, :as => :taggable 
    has_many :tags, :through => :taggings, :order => :name 
end 


class Tag < ActiveRecord::Base 
    has_many :taggings, :dependent => :destroy 
    has_many :stories, :through => :taggings, :source => :taggable, :source_type => "Story" 
end 

कि आप जानते ही इस टैग की तरह कहानी मॉडल के लिए संबद्ध तरीकों की एक पूरी धसान कहते हैं, टैग < <, टैग = , tag.empty ?, आदि

मैं इन तरीकों में से किसी एक को ओवरराइड करने के बारे में कैसे जा सकता हूं? विशेष रूप से टैग < < विधि। सामान्य वर्ग विधियों को ओवरराइड करना बहुत आसान है, लेकिन मुझे एसोसिएशन विधियों को ओवरराइड करने के बारे में कोई जानकारी नहीं मिल रही है।

def tags<< *new_tags 
    #do stuff 
end 

एक वाक्यविन्यास त्रुटि उत्पन्न करता है जब इसे कहा जाता है तो यह स्पष्ट रूप से इतना आसान नहीं है।

+2

आप इसके लिए क्या करने की कोशिश कर रहे हैं? यह अन्य ActiveRecord कार्यक्षमता को तोड़ने को समाप्त कर सकता है, और आप जो भी कोशिश कर रहे हैं उसे करने का शायद एक बेहतर तरीका है – Gareth

उत्तर

53

आप has_many साथ ब्लॉक का उपयोग कर सकते तरीकों के साथ अपने संबंध का विस्तार करने के बनाता है हो सकता है। टिप्पणी देखें "अपने संगठनों को बढ़ाने के लिए ब्लॉक का प्रयोग करें" here
मौजूदा विधियों को ओवरराइड करना भी काम करता है, यह नहीं पता कि यह एक अच्छा विचार है या नहीं।

has_many :tags, :through => :taggings, :order => :name do 
    def << (value) 
     "overriden" #your code here 
     super value 
    end  
    end 
+0

बेशक! उस बारे में भूल गए। यह संभवतः ऐसा करने का सबसे अच्छा तरीका है जो आप कर रहे हैं। –

+1

और आप मूल विधि को कैसे कॉल करेंगे? (मैं बिल्ड विधि को ओवरराइड करना चाहता हूं, कुछ डिफ़ॉल्ट जोड़ना चाहता हूं और फिर मूल को कॉल करना चाहता हूं) –

+1

@EranKampf 'सुपर' चाल नहीं करता है? – lulalala

0

मुझे लगता है कि आप हस्ताक्षर के लिए def tags.<<(*new_tags) चाहते हैं, जो काम करना चाहिए, या निम्नलिखित समकक्ष और थोड़ा क्लीनर है यदि आपको कई विधियों को ओवरराइड करने की आवश्यकता है।

class << tags 
    def <<(*new_tags) 
    # rawr! 
    end 
end 
+0

मुझे नहीं लगता कि इनमें से कोई भी काम करेगा। ऐसा लगता है कि आप जो सुझाव दे रहे हैं वह 'टैग' विधि द्वारा लौटाए गए मूल्य के Eigenclass को बढ़ाने का प्रयास कर रहा है। –

+0

यह 'टैग' द्वारा जो कुछ भी लौटाया गया है, उसके eigenclass के भीतर एक विधि को परिभाषित कर रहा है, जो शायद एक सरणी है। इसका सरणी में एक नया इंस्टेंस विधि जोड़ने का प्रभाव है, जो कि मैं मूल प्रश्न पूछने के लिए समझ गया था। 'विस्तार 'का रूबी में एक विशिष्ट अर्थ है और यह नहीं है कि यहां क्या हो रहा है। – x1a4

+0

आप सही हैं, यह वही है जो यह कर रहा है। मुझे लगता है कि मुझे समझ में नहीं आया कि आप कहां कोड डालने का सुझाव दे रहे थे। वैसे भी, मुझे लगता है कि मैंने थोड़ा और अधिक संदर्भ के साथ, एक ही चीज़ का उत्तर दिया। –

0

आप एक वस्तु है जो एक << विधि है वापस जाने के लिए टैग विधि को परिभाषित करना होगा।

आप इसे ऐसा कर सकते हैं, लेकिन मैं वास्तव में इसकी अनुशंसा नहीं करता। आप अपने मॉडल में बस एक विधि जोड़ना बेहतर होगा जो कि ActiveRecord उपयोगों को प्रतिस्थापित करने की कोशिश करने से आप जो चाहते हैं वह करता है।

यह अनिवार्य रूप से डिफ़ॉल्ट tags विधि को < < विधि को परिणामी ऑब्जेक्ट में जोड़ता है और उस ऑब्जेक्ट को देता है। इसमें कुछ समय संसाधन गहन है क्योंकि यह एक नई विधि हर बार जब आप चलाने यह

def tags_with_append 
    collection = tags_without_append 
    def collection.<< (*arguments) 
    ... 
    end 
    collection 
end 
# defines the method 'tags' by aliasing 'tags_with_append' 
alias_method_chain :tags, :append 
0

मैं जिस विधि का उपयोग करता हूं वह एसोसिएशन का विस्तार करना है। आप जिस तरह से मैं संभाल देख सकते हैं 'मात्रा' यहाँ विशेषताओं: https://gist.github.com/1399762

यह मूल रूप से अनुमति देता है तुम सिर्फ

has_many : tags, :through => : taggings, extend => QuantityAssociation 

करने के लिए जानते हुए भी अपने तरीके इसकी मुश्किल पता करने के लिए यदि आप अधिभावी द्वारा हासिल करने की उम्मीद वास्तव में क्या बिना वही कर सकता था

0

यह आपके मामले में सहायक नहीं हो सकता है, लेकिन यह जांच कर रहे अन्य लोगों के लिए उपयोगी हो सकता है।

एसोसिएशन कॉलबैक: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

डॉक्स से उदाहरण:

class Project 
    has_and_belongs_to_many :developers, :after_add => :evaluate_velocity 

    def evaluate_velocity(developer) 
    ... 
    end 
end 

भी देखें एसोसिएशन एक्सटेंशन:

class Account < ActiveRecord::Base 
    has_many :people do 
    def find_or_create_by_name(name) 
     first_name, last_name = name.split(" ", 2) 
     find_or_create_by_first_name_and_last_name(first_name, last_name) 
    end 
    end 
end 

person = Account.first.people.find_or_create_by_name("David Heinemeier Hansson") 
person.first_name # => "David" 
person.last_name # => "Heinemeier Hansson" 
17

आप मॉडल रेल 3.2 में ही उपयोग करने के लिए चाहते हैं तो आप चाहिए proxy_association.owner

का उपयोग करें

उदाहरण:

class Author < ActiveRecord::Base 
    has_many :books do 
    def << (book) 
     proxy_association.owner.add_book(book) 
    end 
    end 

    def add_book (book) 
    # do your thing here. 
    end 
end 

documentation

+0

नहीं कहा जाता है, यह रेलवे 5.1 – coconup

+0

@coconup में अभी भी मामला है, यह रेल में मेरे लिए काम नहीं करता है 5.1 - ओवरराइडिंग << विधि बिल्कुल नहीं कहा जाता है :-( – dowi

0

Rails guides सीधे जोड़ा तरीकों अधिभावी के बारे में दस्तावेज देखें।

<< ओवरराइडिंग के साथ ओपी का मुद्दा शायद इसका एकमात्र अपवाद है, जिसके लिए the top answer का पालन करें। लेकिन यह has_one के = असाइनमेंट विधि या गेटर विधियों के लिए काम नहीं करेगा।

संबंधित मुद्दे