简体   繁体   English

在与 ActiveRecord 的多对多关系上使用不同的方法

[英]Use distinct method with order on a many to many relation with ActiveRecord

I have a classic many to many relationship defined like this in ActiveRecord:我在 ActiveRecord 中定义了一个经典的多对多关系:

class Developer < ApplicationRecord
  has_many :developers_code_reviews
  has_many :code_reviews, through: :developers_code_reviews
end

class DevelopersCodeReview < ApplicationRecord
  belongs_to :code_review
  belongs_to :developer
end

class CodeReview < ApplicationRecord
  has_many :developers_code_reviews
  has_many :developers, through: :developers_code_reviews
end

and I basically want to have a Developer array sorted by code_review.created_at without doubles.我基本上想要一个按code_review.created_at排序的Developer数组,没有双打。

My first attempt was the basic one: Developer.order('code_reviews.created_at': :asc) which triggers this error: ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'code_reviews.created' in 'order clause .我的第一次尝试是基本的: Developer.order('code_reviews.created_at': :asc)触发此错误: ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'code_reviews.created' in 'order clause

After a few googling I understood the join was not automatically performed by ActiveRecord so I added it: Developer.joins(:code_reviews).order('code_reviews.created_at': :asc) .经过几次谷歌搜索后,我了解到 ActiveRecord 不会自动执行Developer.joins(:code_reviews).order('code_reviews.created_at': :asc)因此我添加了它: Developer.joins(:code_reviews).order('code_reviews.created_at': :asc) This one works but has doubles inside.这个有效,但里面有双打。 I need to have a developer to appear only once in this array.我需要一个开发人员在这个数组中只出现一次。

If I try to create a distinct on that query, ActiveRecord/MySQL complains that the ORDER BY is not performed on a column that is in the SELECT.如果我尝试在该查询上创建一个不同的,ActiveRecord/MySQL 会抱怨没有在 SELECT 中的列上执行ORDER BY How can I solve this problem?我怎么解决这个问题?

I googled it quite a lot I can't find anything.我用谷歌搜索了很多我找不到任何东西。

NOTE笔记

The MYSQL query which works but with doubles looks like this: MYSQL 查询可以使用双打,如下所示:

SELECT `developers`.*
FROM `developers`
INNER JOIN `developers_code_reviews` ON `developers_code_reviews`.`developer_id` = `developers`.`id`
INNER JOIN `code_reviews` ON `code_reviews`.`id` = `developers_code_reviews`.`code_review_id` 
ORDER BY `code_reviews`.`created_at` ASC

and I'd like to have a distinct on the developers.我想对开发人员有一个不同的看法。

I found the answer thanks to this clear example on MySQL sub queries: http://www.mysqltutorial.org/mysql-subquery/由于这个关于 MySQL 子查询的清晰示例,我找到了答案: http : //www.mysqltutorial.org/mysql-subquery/

With this example, I understood that I needed a sub query looking like this:通过这个例子,我明白我需要一个如下所示的子查询:

SELECT *
FROM developers
LEFT OUTER JOIN (
  SELECT developer_id, max(updated_at) max_updated_at
  FROM developers_code_reviews
  GROUP BY developer_id
) dcr
ON developers.id = dcr.developer_id
ORDER BY maxupdt

Translated to ruby in my case:在我的情况下转换为 ruby​​:

class DevelopersCodeReview < ApplicationRecord
  belongs_to :code_review
  belongs_to :developer

  class << self
    def developer_queue
      select('developer_id, max(updated_at) max_updated_at').
      group(:developer_id)
    end
  end
end

class Developer < ApplicationRecord
  belongs_to :slack_workspace
  belongs_to :project, optional: true

  class << self
    def queue
      developer_queue = DevelopersCodeReview.developer_queue.to_sql

      joins("LEFT OUTER JOIN (#{developer_queue}) dcr ON id = dcr.developer_id").
      order(max_updated_at: :asc)
    end
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM