2012-02-15 33 views
109

मैं अपने सिर को inverse_of के आसपास लाने की कोशिश कर रहा हूं और मुझे यह नहीं मिला।inverse_of क्या करता है? यह एसक्यूएल क्या उत्पन्न करता है?

जेनरेटेड एसक्यूएल कैसा दिखता है, अगर कोई है?

inverse_of विकल्प अगर साथ :has_many, :belongs_to, और :has_many_and_belongs_to द्वारा उपयोग किए गए व्यवहार प्रदर्शित करता है?

क्षमा करें अगर यह एक बुनियादी सवाल है।

class Player < ActiveRecord::Base 
    has_many :cards, :inverse_of => :player 
end 

class Card < ActiveRecord::Base 
    belongs_to :player, :inverse_of => :cards 
end 

उत्तर

98

the documentation से, यह :inverse_of विकल्प की तरह लगता है एसक्यूएल प्रश्नों से बचने के लिए, उन्हें पैदा नहीं करने के लिए एक विधि है:

मैं इस उदाहरण देखा। यह एक रिश्ते के माध्यम से इसे फिर से लाने के बजाय पहले से लोड किए गए डेटा का उपयोग करने के लिए ActiveRecord का संकेत है।

उनके उदाहरण:

class Dungeon < ActiveRecord::Base 
    has_many :traps, :inverse_of => :dungeon 
    has_one :evil_wizard, :inverse_of => :dungeon 
end 

class Trap < ActiveRecord::Base 
    belongs_to :dungeon, :inverse_of => :traps 
end 

class EvilWizard < ActiveRecord::Base 
    belongs_to :dungeon, :inverse_of => :evil_wizard 
end 

इस मामले में, dungeon.traps.first.dungeon बुला मूल dungeon वस्तु बजाय लौट जाना एक नया डिफ़ॉल्ट रूप से मामला होगा के रूप में लोड करने की।

+5

क्या आप दस्तावेज़ीकरण में टिप्पणी को समझते हैं: "संबंधित_तो संघों के लिए__nyany व्यस्त संघों को अनदेखा किया जाता है।" और फिर भी डॉक्टर उस सटीक उदाहरण का उपयोग करता है। मुझे यहां क्या समझ नहीं आ रहा है? – dynex

+1

मुझे पूरी तरह से यकीन नहीं है। 'inverse_of' में वास्तव में बहुत अधिक उपयोग नहीं देखा गया है, इसलिए यह एक ऐसा व्यवहार हो सकता है जो बहुत अच्छी तरह परिभाषित नहीं है। मैंने उस सुविधा को इंगित करने के बाद इसका उपयोग करने की कोशिश की है और उसने वास्तव में मेरे लिए कुछ भी उपयोगी नहीं किया है। – tadman

+46

यह मेरे लिए बहुत अजीब बात है, क्योंकि ऐसा लगता है कि आप हमेशा इस व्यवहार को डिफ़ॉल्ट रूप से चाहते हैं, और केवल उपयोग करने की आवश्यकता है: inverse_of जब एसोसिएशन नाम अनुमानित नहीं किया जा सकता है। परिभाषा में असंगतता भी परेशान हैं, लेकिन इससे कुछ मामलों में मुझे मदद मिली है। किसी भी कारण से मुझे इसे हर जगह छूना नहीं चाहिए? – Ibrahim

3

यदि आपके पास दो मॉडल, उपयोगकर्ता और भूमिका के बीच has_many_through संबंध है, और validates_presence of :user_id, :role_id के साथ गैर मौजूदा या अमान्य प्रविष्टियों के विरुद्ध कनेक्टिंग मॉडल असाइनमेंट को सत्यापित करना चाहते हैं, तो यह उपयोगी है। आप अभी भी एक उपयोगकर्ता @user को अपने एसोसिएशन @user.role(params[:role_id]) के साथ उत्पन्न कर सकते हैं ताकि उपयोगकर्ता को सहेजने से असाइनमेंट मॉडल की असफलता न हो।

5

