¿Qué es scope / named_scope en rieles?


105

Recientemente comencé una pasantía. Mi empleador usa ruby ​​on rails y con frecuencia encuentro una nueva sintaxis que necesito buscar para comprender. Busqué en Google una buena explicación de named_scope, pero lo que he encontrado hasta ahora son principalmente publicaciones de blog que lo elogian, más bien una definición o introducción directa.

¿Qué es exactamente named_scope (ahora simplemente llamado alcance) en ruby ​​on rails?



2
Esta publicación de blog fue invaluable para mí cuando aprendí ámbitos con nombre: ryandaigle.com/articles/2008/8/20/…
Peter Brown

@notapatch el enlace está muerto, ¿tienes otro?
mbigras

Ryan Daigle: Alcance con nombre: no es solo para las condiciones, ¿lo sabe ?: web.archive.org/web/20160306110506/http://…
notapatch

Respuestas:


212

Un ámbito es un subconjunto de una colección. ¿Suena complicado? No lo es. Imagina esto:

Tienes usuarios. Ahora, algunos de esos usuarios están suscritos a su boletín. Marcó a aquellos que reciben un boletín agregando un campo a la Base de datos de usuarios (user.subscriptions_to_newsletter = true). Naturalmente, a veces desea obtener aquellos Usuarios que están suscritos a su boletín.

Por supuesto, siempre puedes hacer esto:

User.where(subscribed_to_newsletter: true).each do #something

Sin embargo, en lugar de escribir esto siempre, podrías hacer algo como esto.

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, where(subscribed_to_newsletter: true)
  #yada yada
end

Si está usando Rails 4 o más reciente , haga esto en su lugar:

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, -> { where(subscribed_to_newsletter: true) }
  #yada yada
end

Esto le permite acceder a sus suscriptores simplemente haciendo esto:

User.newsletter.each do #something

Este es un ejemplo muy simple pero, en general, los alcances pueden ser herramientas muy poderosas para facilitar su trabajo.

Consulte este enlace: Descripción de API


7
¿Puedo preguntar cuáles son las ventajas de esto en comparación con la definición de un método en la clase de usuario llamado 'usuarios suscritos'? Por ejemplo, 'def self.subscriptionsUsers self.where (: subscriptions_to_newsletter => true) end
redroot

3
@redroot, la ventaja es que la scopesintaxis es mucho más limpia, obtienes el mismo resultado pero con solo una línea
Aldo 'xoen' Giambelluca

9
@redroot Solía ​​haber una gran ventaja de eficiencia, ya que los scopes consultaban la base de datos con pereza, mientras que los métodos lo hacían con entusiasmo. En Rails 3, los métodos también se volvieron vagos, por lo que ahora la diferencia es más sintáctica. Fuente
evanrmurphy

El enlace del documento API está roto, actualice api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/…
Lohith MV

También permite usar el enlace de
Benjineer

34

El alcance en el registro activo es como los métodos de clase pero devuelven el objeto Relación, lo que significa que puede llamar a otro alcance o método de consulta de registro activo en él.

Por ejemplo, si tiene un modelo Zombie (tabla de zombies) con los métodos de alcance mencionados a continuación,

class Zombie
  scope :rotting, -> { where(rotting: true) }
  scope :fresh, -> { where('age < ?', 25) }
  scope :recent, -> { order(created_at: :desc) }
end

Y tu llamas

Zombie.rotting.fresh.recent.limit(3)

Se traduce a lo siguiente en SQL,

select "zombies.*" from "zombies" where "zombies"."rotting" = 't' and (age<20) order by create_at desc limit 3

El ejemplo anterior se basa en la sintaxis de rails 4


No puedo encontrar un ejemplo de orden (: created_at,: desc) en ninguna documentación. ¿Es posible que quisiste decir scope :recent, -> { order(created_at: :desc) }? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch


7

Los ámbitos no son más que métodos de clase.

¿Por qué usarlos?

El alcance le permite especificar consultas de uso común (se puede considerar como un acceso directo para consultas largas o de uso más frecuente) a las que se puede hacer referencia como llamadas a métodos en los objetos o modelos de asociación. Con estos ámbitos, puede utilizar todos los métodos cubiertos anteriormente, como dónde, se une e incluye. Todos los métodos de alcance devolverán un objeto ActiveRecord :: Relation que permitirá que se invoquen más métodos (como otros ámbitos).

Para definir un alcance simple, usamos el método de alcance dentro de la clase, pasando la consulta que nos gustaría ejecutar cuando se llama a este alcance:

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end

Esto es exactamente lo mismo que definir un método de clase, y el que use es una cuestión de preferencia personal:

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end

Siga el siguiente enlace para obtener una descripción completa con un ejemplo. Espero que esto ayude.

http://guides.rubyonrails.org/active_record_querying.html


3
No es exactamente lo mismo que definir un método de clase . Los métodos de clase regresan nilen pocos casos y, por lo tanto, no se pueden encadenar en determinadas condiciones.
Arslan Ali

1
  • Imagina que tienes un modelo: Persona .

Ahora imagínate:

  • Quiero a todas las personas del mundo que tienen el pelo rojo.
  • quiero a toda la gente del mundo que juega al cricket

¡Podrías obtener esas clases particulares de personas usando un visor!

Person.red_hair.cricket ## finds all people with red hair who play cricket
Person.red_hair ## finds all people with red hair
Person.cricket ## finds all people who play cricket.

Ahora que no fue tan difícil, ¿verdad?

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.