如何在Rails 3中订购包含的元素

roy*_*ter 40 ruby activerecord ruby-on-rails arel

我有一个模型关系,其中today有很多tasks

我正在尝试检索用户的today对象,包括tasks并将它们全部呈现给Json.所有这一切都很顺利,直到我决定要taskstoday对象内进行排序,因为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
Run Code Online (Sandbox Code Playgroud)

这会正确检索所有内容,但似乎根本不会对任务进行排序.

这就是我曾经拥有的(效果很好,但没有订购):

class TodaysController < ApplicationController
  respond_to :html, :json
  def show
    @today = current_user.today
    respond_with @today, :include => :tasks
  end
end
Run Code Online (Sandbox Code Playgroud)

我知道我可以检索数据并在之后对其进行排序,如下所示:

@today = current_user.today
@today.tasks.sort!{|a,b| a.priority <=> b.priority }
Run Code Online (Sandbox Code Playgroud)

这有效并将通过我的测试,但我希望有一种ActiveRecord方法来解决这个问题.

khe*_*lll 63

在你的Today模型中尝试这个:

has_many :tasks, :order => 'priority DESC'
Run Code Online (Sandbox Code Playgroud)

编辑:正如下面的评论中提到的,在Rails 4+中,现在是:

has_many :tasks, -> { order(:priority => :desc) }
Run Code Online (Sandbox Code Playgroud)

(更多信息在这里)

  • 在rails 4中,现在已经弃用了,新的方法是`has_many:tasks, - > {order(:priority =>:desc)}`[在这里阅读](http://stackoverflow.com/questions/18284606 /弃用预警换轨-4-模型与阶) (25认同)
  • 没有别的方法可以做到这一点吗? (5认同)

Jac*_*ack 44

直接解决方案是在tasks之前包含表名priority:

Today.where(:user_id => current_user.id).includes(:tasks).order('tasks.priority').first
# joins(:tasks) is not required
Run Code Online (Sandbox Code Playgroud)

或者,如果您不希望将表名硬编码,则可以从Task模型中合并范围:

Today.where(:user_id => current_user.id).joins(:tasks).includes(:tasks).merge(Task.order(:priority)).first
# joins(:tasks) here is required
Run Code Online (Sandbox Code Playgroud)

此外,您可以添加has_many: todaysUser模型以抛弃该where子句并执行:

current_user.todays.includes(:tasks).order('tasks.priority').first
# or
current_user.todays.joins(:tasks).includes(:tasks).merge(Task.order(:priority)).first
Run Code Online (Sandbox Code Playgroud)

但是,如果你只需要/总是优先订购,并且不需要其他不同的排序,加入orderhas_many :tasks更加容易.

  • 我不明白为什么将订单添加到模型中会更好。在我看来,排序是视图的一部分,与任一模型都无关。 (2认同)
  • 应该可以工作,现在没有 4.2 来测试它,肯定可以在 5 中工作。无论如何,从 4.0 开始,您实际上应该使用 `references` 和 `includes` 来指示您将在查询中使用该表。所以它应该类似于`Today.where(:user_id =&gt; current_user.id).includes(:tasks).references(:tasks).merge(Task.o‌ rder(:priority)).fir‌ st` (2认同)