ruby on rails 3 - ActiveRecord Rails 3 método de alcance vs clase
ruby scope (2)
Como aludió en su respuesta, una diferencia entre el alcance y el método de clase es que los ámbitos se evalúan cuando se carga la clase. Esto puede conducir a un resultado inesperado.
Por ejemplo,
class Post < ActiveRecord::Base
scope :published_earlier, where(''published_at < ?'', Date.today)
end
es propenso al error La forma correcta es usar un lambda
class Post < ActiveRecord::Base
scope :published_earlier, -> { where(''published_at < ?'', Date.today) }
end
El bloque Lambda es evaluado perezosamente. Entonces Date.today se ejecuta cuando llamas al alcance, no cuando se evalúa la clase.
Si usa un método de clase, entonces no necesita usar lambda.
class Post < ActiveRecord::Base
def self.published_earlier
where(''published_at < ?'', Date.today)
end
end
Porque con el método de clase, el código se ejecuta en el momento de la llamada al método.
Soy nuevo en la nueva interfaz de consulta de ActiveRecord, así que todavía estoy averiguando cosas.
Esperaba que alguien pudiera explicar la diferencia entre utilizar un scope
en un modelo ActiveRecord y simplemente usar un método de clase (es decir, self.some_method
)
Por lo que puedo deducir, siempre se espera que un alcance devuelva una relación, mientras que un método de clase no necesariamente tiene que hacerlo. ¿Es esto cierto?
Por ejemplo, pensé que tendría sentido hacer algo como:
class Person
scope :grouped_counts, group(:name).count
end
Pero esto no funciona. Me sale este error:
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
Sin embargo, funciona como un método de clase
def self.grouped_counts
group(:name).count
end
Me interesa conocer las opiniones de las personas sobre cuándo usar los ámbitos y cuándo usar los métodos de clase. ¿Estoy en lo cierto al suponer que un ámbito siempre debe devolver una relación, pero un método de clase puede devolver lo que quiera?
Hubo una mayor diferencia en Rails 2.x, ya que named_scopes no ejecutó sus consultas (por lo que podría encadenarlas), mientras que los métodos de clase generalmente ejecutaron las consultas (por lo que no podría encadenarlas), a menos que haya ajustado manualmente su consulta en un scoped(...)
llamada.
En Rails 3, todo devuelve una relación ActiveRecord::Relation
hasta que necesite los resultados reales, por lo que los ámbitos pueden encadenarse a métodos de clase y viceversa (siempre que los métodos de clase devuelvan objetos ActiveRecord::Relation
, no algún otro tipo de objeto (como un recuento)).
En general, utilizo entradas de scope
para líneas simples para filtrar mi conjunto de resultados. Sin embargo, si estoy haciendo algo complicado en un "alcance" que puede requerir lógica detallada, lambdas, líneas múltiples, etc., prefiero usar un método de clase. Y como atrapaste, si necesito devolver conteos o algo así, utilizo un método de clase.