Rails: Почему with_exclusive_scope защищен? Любая хорошая практика о том, как его использовать?
Учитывая модель с 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 ответа
К вашему сведению, для тех, кто ищет способ Rails3 сделать это, вы можете использовать unscoped
метод:
Ticket.unscoped.all
избежать 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
Вы также можете украсить свою модель 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
Примечание: Кроме того, рассмотрите возможность использования более идиоматического имени столбца datetime, например ends_at
вместо end_date
,
Вы должны заключить защищенный метод в метод модели, что-то вроде:
class Ticket < ActiveRecord::Base
def self.all_tickets_from(user)
with_exclusive_scope{user.tickets.find(:all)}
end
end