रेल एक विशेषता से अधिक find_or_create_by?


202

Find -or_create_by नामक सक्रिय-रिकॉर्ड में एक आसान गतिशील विशेषता है:

Model.find_or_create_by_<attribute>(:<attribute> => "")

लेकिन क्या होगा यदि मुझे एक से अधिक विशेषताओं के द्वारा___ को खोजने की आवश्यकता है?

मान लें कि मेरे पास समूह और सदस्य के बीच M: M संबंध के लिए एक मॉडल है जिसे GroupMember कहा जाता है। मेरे पास ऐसे कई उदाहरण हो सकते हैं जहां सदस्य_आईडी = 4, लेकिन मैं कभी भी एक से अधिक उदाहरण नहीं चाहता हूं जहां सदस्य_आईडी = 4 और समूह_आईडी = 7. मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या ऐसा कुछ करना संभव है:

GroupMember.find_or_create(:member_id => 4, :group_id => 7)

मुझे लगता है कि इसे संभालने के बेहतर तरीके हो सकते हैं, लेकिन मुझे find_or_create के विचार की सुविधा पसंद है।

जवाबों:


464

एकाधिक विशेषताओं को एक के साथ जोड़ा जा सकता है and:

GroupMember.find_or_create_by_member_id_and_group_id(4, 7)

( find_or_initialize_byयदि आप रिकॉर्ड को तुरंत सहेजना नहीं चाहते हैं तो उपयोग करें )

संपादित करें: उपरोक्त विधि रेल 4 में पदावनत है। इसे करने का नया तरीका होगा:

GroupMember.where(:member_id => 4, :group_id => 7).first_or_create

तथा

GroupMember.where(:member_id => 4, :group_id => 7).first_or_initialize

संपादित करें 2: इन सभी को केवल विशिष्ट विशेषता वाले रेल के बाहर फैक्टर नहीं किया गया था।

https://github.com/rails/rails/blob/4-2-stable/guides/source/active_record_querying.md

उदाहरण

GroupMember.find_or_create_by_member_id_and_group_id(4, 7)

बन गया

GroupMember.find_or_create_by(member_id: 4, group_id: 7)

आपको github.com/seamusabshere/upsert भी पसंद आ सकता है - पहला तर्क उन विशेषताओं का हैश है जो रिकॉर्ड खोजने या बनाने के लिए उपयोग किया जाता है
सीमस

1
यह नोट करने में मददगार है कि नए () के बजाय कॉल को इनिशियलाइज़ करें () जो पहले कहा जा सकता है
सुमित बिष्ट

क्या कोई इस उपयोग का उदाहरण दे सकता है? मैं इसके प्लेसमेंट और कॉलिंग से परिचित नहीं हूं।
6 फीट डैन

मैंने रेल 3 कोड को हटा दिया, क्योंकि बहुत से लोग अभी तक रेल 4 का उपयोग नहीं कर रहे हैं।
काइल हिरोनिमस

बस जोड़ने के लिए: find_or_create_by _ * () फ़ंक्शन को रेल 4 में पदावनत किया गया है, हालांकि find_or_create_by () नहीं है। Find_or_create_by () का उपयोग करना ठीक है। उस कमिट की जाँच करें जहाँ यह github.com/rails/rails/commit/… और उपयोग के लिए आधिकारिक रेल 4.2 प्रलेखन जोड़ा गया था : guide.rubyonrails.org/v4.2.0/…
CodeExpress

33

किसी और के लिए जो इस धागे को ठोकर मारता है, लेकिन उन विशेषताओं के साथ एक ऑब्जेक्ट ढूंढना या बनाना है जो परिस्थितियों के आधार पर बदल सकते हैं, अपने मॉडल में निम्न विधि जोड़ें:

# Return the first object which matches the attributes hash
# - or -
# Create new object with the given attributes
#
def self.find_or_create(attributes)
  Model.where(attributes).first || Model.create(attributes)
end

ऑप्टिमाइज़ेशन टिप: आप जो भी समाधान चुनते हैं, उसकी परवाह किए बिना, उन विशेषताओं के लिए अनुक्रमणिका जोड़ने पर विचार करें जिन्हें आप सबसे अधिक बार क्वेरी कर रहे हैं।


8
ध्यान देने वाली एक बात यह है कि यह उन विशेषताओं को संभाल नहीं पाएगी, जिन्हें द्रव्यमान-असाइन नहीं किया जा सकता है, जबकि find_or_create_byहोगा।
X1a4

1
मार्को, कोशिश करो Model.where(attributes).instance_eval{|q| q.first || q.create}
हिरोशी

3
find_or_createएक लेन-देन का उपयोग करने का लाभ भी है, जहां where….first || createएक दौड़ की स्थिति का परिचय दिया गया है
mrm

मैं कहूंगा def self.find_or_create(attributes) self.where(attributes).first || self.create(attributes) endकि आपको दोहराने की जरूरत नहीं हैModel
अगस्तिन Riedinger

@AugustinRiedinger आपको selfविधि निकाय के अंदर की आवश्यकता नहीं है (जब से आप शब्दों को हटाने के लिए देख रहे हैं!)।
डेविड टाइट

31

रेल 4 में आप कर सकते हैं:

GroupMember.find_or_create_by(member_id: 4, group_id: 7)

और उपयोग whereअलग है:

GroupMember.where(member_id: 4, group_id: 7).first_or_create

इस createपर फोन करेंगे GroupMember.where(member_id: 4, group_id: 7):

GroupMember.where(member_id: 4, group_id: 7).create

इसके विपरीत, find_or_create_by(member_id: 4, group_id: 7)वसीयत createपर कॉल GroupMember:

GroupMember.create(member_id: 4, group_id: 7)

कृपया रेल / रेल पर यह प्रासंगिक वचनबद्धता देखें ।


16

ब्लॉक को find_or_createपास करने से , आप अतिरिक्त पैरामीटर पास कर सकते हैं जो ऑब्जेक्ट में जोड़े जाएंगे यदि यह नया बनाया जाता है। यह उपयोगी है यदि आप उस क्षेत्र की उपस्थिति को मान्य कर रहे हैं जिसे आप खोज नहीं रहे हैं।

मान लिया जाये कि:

class GroupMember < ActiveRecord::Base
    validates_presence_of :name
end

फिर

GroupMember.where(:member_id => 4, :group_id => 7).first_or_create { |gm| gm.name = "John Doe" }

यदि यह एक साथ नहीं मिलता है तो "जॉन डो" नाम के साथ एक नया GroupMember बनाएंगे member_id 4 and group_id 7


4

तुम कर सकते हो:

User.find_or_create_by(first_name: 'Penélope', last_name: 'Lopez')
User.where(first_name: 'Penélope', last_name: 'Lopez').first_or_create

या बस आरंभ करने के लिए:

User.find_or_initialize_by(first_name: 'Penélope', last_name: 'Lopez')
User.where(first_name: 'Penélope', last_name: 'Lopez').first_or_initialize

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.