web-dev-qa-db-ja.com

Ruby on Railsの関連付けを通じてhas_manyを注文するにはどうすればよいですか?

次のARモデルを考えて、タスクへのハンドルが与えられたときに姓でアルファベット順にユーザーをソートしたいと思います。

#user
has_many :assignments
has_many :tasks, :through => :assignments    

#assignment
belongs_to :task
belongs_to :user

#task
has_many :assignments
has_many :users, :through => :assignments

タスクを取得して、割り当てられたユーザーに移動し、ユーザーリストをアルファベット順に並べ替えます

次のように:order句をhas_many :users, :through => :assignmentsに追加できると考えています。

#task.rb
has_many :assignments
has_many :users, :through => :assignments, :order => 'last_name, first_name'

ただし、これは機能しません。

タスクが与えられたときにlast_nameでユーザーを並べ替えるにはどうすればよいですか?

58
rswolff

条件引数はRails 4で廃止されているため、スコープブロックを使用する必要があります。

has_many :users, -> { order 'users.last_name, users.first_name' }, :through => :assignments
69
Daniel

Rails 3.xバージョン:

has_many :users, :through => :assignments, :order => 'users.last_name, users.first_name'

更新:これはRails 3.x(おそらくそれ以前)でのみ機能します。4+については、他の回答を参照してください。

37
Martin T.

M.G.Palmer'sアプローチはうまくいきますが、テーブル名が関係します。より良い方法があります:

has_many :users, :through => :assignments, :order => [ :last_name, :first_name ]
12
denis.peplin

これはあなたのために働くでしょうか?

# User.rb

class User < ActiveRecord::Base
 default_scope :order => 'last_name ASC'
 ...
end

ソートが異なる必要がある場合のために、他の名前付きスコープを定義できます。

http://ryandaigle.com/articles/2008/11/18/what-s-new-in-Edge-Rails-default-scoping

7
Antony Sastre

これは私のために働く(Rails 4.2)

スルーマップでの順序の適用は保持されません。別名:これは、ジャンルを順序付けるのに十分ではありません。

has_many    :disk_genre_maps,
            -> {order('disk_genre_map.sort_order')},
            :inverse_of => :disk,
            :dependent  => :destroy,
            :autosave   => true


has_many    :genres,    # not sorted like disk_genre_maps
            :through    => :disk_genre_maps,
            :source     => :genre,
            :autosave   => true

したがって、インスタンスごとにこれを上書きします。

def genres  # redefine genres per instance so that the ordering is preserved
    self.disk_genre_maps.map{|dgm|dgm.genre}
end

割り当てのためにそれを機能させるには、これは次のようなものでなければなりません(テストされていません)

def genres= some_genres
    self.disk_genre_maps = some_genres.map.with_index do |genre, index|
        DiskGenreMap.new(disk:self, genre:genre, sort_order:index)
    end
end
6
edx

Rails(5.0.0.1)を使用しており、group_usersを介して多くのユーザーがいるモデルグループでこの構文を使用してソートを行うことができます。

# Associations.
has_many :group_users
has_many :users, -> { order(:name) }, through: :group_users

動作する必要に応じてコードを調整します。

4
Ricardo Emerson

また、割り当てテーブルに新しい「sort_order」列を作成し、次のようなデフォルトのスコープを追加することもできます

default_scope { order('sort_order desc')}

割り当てモデルに。

2
Yogzzz

has_many:users、-> {order(:last_name、:first_name)}、:through =>:assignments、source: 'user'

0
user223697