私は、Node モデルのすばらしいネストされたセットを介して表される組織階層を持っています。すばらしい、うまく機能する、更新には費用がかかりますが、検索は非常に効率的です。
各 Node モデルには他のモデルの has_many があります。それらを Foo と Bar と呼びましょう。
class Node < ActiveRecord::Base
acts_as_nested_set
has_many :foos
has_many :bars
end
class Foo < ActiveRecord::Base
belongs_to :node
end
現在のノードから見下ろす、特定のサブツリーのすべての foo または bar を検索したいことがよくあります。素朴に、私はできる:
@foos = @node.self_and_descendants.collect(&:foos).compact
N+1 クエリを回避するために ActiveRecord .includes(:foos) を使用することもできます。私が本当に欲しいのはただ尋ねる@node.all_foos
ことなので、次のようなものを実装します:
class Node < ActiveRecord::Base
def all_foos
Foo.where(node_id: self_and_descendants.pluck(:id))
end
# More efficient?
def all_foos_alternately
Foo.where(node_id: self_and_descendants.includes(:foos).pluck(:id))
end
end
しかし、たとえば、私が foos と bar だけでなく、それ以上のものを「収集」したいとしましょう。たとえば、このモデルを 6 つまたは 12 個持っているとしましょう。現在、Node クラスまたはいくつかの lib に all_* メソッドの束を散らかしています。
ノードを引数として受け入れ、そのサブツリーのすべての foos/bars を返すクラス メソッドを foos と bars に定義する必要がありますか? ただし、foo と bar は node.self_and_descendants を理解している必要があります。
または、Foo クラス メソッドはノードのコレクションを受け入れることができ、ネストされた set メソッドを意識する必要はありませんが、その場合、経由node.all_foos
などの簡単なインターフェイスが失われます。
ここで見逃しているパターンまたはメソッドは何ですか? method_missingを介してキャッチオールを実装しnode.all_*
て遊んだことがありますが、パフォーマンスの低下は気に入りません。ここで実行しようとしているのは、基本的にデータベースの検索であり、効率的で洗練されたものでなければなりません。