web-dev-qa-db-ja.com

Rails 3に含まれる要素を注文する方法

todayに多数のtasksがあるモデル関係があります

ユーザーのtodayオブジェクトを取得し、tasksを含めて、それらをすべてJsonにレンダリングしようとしています。 respond_with blockはhtmlページのレンダリングにも使用されるため、tasksオブジェクト内のtodayを注文することを決定するまで、これはすべてうまくいきました。 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の方法を望んでいました。

41
royvandewater

Todayモデルでこれを試してください:

has_many :tasks, :order => 'priority DESC'

編集:以下のコメントで述べたように、Rails 4+)では、これは次のようになります。

has_many :tasks, -> { order(:priority => :desc) }

詳細はこちら

65
khelll

直接的な解決策は、tasksの前にpriorityテーブル名を含めることです。

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

また、Userモデルにhas_many: todaysを追加してwhere句を破棄し、次の操作を実行できます。

current_user.todays.includes(:tasks).order('tasks.priority').first
# or
current_user.todays.joins(:tasks).includes(:tasks).merge(Task.order(:priority)).first

ただし、優先順位による順序付けのみ/常に必要で、他の異なる順序付けが必要ない場合は、has_many :tasksorderを追加する方が簡単です。

44
Jack