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

覆盖Rails的默认范围

  •  139
  • Gareth  · 技术社区  · 15 年前

    如果我有一个带有默认范围的ActiveRecord::Base模型:

    class Foo < ActiveRecord::Base
    
      default_scope :conditions => ["bar = ?",bar]
    
    end
    

    有什么办法吗 Foo.find 没有 使用 default_scope 条件?换句话说,您可以重写默认范围吗?

    我本以为在名字中使用“默认”会建议 可重写,否则它将被称为 global_scope ,对吗?

    8 回复  |  直到 9 年前
        1
  •  147
  •   Community miroxlav    7 年前

    简短回答:不要使用 default_scope 除非你真的需要。使用命名范围可能会更好。有了这句话,你就可以 with_exclusive_scope 如果需要,可以覆盖默认范围。

    看一看 this question 了解更多详细信息。

        2
  •  203
  •   Tim Cooper    12 年前

    轨道3:

    foos = Foo.unscoped.where(:baz => baz)
    
        3
  •  101
  •   Andrew Marshall    12 年前

    如果您只需要更改 default_scope ,您可以使用 reorder method .

    class Foo < ActiveRecord::Base
      default_scope order('created_at desc')
    end
    
    Foo.reorder('created_at asc')
    

    运行以下SQL:

    SELECT * FROM "foos" ORDER BY created_at asc
    
        4
  •  44
  •   jibiel    10 年前

    自从 4.1 你可以用 ActiveRecord::QueryMethods#unscope 对抗默认范围:

    class User < ActiveRecord::Base
      default_scope { where tester: false }
      scope :testers, -> { unscope(:where).where tester: true }
      scope :with_testers, -> { unscope(:where).where tester: [true, false] }
      # ...
    end
    

    它是 currently 可能的 unscope 类似的东西: :where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having .

    但是仍然 请避免使用 default_scope 如果可以的话 . 这是为了你自己。

        5
  •  14
  •   Lucy Bain Jamund Ferguson    11 年前

    您可以使用 with_exclusive_scope 方法。所以:

    foos = Foo.with_exclusive_scope { :conditions => ["baz = ?", baz] }
    
        6
  •  5
  •   vanboom    12 年前

    Rails 3默认的_作用域似乎不会像在Rails 2中那样被覆盖。

    例如

    class Foo < ActiveRecord::Base
      belongs_to :bar
      default_scope :order=>"created_at desc"
    end
    
    class Bar < ActiveRecord::Base
      has_many :foos
    end
    
    > Bar.foos
      SELECT * from Foo where bar_id = 2 order by "created_at desc";
    > Bar.unscoped.foos
      SELECT * from Foo;  (WRONG!  removes the "has" relationship)
    > Bar.foos( :order=>"created_at asc" )  # trying to override ordering
      SELECT * from Foo where bar_id = 2 order by "created_at desc, created_at asc"
    

    在我的应用程序中,使用PostgreSQL,默认范围内的排序将获胜。我将删除所有默认的\u作用域,并在任何地方显式地对其进行编码。

    陷阱轨道3!

        7
  •  5
  •   santervo    10 年前

    对于Rails 3+,您可以使用非范围和合并的组合:

    # model User has a default scope
    query = User.where(email: "foo@example.com")
    
    # get rid of default scope and then merge the conditions
    query = query.unscoped.merge(query)
    
        8
  •  2
  •   Ady Rosen    9 年前

    好吧,你总是可以用过去最喜欢的 find_by_sql 完整的查询。 例如: model.find_by_sql(“select*from models where id=123”)。