Переопределение Rails default_scope - PullRequest
143 голосов
/ 02 декабря 2009

Если у меня есть модель ActiveRecord :: Base с областью действия по умолчанию:

class Foo < ActiveRecord::Base

  default_scope :conditions => ["bar = ?",bar]

end

Есть ли способ сделать Foo.find без , используя условия default_scope? Другими словами, вы можете переопределить область по умолчанию?

Я бы подумал, что использование «по умолчанию» в названии предполагает, что оно может быть переопределенным, в противном случае оно будет называться как global_scope, верно?

Ответы [ 8 ]

210 голосов
/ 12 ноября 2010

In Rails 3:

foos = Foo.unscoped.where(:baz => baz)
148 голосов
/ 02 декабря 2009

Краткий ответ: не используйте default_scope, если это не нужно. Вам, вероятно, будет лучше с именованными областями. С учетом сказанного вы можете использовать with_exclusive_scope для переопределения области по умолчанию, если вам нужно.

Посмотрите на этот вопрос для более подробной информации.

103 голосов
/ 02 августа 2012

Если все, что вам нужно, это изменить порядок, определенный в default_scope, вы можете использовать метод reorder .

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
46 голосов
/ 16 июля 2014

Поскольку 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

В настоящее время возможно unscope, например: :where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having.

Но все же , пожалуйста, избегайте использования default_scope, если можете . Это для вашего же блага.

14 голосов
/ 02 декабря 2009

Вы можете переопределить область по умолчанию, используя метод with_exclusive_scope. Итак:

foos = Foo.with_exclusive_scope { :conditions => ["baz = ?", baz] }
5 голосов
/ 13 августа 2014

С Rails 3+ вы можете использовать комбинацию unscoped и merge:

# 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)
5 голосов
/ 16 февраля 2012

Rails 3 default_scope не переопределяется, как в 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, порядок в области WINS по умолчанию. Я удаляю все свои default_scopes и кодирую это явно везде.

Pitfall Rails3!

2 голосов
/ 26 апреля 2015

Ну, вы всегда можете использовать старый фаворит find_by_sql с полным запросом. Например: Model.find_by_sql («ВЫБЕРИТЕ * ИЗ МОДЕЛЕЙ, ГДЕ id = 123»)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...