Rails: Почему with_exclusive_scope защищен? Любая хорошая практика о том, как его использовать? - PullRequest
46 голосов
/ 30 октября 2009

Для модели с default_scope для фильтрации всех устаревших записей:

# == Schema Information
#
#  id          :integer(4)      not null, primary key
#  user_id     :integer(4)      not null, primary key
#  end_date    :datetime        

class Ticket < ActiveRecord::Base
  belongs_to :user
  default_scope :conditions => "tickets.end_date > NOW()"
end

Теперь я хочу получить любой билет. В этом случае with_exclusive_scope - это путь, но защищен ли этот метод? Только это работает:

 Ticket.send(:with_exclusive_scope) { find(:all) }

Что-то вроде хака, не так ли? Так, как правильно использовать? Особенно, когда дело касается ассоциаций, становится еще хуже (учитывая, что у пользователя много билетов):

 Ticket.send(:with_exclusive_scope) { user.tickets.find(:all) }

Это так безобразно !!! - не может быть рельсовый путь!?

Ответы [ 3 ]

173 голосов
/ 08 июля 2011

К вашему сведению, для тех, кто ищет способ Rails3, вы можете использовать метод unscoped:

Ticket.unscoped.all
34 голосов
/ 30 октября 2009

Избегайте default_scope, если возможно . Я думаю, что вы действительно должны спросить себя, зачем вам нужен default_scope. Противодействие default_scope часто сложнее, чем оно стоит, и его следует использовать только в редких случаях. Кроме того, использование default_scope не очень показательно, когда к билетным ассоциациям обращаются за пределами модели Ticket (например, "Я позвонил account.tickets. Почему там нет моих билетов?" ). Это одна из причин, по которой with_exclusive_scope защищен. Вы должны попробовать синтаксический уксус , когда вам нужно его использовать.

В качестве альтернативы используйте гем / плагин, такой как pacecar , который автоматически добавляет полезные named_scopes в ваши модели, предоставляя вам более понятный код повсюду. Например:

class Ticket < ActiveRecord::Base
  include Pacecar
  belongs_to :user
end

user.tickets.ends_at_in_future # returns all future tickets for the user
user.tickets                   # returns all tickets for the user

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

Class User < ActiveRecord::Base
  has_many :tickets

  def future_tickets
    tickets.ends_at_in_future
  end
end

user.future_tickets # returns all future tickets for the user
user.tickets        # returns all tickets for the user

Примечание. Кроме того, рассмотрите возможность использования более идиоматического названия столбца даты-времени, например ends_at вместо end_date.

20 голосов
/ 30 октября 2009

Вы должны инкапсулировать защищенный метод внутри метода модели, например:

class Ticket < ActiveRecord::Base
  def self.all_tickets_from(user)
    with_exclusive_scope{user.tickets.find(:all)}
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...