【问题标题】:How do I order a has_many through association in Ruby on Rails?如何在 Ruby on Rails 中通过关联订购 has_many?
【发布时间】:2011-01-13 10:04:20
【问题描述】:

鉴于以下 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 对用户进行排序?

【问题讨论】:

    标签: ruby-on-rails has-many-through


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我正在使用 Rails (5.0.0.1),并且可以在我的模型组中使用此语法进行排序,该组通过 group_users 拥有许多用户:

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

      根据您的需要调整代码。

      【讨论】:

        【解决方案3】:

        Rails 3.x 版本:

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

        更新:这只适用于 Rails 3.x(可能在此之前)。对于 4+,请参阅其他答案。

        【讨论】:

        • 对我也很好。干净的解决方案,不会像第一个答案那样影响排序模型的其他功能。
        • 不工作,它说:order is not a key。以下拒绝的答案是有效的。
        【解决方案4】:

        这对我有用(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
        

        【讨论】:

          【解决方案5】:

          由于 Rails 4 不推荐使用条件参数,因此应该使用范围块:

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

          【讨论】:

          • 目前在 Rails 4 中似乎存在一个错误,github.com/rails/rails/issues/17904 "在 Rails 4.0 中,order 子句被忽略。在 Rails 4.1 中,生成了无效的 SQL。"
          • 它甚至没有给我,只是完全忽略了没有消息的订单子句。
          【解决方案6】:

          您还可以在分配表上创建一个新的“排序顺序”列,并添加一个默认范围,例如

          default_scope { order('sort_order desc')}
          

          到您的分配模型。

          【讨论】:

            【解决方案7】:

            M.G.Palmer's 方法效果很好,但是涉及到表名。有更好的方法:

            has_many :users, :through => :assignments, :order => [ :last_name, :first_name ]
            

            【讨论】:

            • 但是如果顺序是由连接表决定的呢?例如分配...但没有定义分配的默认范围..
            【解决方案8】:

            这对你有用吗?

            # 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

            【讨论】:

            • 很抱歉提出一个老问题,但这可能与未来的读者有关:某些插件(例如 acts_as_list)不能与 default_scope 一起正常工作。
            • 也遇到了这个问题,因为我遇到了类似的问题,但需要对 :through 表中的字段进行排序 - 令人敬畏的是 default_scope 也适用于 :through 表,并且通过检索记录这种关系将尊重秩序。
            • 拥有default_scope 是一种非常糟糕的做法。有很多关于这个主题的文章,例如:piechowski.io/post/why-is-default-scope-bad-rails
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-01-14
            • 2010-12-28
            • 2012-06-12
            • 1970-01-01
            • 2012-04-01
            • 2011-04-21
            • 1970-01-01
            相关资源
            最近更新 更多