बस हर किसी के लिए एक अद्यतन - हम सिर्फ हमारे ऐप्स में से किसी inverse_of इस्तेमाल किया एक has_many :through संघ के साथ


यह मूल रूप से "मूल" वस्तु उपलब्ध बनाता "बच्चा" वस्तु को

आप रेल 'उदाहरण का उपयोग कर रहे तो अगर:

class Dungeon < ActiveRecord::Base 
    has_many :traps, :inverse_of => :dungeon 
    has_one :evil_wizard, :inverse_of => :dungeon 
end 

class Trap < ActiveRecord::Base 
    belongs_to :dungeon, :inverse_of => :traps 
    validates :id, 
     :presence => { :message => "Dungeon ID Required", :unless => :draft? } 

    private 
    def draft? 
     self.dungeon.draft 
    end 
end 

class EvilWizard < ActiveRecord::Base 
    belongs_to :dungeon, :inverse_of => :evil_wizard 
end 

:inverse_of का उपयोग करते हुए किसी भी आगे एसक्यूएल के बिना प्रदर्शन, आप देखेंगे कि यह का प्रतिलोम है डेटा वस्तु का उपयोग करने की अनुमति देगा प्रश्नों

30

मुझे लगता है कि :inverse_of सबसे अधिक उपयोगी है जब आप संघों कि अभी तक कायम नहीं किया गया है के साथ काम कर रहे हैं। उदा .:

class Project < ActiveRecord::Base 
    has_many :tasks, :inverse_of=>:project 
end 

class Task < ActiveRecord::Base 
    belongs_to :project, :inverse_of=>:tasks 
end 

अब, कंसोल में:

irb> p = Project.new 
=> #<Project id: nil, name: nil, ...> 
irb> t = p.tasks.build 
=> #<Task id: nil, project_id: nil, ...> 
irb> t.project 
=> #<Project id: nil, name: nil, ...> 
बिना

: तर्क inverse_of, t.project शून्य वापसी होगी, क्योंकि यह एक एसक्यूएल क्वेरी से चलाता है और डेटा अभी तक संग्रहीत नहीं है। इनवर्क्स_ओफ तर्कों के साथ, डेटा स्मृति से पुनर्प्राप्त किया जाता है।

+0

मुझे accepts_nested_attributes_for के साथ कोई समस्या थी। डिफ़ॉल्ट रूप से, मौजूदा संबंधित ऑब्जेक्ट्स के लिए केवल नेस्टेड विशेषताएँ दिखाती हैं (क्रिया संपादित करें)। यदि, उदाहरण के लिए, आप 3 ऑब्जेक्ट्स के साथ ऑब्जेक्ट बनाना चाहते हैं, तो आपके पास मॉडल.न्यू (नई एक्शन) और: आपके मॉडल में inverse_of होना चाहिए। –

+0

रेल 4 और बाद में व्यवहार पर सहमति हुई, लेकिन यह v3 में ठीक काम करता था (कुछ बाद के अवतारों को छोड़कर, हालांकि पुराने वाक्यविन्यास v3.2.13 में फिर से काम करता है)। और जॉइन-मॉडल में नोट करें, आईडी की उपस्थिति को मान्य नहीं कर सकता - केवल मॉडल-ऑब्जेक्ट। ऐसा लगता है कि आप v4 'logic' में, इसके लिए आईडी के बिना एक एसोसिएशन प्राप्त कर सकते हैं। – JosephK

+0

बिल्कुल .. ': inverse_of' ने उसी रूप में नए माता-पिता और बाल संस्थाओं को बनाते समय मेरे लिए एक मुद्दा हल किया। –

4

जब हमारे पास has_many के साथ 2 मॉडल हैं और रिश्तों के संबंध में हैं, तो हमेशा सक्रिय_कॉम का उपयोग करना बेहतर होता है जो कि एसोसिएशन के एक ही पक्ष से संबंधित है। इसलिए यदि एक तरफ से एक क्वेरी ट्रिगर हो जाती है, तो यह कैश से कैश और सेवा करेगा यदि यह विपरीत दिशा से ट्रिगर हो जाता है। जो प्रदर्शन में सुधार करता है। रेल 4.1 से, inverse_of स्वचालित रूप से सेट हो जाएगा, अगर हम विदेशी_की का उपयोग करते हैं या कक्षा के नाम में परिवर्तनों को हमें स्पष्ट रूप से सेट करने की आवश्यकता है।

