【问题标题】:Sorting a Rails database table by a column in an associated model按关联模型中的列对 Rails 数据库表进行排序
【发布时间】:2011-06-07 11:48:39
【问题描述】:

我正在尝试实现 Ryan Bates 的可排序表列代码 (Railscast #228),但我希望能够对关联的列进行排序。特别是,我有以下模型和关联:

class Project < ActiveRecord::Base
  belongs_to :program_manager, :class_name => "User"

class User < ActiveRecord::Base
  has_many :program_manager_projects, :class_name => "Project", :foreign_key => "program_manager_id"

项目模型和用户模型之间的关联由“program_manager_id”外键介导,用户使用集合选择下拉菜单在新/编辑视图中设置该外键。这是project.rb顶部的部分注释:

# Table name: projects
# program_manager_id :integer

我希望能够按项目经理的姓名(即 project.program_manager.name)对索引视图中的项目列表进行排序。

理想情况下,我能够以某种方式将 :order 指向这个名称,也许在我的 ProjectsController 的 index 方法中使用类似这样的东西:

@projects = Project.find(:all, :order => project.program_manager.name)

但这显然行不通(更不用说 Ryan 的例程通过对要排序的模型中的表名的特定引用来实现这一点。)

我遇到过一些使用 named_scope 的令人生畏的方法,例如:

named_scope :most_active, :select => "questions.*", :joins => "left join comments as comments_for_count on comments_for_count.question.id = questions.id", :group => "questions.id", :order => "count(questions.id) desc"

但鉴于我缺乏 MySQL 专业知识,这对我来说相当难以理解。

谁能帮助我针对我的具体情况概括上面的 named_scope 示例,或者指出一个更直接的策略?

非常感谢,

院长

【问题讨论】:

  • 以ORM为借口不学习SQL是个坏主意。阅读连接。这似乎是一个很好的高级概述:codinghorror.com/blog/2007/10/…
  • 要点...感谢有用的文章链接!我会听取你的建议,不要再拖延深入研究 SQL 了。

标签: mysql ruby-on-rails sorting associations named-scope


【解决方案1】:

让我们剖析您上面引用的命名范围。想象一个有很多评论的模型问题。

named_scope :most_active, :select => "questions.*", :joins => "left join comments as comments_for_count on comments_for_count.question.id = questions.id", :group => "questions.id", :order => "count(questions.id) desc"

:most_active

您的作用域的名称。你会这样引用: Question.find(:all).most_active

:select => "questions.*"

默认情况下,范围无论如何都会选择表中的所有列,因此这会将结果限制为仅问题表,而不是 cmets 表。这是可选的。

:joins => "left join comments as comments_for_count on comments_for_count.question.id = questions.id"

这是对每个问题的说明,我还想获取所有与它们相关联的 cmets。 cmets 表有一个列“question_id”,我们将使用它来将它们与适当的问题记录相匹配。这个很重要。它允许我们访问不在我们模型上的字段!

 :group => "questions.id"

这是 order 子句中的 count() 函数所必需的,它告诉我们我们想要基于 question 的 cmets 计数。我们的 order 子句中不需要 count 函数,所以我们也不需要这个 group 语句

:order => "count(questions.id) desc"

按照 cmets 的数量从高到低的顺序返回结果。

因此,对于我们的示例,丢弃我们不需要的东西并应用您的需求,我们最终得到:

:named_scope :by_program_manager_name, :joins => "left join users on projects.program_manager_id = users.id", :order => "users.name"

这个named_scope会被这样调用:

Project.find(:all).by_program_manager_name

注意这基本上等同于:

Project.find(:all, :joins => "left join users on projects.program_manager_id = users.id", :order => "users.name")

但是,正如上面提到的 cam,您应该真正了解底层 SQL。如果没有这种理解,你的能力将受到严重阻碍

【讨论】:

  • 这正是我正在寻找的答案。感谢您花时间把事情说得这么清楚。根据您的建议,我能够修改 Railscast 代码以执行我想要的操作。正如我在给 Cam 的信息中所指出的,您强烈地激励我坐下来研究 ActiveRecord 的“魔力”背后的 SQL。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-02
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
  • 2021-03-20
相关资源
最近更新 更多