나는 RoR 프로젝트를 가지고있다. 내 모델의 해당 섹션이 있습니다.
집
has_many :communities, :through => :availabilities
has_many :availabilities, :order => "price ASC"
커뮤니티
has_many :homes, :through => :availabilities
has_many :availabilities
유효성
belongs_to :home
belongs_to :community
데이터베이스의 "사용 가능"테이블에는 추가 데이터 열 "가격"
그래서 지금 전화 할 수 있습니다.
@home.availabilities.each do |a|
a.community.name
a.price
원하는대로 가격순으로 정렬 된 사용 가능 여부 데이터를 가져옵니다. 내 질문은 이것이다 :
자동으로 주택을 주문하는 방법이 있습니까?avaliabilities.first.price
(첫째 = 최하위)? 어쩌면default_scope :order
?
나는 사용을 피하도록 제안 할 것이다.default_scope
특히 다른 테이블에있는 가격 같은 것. 해당 테이블을 사용할 때마다 조인 및 정렬이 수행되어 복잡한 쿼리에서 이상한 결과를 가져오고 어쨌든 쿼리를 느리게 만듭니다.
자신의 범위에있어 아무 문제가 없습니다. 더 간단하고 더 명확합니다. 다음과 같이 간단하게 만들 수 있습니다.
scope :ordered, -> { includes(:availabilities).order('availabilities.price') }
추신 :에 인덱스를 추가하는 것을 잊지 마세요.price
도움으로 그것을 알아 냈어.이 관련 게시물.
주문을 홈 모델에서 가용성 모델로 옮겼습니다.
유효성
default_scope :order => "price ASC"
그런 다음 홈 모델에 가용성을로드하고 가격순으로 정렬하겠습니다.
집
default_scope :include => :availabilities, :order => "availabilities.price ASC"
@ecoologic대답:
scope :ordered, -> { includes(:availabilities).order('availabilities.price') }
위대한입니다,하지만 그것은 언급되어야합니다includes
수 있습니다, 그리고 어떤 경우에는에 의해 대체되어야합니다joins
.둘 다 최적의 사용 사례를가집니다..
실용적인 관점에서 두 가지 주요 차이점이 있습니다.
includes
관련 레코드를로드한다. 이 경우Availability
기록.joins
연관된 레코드를로드하지 마십시오. 그래서 당신은includes
예를 들어 조인 모델의 데이터를 사용하려는 경우. 디스플레이price
어딘가에. 한편,joins
쿼리에서 조인 모델의 데이터 만 사용하려는 경우에 사용해야합니다. ...에서ORDER BY
또는WHERE
조항.
includes
모든 레코드를로드하는 동시에joins
연관된 조인 모델이있는 레코드 만로드합니다. 그래서 OP의 경우,Home.includes(:availabilities)
모든 집을 짐을Home.joins(:availabilities)
최소한 하나의 가용성을 가진 주택 만 적재하게됩니다.
참조이 질문.
Rails 5.2 이상에서는 문자열 매개 변수를 주문 메소드에 전달할 때 사용 중단 경고가 표시 될 수 있습니다.
DEPRECATION WARNING : 속성이 아닌 인수 ( "s :"table.column ")로 불리는 위험한 쿼리 메서드 (인수가 원시 SQL로 사용되는 메서드). Rails 6.0에서는 비 속성 인수가 허용되지 않습니다. 이 메소드는 요청 매개 변수 또는 모델 속성과 같은 사용자 제공 값으로 호출하면 안됩니다.
이 문제를 해결하려면Arel.sql()
:
scope :ordered, -> {
includes(:availabilities).order(Arel.sql('availabilities.price'))
}
이것을 달성하는 또 다른 방법은 다음과 같습니다.
scope :ordered, -> { includes(:availabilities).order(Availability.arel_table[:price]) }
당신은 또한 지정할 수 있습니다ASC
방향과 함께
scope :ordered, -> { includes(:availabilities).order(Availability.arel_table[:price].asc) }
DESC
:
scope :ordered, -> { includes(:availabilities).order(Availability.arel_table[:price].desc) }
사용arel_table
...에ActiveRecord
모델을 사용하면 테이블 이름이 변경되었을 때 시나리오를 저장할 수 있습니다 (그러나 매우 드물게 발생합니다).
추가하는 것이 좋습니다.main_table#id
결정적인 정렬을 위해.
최종 버전은 다음과 같습니다.
scope :ordered, -> {
includes(:availabilities).
order(Availability.arel_table[:price].asc, order(Home.arel_table[:id].asc)
}
includes
조인 대신에? - Jwan622