ruby on rails - query - Rails: ¿por qué está protegido con_s_sclusivo_scope? ¿Alguna buena práctica sobre cómo usarlo?
raw query ruby on rails (3)
Debe encapsular el método protegido dentro de un método modelo, algo así como:
class Ticket < ActiveRecord::Base
def self.all_tickets_from(user)
with_exclusive_scope{user.tickets.find(:all)}
end
end
Dado un modelo con default_scope para filtrar todas las entradas desactualizadas:
# == 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
Ahora quiero obtener cualquier boleto. En este caso, with_exclusive_scope es el camino a seguir, pero ¿este método está protegido? Solo esto funciona:
Ticket.send(:with_exclusive_scope) { find(:all) }
Una especie de truco, ¿no? Entonces, ¿cuál es la forma correcta de usar? Especialmente cuando se trata de asociaciones, se está empeorando (dado que un usuario tiene muchas entradas):
Ticket.send(:with_exclusive_scope) { user.tickets.find(:all) }
¡Eso es tan feo! - ¡No puede ser el camino de los carriles !?
Para su información, para cualquiera que esté buscando la forma de hacerlo de Rails3, puede usar el método sin unscoped
:
Ticket.unscoped.all
Evite default_scope
si es posible . Creo que realmente debería volver a preguntarse por qué necesita un default_scope
. Contrarrestar un default_scope
suele ser más desordenado de lo que vale y solo debería usarse en casos excepcionales. Además, usar default_scope
no es muy revelador cuando se accede a las asociaciones de tickets fuera del modelo de ticket (por ejemplo, "llamé a account.tickets
. ¿Por qué mis tickets no están allí?" ). Esta es parte de la razón por la with_exclusive_scope
está protegido with_exclusive_scope
. Debes probar un poco de vinagre sintáctico cuando lo necesites.
Como alternativa, utilice una gema / complemento como el pacecar que agrega automáticamente sun_scopes útiles a sus modelos, proporcionándole un código más revelador en todas partes. Por ejemplo:
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
También puede decorar su modelo de Usuario para limpiar el código anterior:
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
Nota al ends_at
: Además, considere usar un nombre de columna de fecha y hora más idiomático como ends_at
lugar de end_date
.