祖先の宝石を使用して、ツリー内のいくつかのグループを構築しています。同時に、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 をトレースすると、祖先の深さの順序はわかりませんが、代わりに my からの位置の順序が表示されます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 を使用しますが、それがここでの決定的な違いだとは思いません。