좋아요. 저는 오랫동안 더 효율적으로 뭔가를하고 싶었습니다.
매우 적은 결과 만 포함해도 제대로 작동합니다. 다음과 같은 코드는 참여하고자하는 항목이 많을 때 더 효과적입니다.
코드를 더 쉽게 이해할 수 있도록 먼저 손쉬운 버전을 만든 다음 확장했습니다.
첫 번째 방법 : 다음 우리는 테이블 (N × M 개의 관계)
merge_through "을 통해"할 수 있습니다 것으로 나타났습니다
# 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
!주소이 문제는 :
여기
# 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의 사용을 만드는) 전체 방법에 대해 지금
lambmerge = lambda do |lhash, rhash, lid, rid|
lhash[lid].keywords << rhash[rid]
end
Location.merge_through!(Location.all, Keyword.all, LocationsKeyword.all, lambmerge)
:
# 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