代码之家  ›  专栏  ›  技术社区  ›  Hakanai

当使用has many时,是否有方法脱离默认的\u范围?

  •  2
  • Hakanai  · 技术社区  · 15 年前

    我有一个像树一样的模型 除一种情况外的所有情况 ,我想将结果范围限定为只返回根。

    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 结果永远找不到孩子。但是 哈萨尔多 只有 就“违约”行为而言,我认为这是需要突破范围的地方。 默认范围 是相当合理的。

    那么,有没有什么好的方法来解决这个特定的问题呢?

    下面是一个我不太喜欢的,因为它使用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() 说实话,也不是很干。它只是要求在不使用作用域的地方出现一个bug。

    2 回复  |  直到 13 年前
        1
  •  2
  •   Michael Durrant    13 年前

    试用使用 Licence.unscoped.find()

    顺便说一句 文件 ActiveRecord::Base.unscoped 说的是链子 unscoped 用一个名字 scope 方法无效。
    建议使用 无范围的 因为链接 无范围的 用一个名字 范围 不起作用。如果“sent”(下面)是一个命名的\作用域,则以下两个语句是相同的。

    Message.unscoped.sent
    Message.sent  
    

    Fyi Rails 2也有 with_exclusive_scope 这是有帮助的。

        2
  •  0
  •   John Topley    15 年前

    你不能利用 :conditions 协会的选择?像这样:

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