47 votes

Rails: Pourquoi with_exclusive_scope est-il protégé? Toute bonne pratique sur la façon de l'utiliser?

Un modèle avec *default_scope* pour filtrer toutes les entrées obsolètes:

# == 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

Maintenant, je veux obtenir quelque billet. Dans ce cas *with_exclusive_scope* est le chemin à parcourir, mais cette méthode est-elle protégée? Seulement cela fonctionne:

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

Une sorte de hack, n'est-ce pas? Alors, quelle est la bonne façon de l'utiliser? Surtout lorsque vous traitez avec les associations, c'est encore pire (étant donné qu'un utilisateur a de nombreux billets):

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

C'est tellement laid!!! - ne peut pas être les rails-les de façon!?

175voto

brad Points 11382

Pour votre information, si vous recherchez la méthode Rails3, vous pouvez utiliser la méthode unscoped :

 Ticket.unscoped.all
 

34voto

Ryan McGeary Points 76053

Évitez default_scope si possible. Je pense que vous devriez vraiment re-demandez-vous pourquoi vous avez besoin d'un default_scope. La lutte contre une default_scope est souvent plus problématique que ça vaut le coup et il ne doit être utilisé que dans de rares cas. Aussi, à l'aide de default_scope n'est pas très révélateur lors de billet d'associations sont accessibles à l'extérieur du modèle de Billet (par exemple, "j'ai appelé account.tickets. Pourquoi ne sont pas mes billets il y a?"). C'est en partie la raison pour laquelle with_exclusive_scope est protégé. Vous devriez goûter quelques vinaigre de syntaxe lorsque vous avez besoin de l'utiliser.

Comme une alternative, utiliser un gem/plugin comme pacecar qui ajoute automatiquement utile named_scopes à vos modèles, vous donnant plus révélateur de code partout. Par Exemple:

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

Vous pouvez également décorer votre modèle Utilisateur pour rendre le code plus propre:

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

Remarque: en outre, envisager d'utiliser un plus idiomatiques colonne datetime nom comme ends_at au lieu de end_date.

20voto

Vlad Zloteanu Points 5730

Vous devez encapsuler la méthode protégée dans une méthode de modèle, comme suit:

 class Ticket < ActiveRecord::Base
  def self.all_tickets_from(user)
    with_exclusive_scope{user.tickets.find(:all)}
  end
end
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X