我有一个树状模型,在除一种之外的所有情况下,我都希望将结果范围限定为仅返回根。
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
似乎是一个很棒的想法,因为与许可证关联的各种模型(大约有 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
但这真的不是很干。Licence.roots.find()
老实说,实际上必须通过而不是做每一个查询Licence.find()
也不是很干。它只是要求在不使用范围的地方发生错误。