如何按最新的子记录属性排序记录

时间:2015-02-20 16:46:23

标签: ruby-on-rails has-many has-one

通过has_one关联订购我的记录时遇到了麻烦。我很确定解决方案是显而易见的,但我无法得到它。

class Migration
  has_many :checks
  has_one :latest_origin_check, -> { where(origin: true).order(at: :desc) }, class_name: 'Check'
end

class Check
  belongs_to :migration
end

如果我通过checks.status订购,我总会得到不同的支票ID。它们不应该是相同的但是有不同的顺序吗?

或者是 - > {}获取has_one关联问题的方法是什么?

Migration.all.includes(:latest_origin_check).order("checks.status DESC").each do |m| puts m.latest_origin_check.id end

所以在一句话中:如何通过自定义has_one关联订购记录?

我正在使用Ruby 2.0.0,Rails 4.2和PostgreSQL。

更新

我不够具体。我在检查关系上有两个has_one关系。 也非常重要。一个迁移可以通过大量检查来同时包含所有检查。所以Migration.first.includes(:checks)会很慢。我们谈的是几千人,我只需要最新的。

class Migration
  has_many :checks
  has_one :latest_origin_check, -> { where(origin: true).order(at: :desc) }, class_name: 'Check'
  has_one :latest_target_check, -> { where(origin: false).order(at: :desc) }, class_name: 'Check'


end

class Check
  belongs_to :migration
end

现在,如果我得到latest_origin_check,我会得到正确的记录。查询如下。

pry(main)> Migration.last.latest_origin_check
Migration Load (1.1ms)  SELECT  "migrations".* FROM "migrations"  ORDER BY  "migrations"."id" DESC LIMIT 1
Check Load (0.9ms)  SELECT  "checks".* FROM "checks" WHERE "checks"."migration_id" = $1 AND "checks"."origin" = 't'  ORDER BY "checks"."at" DESC LIMIT 1  [["migration_id", 59]]

如何获取每次迁移的最新检查,然后按最新检查的属性对迁移进行排序?

我正在使用hansack。当我通过“checks.at”

订购记录时,Ransack似乎正确
SELECT "migrations".* FROM "migrations" LEFT OUTER JOIN "checks" ON "checks"."migration_id" = "migrations"."id" AND "checks"."origin" = 't' WHERE (beginning between '2015-02-22 23:00:00.000000' and '2015-02-23 22:59:59.000000' or ending between '2015-02-22 23:00:00.000000' and '2015-02-23 22:59:59.000000') ORDER BY "checks"."at" ASC

但是当我按状态

命令时,相同的查询会返回错误的结果
SELECT "migrations".* FROM "migrations" LEFT OUTER JOIN "checks" ON "checks"."migration_id" = "migrations"."id" AND "checks"."origin" = 't' WHERE (beginning between '2015-02-22 23:00:00.000000' and '2015-02-23 22:59:59.000000' or ending between '2015-02-22 23:00:00.000000' and '2015-02-23 22:59:59.000000') ORDER BY "checks"."status" ASC

Check.status是一个布尔值,check.at是一个DateTime。一位同事建议布尔值是问题所在。我是否需要将布尔值转换为整数以使其可排序?我如何只为:latest_origin_check?那样的东西?

.order("(case when \"checks\".\"status\" then 2 when \"checks\".\"status\" is null  then 0 else 1 end) DESC")

1 个答案:

答案 0 :(得分:0)

您与Check上的Migration已建立了has_many关系。我认为你正在寻找范围:

scope :latest_origin_check, -> { includes(:checks).where(origin:true).order("checks.status DESC").limit(1)}

has_one :latest_origin_check行放在Migration上。

Migration.latest_origin_check

我认为该行应返回您想要的结果集。