我正在使用祖先 gem在树中构建一些组。同时,我使用acts_as_list 将组保持在排序列表中的同一树级别。给定以下模型:
class Group < ActiveRecord::Base
acts_as_tree
acts_as_list :scope => "ancestry"
named_scope :parentable, :conditions => "NOT type = 'PriceGroup'"
named_scope :without, lambda { |ids| { :conditions => ['id NOT IN (?)', ids] }}
default_scope :order => "groups.position ASC, groups.name ASC"
end
这非常符合预期,例如,我用来@group.path
在管理界面顶部生成面包屑导航。生成的 SQL 没问题,面包屑按树的深度排序。至少对于开发环境来说是这样。
在生产中,它看起来完全不同:跟踪生成的 SQL 我发现不是祖先的path
生成结果顺序,而是我default_scope
的接管。
所以我修复了我的模型,通过覆盖忽略默认范围path
:
# remove default scope to not change path sorting
def path
self.class.send :with_exclusive_scope do
super
end
end
但是,虽然这从我default_scope
的开发中删除了位置范围,但在生产中仍然完全被忽略了。跟踪生产中的 SQL,我没有看到祖先的深度排序,而是从我的default_scope
.
更新:由于我最初对“修补”该path
方法的想法有点愚蠢(敲敲:它不是继承的,它是动态定义的),我尝试了以下方法仍然无济于事:
# remove default scope to not change path sorting
def path_with_exclusive_scope
self.class.send :with_exclusive_scope do
path_without_exclusive_scope
end
end
alias_method_chain :path, :exclusive_scope
在开发中调用path
生成的SQL如下:
SELECT *
FROM "groups"
WHERE ("groups"."id" IN (5,64))
ORDER BY (case when ancestry is null then 0 else 1 end), ancestry
与之相比,这里是生产中生成的 SQL:
SELECT *
FROM `groups`
WHERE (`groups`.`id` IN (8,49))
ORDER BY groups.position ASC, groups.name ASC
开发使用 SQLite,而生产使用 MySQL——但我认为这不是关键的区别。