我正在尝试实现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"
Project模型和User模型之间的关联由’program_manager_id’外键调解,用户使用collection-select下拉列表在new / edit视图中设置该外键.这是project.rb顶部注释的一部分:
# Table name: projects
# program_manager_id :integer
我希望能够通过程序管理器的名称(即project.program_manager.name)在索引视图中对项目列表进行排序.
理想情况下,我能够指出:以某种方式命令这个名字,也许在我的ProjectsController的索引方法中使用这样的东西:
@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示例概括为我的特定情况,还是指向一个更简单的策略?
非常感谢,
院长
解决方法:
让我们剖析您在上面引用的命名范围.想象一个模型问题有很多评论.
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.*"
默认情况下,作用域会选择表中的所有列,因此这会将结果限制为仅限问题表,而不是注释表.这是可选的.
:joins => "left join comments as comments_for_count on comments_for_count.question.id = questions.id"
这是对每个问题的说法,我也想得到与他们相关的所有评论.评论表有一个’question_id’列,我们将使用它来匹配它们到相应的问题记录.这个很重要.它允许我们访问不在我们模型上的字段!
:group => "questions.id"
这是order子句中count()函数所必需的,告诉我们我们想要基于问题的注释计数.我们的order子句中不需要count函数,所以我们也不需要这个group语句
:order => "count(questions.id) desc"
按照评论数量的顺序返回结果,从最高到最低.
因此,对于我们的示例,丢弃我们不需要的东西,并应用于您的需求,我们最终得到:
: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.没有这种理解,你的能力将受到严重阻碍