विवरण और उदाहरण के लिए सर्वश्रेष्ठ लेख।

http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations

7

रेल 5.0 और महान के प्रलेखन से।

Guide

द्वि-दिशात्मक संघों

संघों दो अलग अलग मॉडल पर दो दिशाओं में काम करने के लिए, घोषणा की आवश्यकता होती है सामान्य है:

class Author < ApplicationRecord 
    has_many :books 
end 

class Book < ApplicationRecord 
    belongs_to :author 
end 

डिफ़ॉल्ट रूप से, सक्रिय रिकॉर्ड नहीं करता है ' इन एसोसिएशन के बीच कनेक्शन के बारे में नहीं पता।

a = Author.first 
b = a.books.first 
a.first_name == b.author.first_name # => true 
a.first_name = 'Manny' 
a.first_name == b.author.first_name # => false 

यह इसलिए होता है क्योंकि एक और b.author दो अलग-अलग में स्मृति एक ही डेटा का निरूपण कर रहे हैं, और न ही एक स्वचालित रूप से करने के लिए परिवर्तन से ताज़ा किया जाता है: यह एक वस्तु की दो प्रतियां सिंक्रनाइज़ेशन से बाहर हो रही करने के लिए नेतृत्व कर सकते हैं अन्य। inverse_of विकल्प ताकि आप इन संबंधों की यह सूचित कर सकते हैं:: सक्रिय रिकॉर्ड प्रदान करता है

class Author < ApplicationRecord 
    has_many :books, inverse_of: :author 
end 

class Book < ApplicationRecord 
    belongs_to :author, inverse_of: :books 
end 
इन परिवर्तनों के साथ

, सक्रिय रिकॉर्ड केवल लेखक वस्तु की एक प्रति लोड होगा, विसंगतियों को रोकने और अपने आवेदन और अधिक कार्यकुशल बनाने:

वे साथ काम नहीं करते: संघों के माध्यम से

a = Author.first 
b = a.books.first 
a.first_name == b.author.first_name # => true 
a.first_name = 'Manny' 
a.first_name == b.author.first_name # => true 

समर्थन inverse_of लिए कुछ सीमाएं हैं। वे पॉलिमॉर्फिक संघों के साथ काम नहीं करते हैं। वे साथ काम नहीं करते: एसोसिएशन के रूप में।

एसोसिएशन के लिए संबंधित है, has_many व्यस्त संघों को नजरअंदाज कर दिया गया है। प्रत्येक एसोसिएशन स्वचालित रूप से व्यस्त एसोसिएशन को खोजने का प्रयास करेगा और इसे सेट करेगा: inverse_of विकल्प heuristically (एसोसिएशन नाम के आधार पर)। मानक नाम वाले अधिकांश संगठनों का समर्थन किया जाएगा।हालांकि, संघों कि इन विकल्पों को शामिल उनके प्रतिलोम स्वचालित रूप से सेट नहीं किया है:

  • : स्थिति
  • : बहुरूपी
  • :
  • के माध्यम से foreign_key
+0

मैं रेल 5 का उपयोग कर रहा हूं, और या तो आप 'inverse_of' जोड़ते हैं या नहीं,' a.first_name == b.author.first_name' के परिणाम हमेशा ट्यूर होते हैं। –

-1

कृपया एक बार देख ले 2 दो उपयोगी संसाधन

और याद रखें inverse_of की कुछ सीमाएं:

साथ काम नहीं करता: संघों के माध्यम से।

इसके साथ काम नहीं करता है: पॉलिमॉर्फिक संघ।

एसोसिएशन के लिए has_many व्यस्त संघों को अनदेखा कर दिया गया है।

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