ठीक है मैं कुछ ऐसा करना चाहता हूं जो थोड़ी देर के लिए अधिक कुशल हो।
कृपया ध्यान दें कि बहुत कम परिणामों के लिए, काम ठीक है। नीचे दिया गया कोड बेहतर काम करता है जब आपके पास बहुत सारे कॉलम शामिल होते हैं जिन्हें आप शामिल करना चाहते हैं।
कोड को समझना आसान बनाने के लिए, मैंने पहले एक आसान संस्करण तैयार किया और उस पर विस्तार किया।
सबसे पहले विधि:
# takes a main array of ActiveRecord::Base objects
# converts it into a hash with the key being that object's id method call
# loop through the second array (arr)
# and call lamb (a lambda { |hash, itm|) for each item in it. Gets called on the main
# hash and each itm in the second array
# i.e: You have Users who have multiple Pets
# You can call merge(User.all, Pet.all, lambda { |hash, pet| hash[pet.owner_id].pets << pet }
def merge(mainarray, arr, lamb)
hash = {}
mainarray.each do |i|
hash[i.id] = i.dup
end
arr.each do |i|
lamb.call(i, hash)
end
return hash.values
end
मैं तो देखा हम तालिकाओं (nxm रिश्ते)
merge_through "के माध्यम से" हो सकता है!पतों इस मुद्दे:
lambmerge = lambda do |lhash, rhash, lid, rid|
lhash[lid].keywords << rhash[rid]
end
Location.merge_through!(Location.all, Keyword.all, LocationsKeyword.all, lambmerge)
पूरा विधि के लिए अब
# merges multiple arrays (or hashes) with the main array (or hash)
# each arr in the arrs is a hash, each must have
# a :value and a :proc
# the procs will be called on values and main hash
#
# :middletable will merge through the middle table if provided
# :value will contain the right table when :middletable is provided
#
def merge_multi!(mainarray, arrs)
hash = {}
if (mainarray.class == Hash)
hash = mainarray
elsif (mainarray.class == Array)
mainarray.each do |i|
hash[i.id] = i.dup
end
end
arrs.each do |h|
arr = h[:value]
proc = h[:proc]
if (h[:middletable])
middletable = h[:middletable]
merge_through!(hash, arr, middletable, proc)
else
arr.each do |i|
proc.call(i, hash)
end
end
end
return hash.values
end
यहाँ कैसे मैं अपने कोड का उपयोग करें (जो merge_through का उपयोग करता है):
# this works for tables that have the equivalent of
# :through =>
# an example would be a location with keywords
# through locations_keywords
#
# the middletable should should return as id an array of the left and right ids
# the left table is the main table
# the lambda fn should store in the lefthash the value from the righthash
#
# if an array is passed instead of a lefthash or a righthash, they'll be conveniently converted
def merge_through!(lefthash, righthash, middletable, lamb)
if (lefthash.class == Array)
lhash = {}
lefthash.each do |i|
lhash[i.id] = i.dup
end
lefthash = lhash
end
if (righthash.class == Array)
rhash = {}
righthash.each do |i|
rhash[i.id] = i.dup
end
righthash = rhash
end
middletable.each do |i|
lamb.call(lefthash, righthash, i.id[0], i.id[1])
end
return lefthash
end
यह कैसे मैं इसे कहते है :
def merge_multi_test()
merge_multi!(Location.all,
[
# each one location has many s3_images (one to many)
{ :value => S3Image.all,
:proc => lambda do |img, hash|
if (img.imageable_type == 'Location')
hash[img.imageable_id].s3_images << img
end
end
},
# each location has many LocationsKeywords. Keywords is the right table and LocationsKeyword is the middletable.
# (many to many)
{ :value => Keyword.all,
:middletable => LocationsKeyword.all,
:proc => lambda do |lhash, rhash, lid, rid|
lhash[lid].keywords << rhash[rid]
end
}
])
end
आप कर सकते हैं कोड को संशोधित करें यदि आप आलसी लोड गुणों की इच्छा करना चाहते हैं जो कई लोगों में से एक हैं (जैसे कोई शहर किसी स्थान पर है) असल में, उपरोक्त कोड काम नहीं करेगा क्योंकि आपको मुख्य हैश के माध्यम से लूप करना होगा और शहर को सेट करना होगा दूसरा हैश (कोई "city_id, location_id" तालिका नहीं है)। शहर के हश में सभी स्थानों को वापस निकालने के लिए आप शहर और स्थान को उलट सकते हैं। मुझे लगता है कि कोड अभी तक तो मैं यह छोड़ दिया की जरूरत नहीं है =)
आप का उपयोग करके ActiveRecord मॉडल के सभी कॉलम प्राप्त कर सकते हैं: ** Model.columns.map (&: name) **, लेकिन मुझे यकीन नहीं है कि यह वही है जो आप चाहते हैं। – MurifoX
जब मैं शामिल होता हूं, तो मुझे नहीं पता कि कौन से मूल्य मॉडल के हैं। यही कारण है कि मैं कॉलम के नाम चाहता था। भविष्य में यहां आने वाले किसी भी व्यक्ति के लिए – Abdo