私は作業中に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
から助けを借りてそれを考え出したこの関連記事。
私は、注文をHomeモデルからAvailabilityモデルに移動しました。
可用性
default_scope :order => "price ASC"
それから私は家のモデルに空室状況をロードして価格でソートしたがっています:
ホーム
default_scope :include => :availabilities, :order => "availabilities.price ASC"
エコロジー回答:
scope :ordered, -> { includes(:availabilities).order('availabilities.price') }
素晴らしいですが、それは言及されるべきですincludes
可能性があり、場合によっては次のように置き換えられます。joins
。どちらも最適なユースケースがあります。
実用的な観点からは、主に2つの違いがあります。
includes
関連レコードをロードします。この場合Availability
記録。joins
関連付けられているレコードをロードしないでください。だからあなたは使うべきですincludes
結合モデルのデータを使用したい場合表示price
どこかに。一方、joins
結合モデルのデータをクエリ内でのみ使用する場合は、これを使用してください。にORDER BY
またはWHERE
条項
includes
すべてのレコードをロードしますjoins
結合モデルが関連付けられているレコードのみをロードします。だからOPの場合、Home.includes(:availabilities)
一方、すべての家に荷を積みますHome.joins(:availabilities)
少なくとも1つの可用性に関連付けられている住宅のみをロードします。
また見なさいこの質問。
Rails 5.2以降では、orderメソッドに文字列パラメータを渡すときに非推奨の警告が表示されることがあります。
非推奨警告:危険なクエリメソッド(引数が生のSQLとして使用されているメソッド)が、属性以外の引数で呼び出されました: "table.column"。 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