Rails 4 关系未排序:'has_many' 带默认作用域的关联,'includes' 和 'order' 链接在一起

Rails 4 Relation is not being sorted: 'has_many' association w/ default scope, 'includes' and 'order' chained together

我正在尝试使用默认范围对模型 QuizCategoryWeight 施加排序顺序。目标是让@possible_answer.quiz_category_weights 到 return 的权重按排序顺序排列。

更新: 我已经将问题缩小到默认范围似乎对我有用的事实,只要它们只有 'order' 方法,但当 'includes' 方法与 'order' 方法链接时则不会。但是,这种链接确实适用于命名范围。

会不会是我的开发环境?或者这可能是 Rails 中的错误?

我正在使用 windows,所以这可能就是问题所在。目前在 ruby 2.0.0p645 (2015-04-13) [i386-mingw32] 和 Rails 4.2.4...

以下使用 QuizCategoryWeight 的默认范围似乎不起作用:

class QuizCategoryWeight < ActiveRecord::Base
    #trying to use a default scope, but does not work
    default_scope { includes(:quiz_category).order("quiz_categories.sort_order") }

    belongs_to :possible_answer, inverse_of: :quiz_category_weights,
        class_name: 'QuizPossibleAnswer', foreign_key: 'possible_answer_id'

    belongs_to :quiz_category

end

class QuizPossibleAnswer < PossibleAnswer
    has_many :quiz_category_weights, 
        #does not work whether the line below is used or not
        ->{ includes(:quiz_category).order("quiz_categories.sort_order") }, 
        inverse_of: :possible_answer, 
        dependent: :destroy, 
        foreign_key: 'possible_answer_id' 
end

class QuizCategory < ActiveRecord::Base
    default_scope { order :sort_order }
end  

有了命名范围,它确实有效。但是,这意味着我必须向我的表单构建器添加一个参数才能使用集合 'f.object.quiz_category_weights.sorted'.

class QuizCategoryWeight < ActiveRecord::Base
    # named scope works...
    scope :sorted,  ->{ includes(:quiz_category).order("quiz_categories.sort_order") }

    belongs_to :possible_answer, inverse_of: :quiz_category_weights,
        class_name: 'QuizPossibleAnswer', foreign_key: 'possible_answer_id'

    belongs_to :quiz_category

end

class QuizPossibleAnswer < PossibleAnswer
    has_many :quiz_category_weights, 
        inverse_of: :possible_answer, 
        dependent: :destroy, 
        foreign_key: 'possible_answer_id' 
end

我认为在 Rails 框架或我的 windows 版本中使用具有默认范围的 'includes' 存在错误。

不过,我发现使用 'joins' 确实有效。我没有使用 QuizCategory 中的任何其他属性,因此它也更适合我的用例:我只想使用连接的 table.

中的 'sort_order' 属性进行排序

固定码为:

class QuizCategoryWeight < ActiveRecord::Base
    default_scope { joins(:quiz_category).order("quiz_categories.sort_order") }

    belongs_to :quiz_category
end

为关系引入了 includes 方法,以提供 Rails 减少数据库查询的提示。它说:当你获取类型A的对象时,还要获取关联对象,因为我稍后需要它们,它们不应该一个一个地获取(the N+1 queries problem)

includes 最初是通过两个数据库查询实现的。首先是所有 A,然后是所有具有 A 中的一个 ID 的 B。现在 includes 经常使用 sql 连接来只有一个数据库查询。但这是一个内部优化。 这个概念是面向对象的,你想要来自 A 的对象,然后你通过 A 检索 B。所以我认为,如果你将包含的 B 的顺序设置回 A,你所做的比原始 includes.