개체 배열을 ActiveRecord :: Relation으로 변환
나는 객체의 배열을 가지고 있습니다 Indicator
. def self.subjects
이 배열 에서 Indicator 클래스 메서드 ( 다양성, 범위 등) 를 실행하고 싶습니다 . 개체 그룹에서 클래스 메서드를 실행하는 유일한 방법은 ActiveRecord :: Relation이되도록하는 것입니다. 그래서 나는 추가에 의지 결국 to_indicators
에 방법을 Array
.
def to_indicators
# TODO: Make this less terrible.
Indicator.where id: self.pluck(:id)
end
때때로 나는 클래스 메소드 내에서 결과를 필터링하기 위해 이러한 범위 중 상당수를 연결합니다. 따라서 ActiveRecord :: Relation에서 메서드를 호출하더라도 해당 개체에 액세스하는 방법을 모릅니다. 나는 그것을 통해서만 그것의 내용을 얻을 수 있습니다 all
. 그러나 all
배열입니다. 그래서 그 배열을 ActiveRecord :: Relation으로 변환해야합니다. 예를 들어, 다음 방법 중 하나의 일부입니다.
all.to_indicators.applicable_for_bank(id).each do |indicator|
total += indicator.residual_risk_for(id)
indicator_count += 1 if indicator.completed_by?(id)
end
나는 이것이 두 가지 질문으로 요약 된 것 같다.
- 개체 배열을 ActiveRecord :: Relation으로 어떻게 변환 할 수 있습니까?
where
매번 하지 않고 가급적이면 . def self.subjects
ActiveRecord :: Relation에서 형식 메서드를 실행할 때 ActiveRecord :: Relation 개체 자체에 액세스하려면 어떻게해야합니까?
감사. 명확히해야 할 점이 있으면 알려주세요.
개체 배열을 ActiveRecord :: Relation으로 어떻게 변환 할 수 있습니까? 가급적이면 매번 장소를하지 않고.
Relation은 SQL 쿼리의 작성 기일 뿐이며 해당 메서드는 실제 데이터에서 작동하지 않으므로 Array를 ActiveRecord :: Relation으로 변환 할 수 없습니다.
그러나 원하는 것이 관계라면 :
ActiveRecord 3.x의 경우를 호출하지 않고
all
대신을 호출 하면 배열에서 제공scoped
하는 것과 동일한 레코드를 나타내는 Relation이all
반환됩니다.ActiveRecord 4.x의 경우 간단히을 호출
all
하면 관계가 반환됩니다.
def self.subjects
ActiveRecord :: Relation에서 형식 메서드를 실행할 때 ActiveRecord :: Relation 개체 자체에 액세스하려면 어떻게해야합니까?
메서드가 Relation 개체에서 호출 될 때는 self
관계입니다 (정의 된 모델 클래스와 반대).
다음 arr
과 같이 객체 배열을 ActiveRecord :: Relation으로 변환 할 수 있습니다 (객체가 어떤 클래스인지 알고 있다고 가정 할 때).
MyModel.where(id: arr.map(&:id))
where
그래도 사용해야 하지만 사용을 꺼려해서는 안되는 유용한 도구입니다. 이제 배열을 관계로 변환하는 한 줄짜리가 있습니다.
map(&:id)
개체 배열을 ID 만 포함하는 배열로 바꿉니다. 그리고 where 절에 배열을 전달하면 IN
다음과 같은 SQL 문이 생성됩니다 .
SELECT .... WHERE `my_models`.id IN (2, 3, 4, 6, ....
배열의 순서가 손실된다는 점을 염두에 두십시오. 그러나 귀하의 목표는 이러한 객체 컬렉션 에 대해 클래스 메서드를 실행하는 것이므로 문제가되지 않는다고 가정합니다.
글쎄, 제 경우 에는 개체 배열을 ActiveRecord :: Relation 으로 변환 하고 특정 열 (예 : ID) 로 정렬 해야합니다. MySQL을 사용하고 있으므로 필드 함수 가 도움이 될 수 있습니다.
MyModel.where('id in (?)',ids).order("field(id,#{ids.join(",")})")
SQL은 다음과 같습니다.
SELECT ... FROM ... WHERE (id in (11,5,6,7,8,9,10))
ORDER BY field(id,11,5,6,7,8,9,10)
ActiveRecord::Relation
데이터베이스에서 데이터를 검색하는 데이터베이스 쿼리를 바인딩합니다.
이해하기 위해 동일한 클래스의 객체가있는 배열이 있다고 가정합니다. 그러면 어떤 쿼리를 사용하여 바인딩할까요?
내가 달릴 때
users = User.where(id: [1,3,4,5])
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 3, 4, 5) ORDER BY created_at desc
위의 여기에서 객체를 users
반환 Relation
하지만 그 뒤에 데이터베이스 쿼리를 바인딩하고 볼 수 있습니다.
users.to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 3, 4, 5) ORDER BY created_at desc"
따라서 ActiveRecord::Relation
SQL 쿼리와 무관 한 객체 배열 에서 반환하는 것은 불가능합니다 .
First of all, this is NOT a silver bullet. Out of my experience, I found that converting to relation is sometimes easier than alternatives. I try to use this approach very sparingly and only in cases where the alternative would be more complex.
That being said here is my solution, I've extended Array
class
# lib/core_ext/array.rb
class Array
def to_activerecord_relation
return ApplicationRecord.none if self.empty?
clazzes = self.collect(&:class).uniq
raise 'Array cannot be converted to ActiveRecord::Relation since it does not have same elements' if clazzes.size > 1
clazz = clazzes.first
raise 'Element class is not ApplicationRecord and as such cannot be converted' unless clazz.ancestors.include? ApplicationRecord
clazz.where(id: self.collect(&:id))
end
end
A usage example would be array.to_activerecord_relation.update_all(status: 'finished')
. Now where do I use it?
Sometimes you need to filter out ActiveRecord::Relation
for example take out not completed elements. In those cases best is to use scope elements.not_finished
and you would still keep ActiveRecord::Relation
.
But sometimes that condition is more complex. Take out all elements that are not finished, and that has been produced in the last 4 weeks and have been inspected. To avoid creating new scopes you can filter to an array and then convert back. Keep in mind that you still do a query to DB, quick since it searches by id
but still a query.
참고URL : https://stackoverflow.com/questions/17331862/converting-an-array-of-objects-to-activerecordrelation
'programing tip' 카테고리의 다른 글
내 Android 앱을 어떻게 프로파일 링 할 수 있습니까? (0) | 2020.08.31 |
---|---|
'tuple'과 'tie'를 통해 비교 연산자를 구현하는 것이 좋습니다. (0) | 2020.08.31 |
사용자 정의 필터 기능이있는 AngularJS 다중 필터 (0) | 2020.08.30 |
iOS 시뮬레이터가 너무 큼 (0) | 2020.08.30 |
이미 검증 된 양식에 오류를 삽입 하시겠습니까? (0) | 2020.08.30 |