rails ruby-on-rails-3 activerecord class-method scopes

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.