试图在activerecord中订购包含的结果

时间:2016-10-19 05:25:14

标签: ruby-on-rails activerecord

我有一个多次连接到另一个模型的activerecord模型:

class Claim < ActiveRecord::Base
  belongs_to :user
  belongs_to :treated_by, foreign_key: :treated_by_id, class_name: 'User'
  belongs_to :person_involved, foreign_key: :person_involved_id, class_name: 'User'
  belongs_to :case_manager, foreign_key: :case_manager_id, class_name: 'User'
end

在某些方面,我希望获取声明及其所有用户实例,以便通过使用包含来避免N + 1个查询:

claims = Claim.all.includes(:user, :treated_by, :person_involved)

这很好但现在我想对声明进行排序(没有它们在内存中)所以我想做类似的事情:

Claim.all.includes(:user, :person_involved, :treated_by).order('treated_by.last_name')

但是我得到了无效的SQL,除非我像这样使用表名:

Claim.all.includes(:user, :person_involved, :treated_by).order('users.last_name')

这显然不会帮助我按照用户子集last_name处理的顺序。我该如何正确地做到这一点?

6 个答案:

答案 0 :(得分:1)

includes这里使用单独的查询预加载关系,因此无法根据其他表格列对其进行排序。

您应该使用joins代替。

答案 1 :(得分:1)

Abishek Kumar中提及的his answer,您应该使用joins代替includes,因为includes仅用于阻止N + 1查询问题。 似乎允许您按关联排序,但如果您的关联具有自定义名称,它将无法帮助您。

我认为你必须稍微离开ActiveRecord漂亮舒适的地方一段时间,然后手动编写连接语句:

Claim.all
  .joins("INNER JOIN users AS treated_bys ON claims.treated_by_id = treated_bys.id")
  .order("treated_bys.last_name ASC")

...那么你也可以用includes语句来解决查询,如果你需要它来避免N + 1查询等等。

答案 2 :(得分:0)

这里,查询中的表名应该是复数。 尝试以下:

Claim.all.includes(:user, :person_involved, treated_by).order('treated_bys.last_name')

快乐编码!!

答案 3 :(得分:0)

Claim.all.includes(:user, :person_involved, treated_by).sort_by { |c| c.treated_by.last_name }

答案 4 :(得分:0)

编辑:这不起作用。不要试试这个。

这会有用吗?

Claim.all
  .includes(:user, :person_involved, :treated_by)
  .order(treated_by: { last_name: :asc})

我知道ActiveRecord接受连接的语法,但我不确定它是否适用于排序。

更新:ActiveRecord不支持此语法来订购记录。 order方法接受字符串或散列。当它获得散列时,它期望键是列,值是方向(:asc, :desc; :ASC, :DESC,“asc”,“desc”,“ASC”,“DESC”之一{ {1}} where where子句。

答案 5 :(得分:0)

正如其他人所说,order('treated_by.last_name')不起作用,因为treated_by是仅在rails中起作用的别名,但不包含在要执行的SQL语句中。 order('users.last_name')不会失败,但是不会达到预期的结果,您需要别名由rails自动分配,这可能是...我不知道,¿t1

顺便说一句,这不是“铁路方式”。当您向模型添加belongs_to关系时,您可以在每次通过该关系加入方式以及如何按其列排序时为ON语句指定限制时添加范围。{{3} }

class Claim < ActiveRecord::Base
  belongs_to :user
  belongs_to :treated_by, foreign_key: :treated_by_id, class_name: 'User'
  belongs_to :person_involved, foreign_key: :person_involved_id, class_name: 'User'
  belongs_to :case_manager, foreign_key: :case_manager_id, class_name: 'User'

  belongs_to :treated_and_sort_by, -> { order last_name: :asc }, foreign_key: :treated_by_id, class_name: 'User'
end

所以这应该像这样...

Claim.all.includes(:user, :person_involved, :treated_and_sort_by)