使用has_many时有没有办法打破default_scope?

时间:2010-07-07 06:41:50

标签: ruby-on-rails tree scope has-many default-scope

我有一个树状模型,在所有情况但只有一个中,我想将结果范围仅返回根。

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非常合理。< / p>

那么有什么好方法可以解决这个具体问题吗?

这是我不太喜欢的一个,因为它使用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()进行每个查询都不是很干,说实话。它只是要求在不使用范围的情况下发生错误。

2 个答案:

答案 0 :(得分:2)

尝试使用Licence.unscoped.find()

不过 - 顺便说一下 - ActiveRecord::Base.unscoped的文档说明使用命名unscoped方法链接scope无效。
建议使用unscoped的阻止形式,因为将unscoped与名为scope的链接不起作用。如果“sent”(下面)是named_scope,则以下两个语句是相同的。

Message.unscoped.sent
Message.sent  

fyi rails 2也有with_exclusive_scope,这可能会有所帮助。

答案 1 :(得分:0)

你不能在关联中使用:conditions选项吗?像这样:

has_many :nested_licences, :class_name => 'Licence',
         :dependent => :destroy, :conditions => "parent_licence_id = #{id}"