Je suis nouveau dans la nouvelle interface de requête d'ActiveRecord, je tiens toujours à trouver des choses.
J'espérais que quelqu'un puisse expliquer la différence entre l'utilisation d'un scope
dans un modèle Activerecord et d'utiliser simplement une méthode de classe (c'est-à-dire self.some_method
)
D'après ce que je peux rassembler, une portée est toujours censée renvoyer une relation, alors qu'une méthode de classe n'a pas nécessairement besoin. Est-ce vrai?
Par exemple, je pensais qu'il serait logique de faire quelque chose comme:
class Person
scope :grouped_counts, group(:name).count
end
Mais cela ne fonctionne pas. Je reçois cette erreur:
ArgumentError: Unknown key(s): communicating, failed, matched, unmatched
from /Users/bradrobertson/.rvm/gems/Ruby-1.9.2-p180@influitive/gems/activesupport-3.0.5/lib/active_support/core_ext/hash/keys.rb:43:in `assert_valid_keys'
from /Users/bradrobertson/.rvm/gems/Ruby-1.9.2-p180@influitive/gems/activerecord-3.0.5/lib/active_record/relation/spawn_methods.rb:110:in `apply_Finder_options'
from /Users/bradrobertson/.rvm/gems/Ruby-1.9.2-p180@influitive/gems/activerecord-3.0.5/lib/active_record/named_scope.rb:110:in `block in scope'
from (irb):48
from /Users/bradrobertson/.rvm/gems/Ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/Rails/commands/console.rb:44:in `start'
from /Users/bradrobertson/.rvm/gems/Ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/Rails/commands/console.rb:8:in `start'
from /Users/bradrobertson/.rvm/gems/Ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/Rails/commands.rb:23:in `<top (required)>'
from script/Rails:6:in `require'
from script/Rails:6:in `<main>'
r
Il fonctionne cependant comme une méthode de classe
def self.grouped_counts
group(:name).count
end
Je suis intéressé de connaître les pensées des peuples sur quand utiliser des étendues et quand utiliser des méthodes de classe. Suis-je correct pour supposer qu'une portée doit toujours renvoyer une relation, mais une méthode de classe peut retourner ce qu'il veut?
AS Dylan fait allusion à sa réponse, une différence entre la portée et la méthode de la classe est que les scopes sont évalués lorsque la classe est chargée. Cela peut conduire à un résultat inattendu.
Par exemple,
class Post < ActiveRecord::Base
scope :published_earlier, where('published_at < ?', Date.today)
end
est sujette à l'erreur. La bonne façon est d'utiliser une lambda
class Post < ActiveRecord::Base
scope :published_earlier, -> { where('published_at < ?', Date.today) }
end
Le bloc Lambda est évalué paresseusement. Donc, date.today est exécutée lorsque vous appelez la portée, pas lorsque la classe est évaluée.
Si vous utilisez une méthode de classe, vous n'avez pas besoin d'utiliser Lambda.
class Post < ActiveRecord::Base
def self.published_earlier
where('published_at < ?', Date.today)
end
end
Parce que avec la méthode de classe, le code est exécuté au moment de l'appel de la méthode.