2013-06-09 8 views
11

बनाने के लिए सरणी में संग्रहीत 'विदेशी कुंजी' रेलवे (4) में एक-से-कई/has_many एसोसिएशन बनाने के लिए arrays पोस्ट किया जा सकता है? मुझे पता है कि एक विदेशी कुंजी प्रकार सरणी संभव नहीं है।रेल/पोस्टग्रेस, 1-एसोसिएशन

उदाहरण: एक कार्य में एकाधिक असाइनर्स हैं। परंपरागत रूप से मैं इसे एक एसोसिएशन टेबल का उपयोग करके हल कर दूंगा: कार्य-> असाइनर्स-> उपयोगकर्ता। सरणी का उपयोग करना, यह आवश्यक नहीं होगा क्योंकि एकाधिक 'विदेशी कुंजी' को संग्रहीत किया जा सकता है।

निम्न क्वेरी तो मेरे पास सौंपा सभी कार्य प्राप्त करने के लिए इस्तेमाल किया जा सकता:

select * from tasks where ? IN tasks.assignees 
+5

आपको लगता है कि सरणी-आधारित विदेशी कुंजी जानने में दिलचस्पी पर काम किया जा रहा है हो जाएगा। वे इसे PostgreSQL 9.4 में बना सकते हैं, लेकिन मुझे नहीं लगता कि उन्होंने इसे 9.3 के लिए बनाया है। –

उत्तर

6

आप रेल इस सरणी से अवगत कराने और संघों के लिए इसका इस्तेमाल करने में सक्षम नहीं होगा।

लेकिन यदि आप उपयोगकर्ताओं को सौंपा गया कार्य की त्वरित खोज/फ़िल्टरिंग चाहते हैं तो आप कार्य ऑब्जेक्ट में उपयोगकर्ता आईडी की सरणी रख सकते हैं। अन्यथा, आपको अपने मानक एसोसिएशन टेबल में ऐलिस को सौंपा गया सभी कार्यों को खोजने के लिए जॉइन करना होगा।

तो समाधान एसोसिएशन टेबल रखना है, लेकिन कार्य ऑब्जेक्ट में असाइन करने वाले उपयोगकर्ता आईडी को डुप्लिकेट करना और तेज़ खोज/फ़िल्टरिंग के लिए उस आईडी सूची का उपयोग करना है।

आपको after_create और after_destroy असाइन करने वाले ऑब्जेक्ट्स के लिए जीवन चक्र में हुक करने और कार्य रिकॉर्ड सरणी में नई असाइन आईडी को डालने की आवश्यकता होगी। और फिर जब किसी कार्य से एक एग्निनी हटा दी जाती है तो आईडी को निकालने के लिए सरणी को अद्यतन करें।

सभी सरणी ऑपरेटरों के लिए Postgres देखें डॉक्स:

कुछ इस तरह:

class Task < ActiveRecord::Base 
    has_many :assignees, :dependent => :destroy 
end 

class Asignee < ActiveRecord::Base 

    belongs_to :task 
    after_create :insert_task_assignee 
    after_destroy :remove_task_assignee 

    # assumes that there is a column called assignee_id 
    # that contains the User ID of the assigned person 

    private 

    def insert_task_assignee 
     # TODO: check for duplicates here - before we naively push it on? 
     task.assignee_list = task.assignee_list.push(assignee_id) 
     task.assignee_list.save 
    end 

    def remove_task_assignee 
     id_list = task.assignee_list 
     id_list.reject! { |candidate_id| candidate_id == assignee_id } 
     task.assignee_list = id_list 
     task.assignee_list.save 
    end 

end 

# find all tasks that have been assigned Alice & Bob 
# this will require the `postgres_ext` gem for Ruby/Postgres array searching 
tasks = Task.where.contains(:assignee_list => [alice.id, bob.id]).all 
+0

लेकिन कैसे सरणी को किसी सरणी के माध्यम से किसी एसोसिएशन के बारे में जागरूक करना है ताकि जब मॉडल शामिल हों तो यह मॉडलों को लोड करेगा? – Xeago

+1

आप ऐरे के माध्यम से एसोसिएशन के बारे में जागरूक रेल नहीं बना सकते हैं। इसका उपयोग केवल मूल "कैशिंग" तंत्र के रूप में किया जाएगा और संभावित रूप से अनुकूलन होगा क्योंकि कार्यों को 'जॉइन' करने के बजाय सीधे पूछे जा सकते हैं –