简体   繁体   English

按关联模型中的列对Rails数据库表进行排序

[英]Sorting a Rails database table by a column in an associated model

I'm trying to implement Ryan Bates' sortable table columns code (Railscast #228) but I'd like to be able to sort on an associated column. 我正在尝试实现Ryan Bates的可排序表列代码(Railscast#228),但我希望能够对相关列进行排序。 In particular, I have the following models and associations: 特别是,我有以下模型和协会:

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"

The association between the Project model and the User model is mediated by the 'program_manager_id' foreign key, which the user sets in the new/edit views using a collection-select dropdown. Project模型和User模型之间的关联由'program_manager_id'外键调解,用户使用collection-select下拉列表在new / edit视图中设置该外键。 Here's part of the annotation at the top of project.rb: 这是project.rb顶部注释的一部分:

# Table name: projects
# program_manager_id :integer

I want to be able to sort my list of projects in the index view by the program manager's name, ie, by project.program_manager.name. 我希望能够通过程序管理器的名称(即project.program_manager.name)对索引视图中的项目列表进行排序。

Ideally, I'd be able to point :order to this name somehow, perhaps with something like this in the index method of my ProjectsController: 理想情况下,我能够指出:以某种方式命令这个名字,也许在我的ProjectsController的索引方法中使用这样的东西:

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

But that obviously won't work (not to mention Ryan's routine implements this with a specific reference to table names from the model to be sorted.) 但这显然不起作用(更不用说Ryan的例程通过特定引用要排序的模型中的表名来实现它。)

I've come across some intimidating approaches that use named_scope, such as: 我遇到过一些使用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"

But given my lack of MySQL expertise, this is fairly impenetrable to me. 但鉴于我缺乏MySQL的专业知识,这对我来说是相当难以理解的。

Can anyone help me either generalize the named_scope example above for my specific case, or point me to a more straightforward strategy? 任何人都可以帮助我将上面的named_scope示例概括为我的特定情况,还是指向一个更简单的策略?

Thanks very much, 非常感谢,

Dean 院长

Let's dissect that named scope you referenced above. 让我们剖析您在上面引用的命名范围。 Imagine a model Question which has many Comments. 想象一个模型问题有很多评论。

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

the name of your scope. 范围的名称。 You would reference thusly: Question.find(:all).most_active 你会这样参考:Question.find(:all).most_active

:select => "questions.*"

by default scopes selects all columns from your table anyway, so this limits the results to only the questions table, and not the comments table. 默认情况下,作用域会选择表中的所有列,因此这会将结果限制为仅限问题表,而不是注释表。 This is optional. 这是可选的。

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

this is saying for every question, I also want to get all comments associated with them. 这是对每个问题的说法,我也想得到与他们相关的所有评论。 The comments table has a column 'question_id' which is what we'll be using to match them up to the appropriate question record. 评论表有一个'question_id'列,我们将使用它来匹配它们到相应的问题记录。 This is important. 这个很重要。 It allows us access to fields that are not on our model! 它允许我们访问不在我们模型上的字段!

 :group => "questions.id"

This is required for the count() function in the order clause to tell us that we want the count of comments based on question. 这是order子句中count()函数所必需的,告诉我们我们想要基于问题的注释计数。 We don't need the count function in our order clause, so we also don't need this group statement 我们的order子句中不需要count函数,所以我们也不需要这个group语句

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

Return the results in order of number of comments, highest to lowest. 按照评论数量的顺序返回结果,从最高到最低。

So for our example, discarding what we don't need, and applying to your needs, we end up with: 因此,对于我们的示例,丢弃我们不需要的东西,并应用于您的需求,我们最终得到:

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

This named_scope would be called thusly: 这个named_scope将被调用:

Project.find(:all).by_program_manager_name

Note this is basically equivalent to: 注意这基本上相当于:

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

But, as cam referenced above, you should really know the underlying SQL. 但是,正如上面提到的cam,您应该真正了解底层SQL。 Your abilities will be severely hampered without this understanding 没有这种理解,你的能力将受到严重阻碍

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

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