如何在 Rails 3 中订购包含的元素
Posted
技术标签:
【中文标题】如何在 Rails 3 中订购包含的元素【英文标题】:How to order included elements in Rails 3 【发布时间】:2011-07-17 21:56:39 【问题描述】:我有一个模型关系,其中today
有很多tasks
我正在尝试检索用户的 today
对象,包括 tasks
并将它们全部呈现给 Json。所有这一切都很顺利,直到我决定在today
对象中订购tasks
,因为respond_with block
也用于呈现html 页面。有什么方法可以包含tasks
并订购它们?
我正在尝试这样的事情:
class TodaysController < ApplicationController
respond_to :html, :json
def show
@today = Today.where(:user_id => current_user.id).joins(:tasks).includes(:tasks).order(:priority).first
respond_with @today, :include => :tasks
end
end
这会正确检索所有内容,但似乎根本没有对任务进行排序。
这是我曾经拥有的(效果很好,但没有订购):
class TodaysController < ApplicationController
respond_to :html, :json
def show
@today = current_user.today
respond_with @today, :include => :tasks
end
end
我知道我可以像这样检索数据并在之后对其进行排序:
@today = current_user.today
@today.tasks.sort!|a,b| a.priority <=> b.priority
这可行并且会通过我的测试,但我希望有一种 ActiveRecord 方法来解决这个问题。
【问题讨论】:
关于你的最后一行代码。下面稍微清楚一点:@today.tasks.sort_by(&:priority)
.
【参考方案1】:
在您的 Today
模型中试试这个:
has_many :tasks, :order => 'priority DESC'
编辑:正如下面评论中提到的,在 Rails 4+ 中,现在是:
has_many :tasks, -> order(:priority => :desc)
(more info here)
【讨论】:
没有其他办法吗? 在 Rails 4 中,现在已弃用,新方法将是has_many :tasks, -> order(:priority => :desc)
read about it here【参考方案2】:
直接的解决方案是在priority
之前包含tasks
表名:
Today.where(:user_id => current_user.id).includes(:tasks).order('tasks.priority').first
# joins(:tasks) is not required
或者,如果您不想硬编码表名,您可以与Task
模型的范围合并:
Today.where(:user_id => current_user.id).joins(:tasks).includes(:tasks).merge(Task.order(:priority)).first
# joins(:tasks) here is required
此外,您可以将 has_many: todays
添加到 User
模型以放弃 where
子句并执行以下操作:
current_user.todays.includes(:tasks).order('tasks.priority').first
# or
current_user.todays.joins(:tasks).includes(:tasks).merge(Task.order(:priority)).first
但如果您只需要/总是按优先级排序,而不需要其他不同的排序,则将order
添加到has_many :tasks
会更容易。
【讨论】:
我不明白为什么将订单添加到模型中会更好。在我看来,排序是视图的一部分,与任何一个模型都无关。 是的。我的意思是更容易。已编辑。 @JackToday.where(:user_id => current_user.id).joins(:tasks).includes(:tasks).merge(Task.order(:priority)).first
它不适用于 Rails 4.2
应该可以,现在没有 4.2 来测试它,肯定可以在 5 中使用。无论如何,从 4.0 开始,您实际上应该使用 references
和 includes
来表明您将使用表格查询。所以它应该类似于Today.where(:user_id => current_user.id).includes(:tasks).references(:tasks).merge(Task.order(:priority)).first
以上是关于如何在 Rails 3 中订购包含的元素的主要内容,如果未能解决你的问题,请参考以下文章
Rails 3.1 资产管道和手动订购的 Javascript 需要
如何通过远距离以外的其他方式订购rails geocoder gem的结果