私はツリーのようなモデルを持っていますが、1 つを除くすべての状況で、ルートのみを返すように結果をスコープしたいと考えています。
class Licence < ActiveRecord::Base
default_scope :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences
end
default_scope
License に関連付けられているさまざまなモデル (約 4 つあります) と、find() を使用するコードは特別なことをする必要がないため、使用は素晴らしいアイデアのように思えました。これが素晴らしいアイデアではない理由は、デフォルトのスコープが にも適用されhas_many
、その結果、子が見つからないためです。しかし、これは範囲外にする必要has_many
がある唯一の場所なので、「デフォルト」の動作に関する限り、これdefault_scope
は非常に合理的だと思います。
では、この特定の問題を回避する良い方法はありますか?
これは、ほとんど些細なクエリに SQL を使用するため、私があまり好きではないものです。
has_many :nested_licences, :class_name => 'Licence', :dependent => :destroy,
:finder_sql => 'SELECT l.* FROM licences l WHERE l.parent_licence_id = #{id}',
:counter_sql => 'SELECT COUNT(l.*) FROM licences l WHERE l.parent_licence_id = #{id}'
または、名前付きスコープをモデルからの関連付けに適用する方法はありますか? たとえば、このナンセンスコードの行に沿った何か:
class Licence < ActiveRecord::Base
named_scope :roots, :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences, :scope => :roots # a :scope option doesn't really exist
end
私もこれを行うことができることを知っています:
class Licence < ActiveRecord::Base
named_scope :roots, :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences, :conditions => { :parent_licence_id, nil }
end
しかし、それは実際にはあまり DRY ではありません。正直に言うと、実際にすべてのクエリを実行するLicence.roots.find()
代わりに、Licence.find()
それほど DRY ではありません。スコープが使用されていない場所でバグが発生することを求めているだけです。