update rails query left includes has_and_belongs_to_many active ruby-on-rails ruby activerecord

ruby on rails - rails - La búsqueda de ActiveRecord comienza con



rails sql query (8)

Ahora es 2012, pensé que lanzaría esta actualización a la respuesta de Narsk.

named_scope convirtió en simple scope un tiempo, por lo que el ejemplo se convierte

class User scope :name_starts_with, lambda {|str| :conditions => [''lower(name) like ?'', "#{str.downcase}%"] } end

Nota: eliminé el primer % de la solución de narsk ya que el OP está pidiendo una coincidencia ''starts_with'' no una ''contains''.

Ahora puedes hacer cosas como

User.name_starts_with("b").each do {|bs| puts bs.inspect} bob = User.name_starts_with("bob").first … etc

Tenga en cuenta que los ámbitos siempre devuelven colecciones , nunca resultados individuales. Eso me sorprendió cuando recién comencé con AR y todavía logro olvidarlo de vez en cuando.

Pregunta realmente simple: ¿cómo hago una búsqueda para encontrar todos los registros donde el nombre comienza con una cierta cadena en ActiveRecord. He visto todo tipo de bits en Internet donde se usan cláusulas LIKE SQL similares, pero por lo que he escuchado, esa no es la forma "correcta" de hacerlo.

¿Hay un camino ''apropiado'' de Rails?


Dave Sag, supongo que la primera parte de tu código debería ser

class User scope :name_starts_with, (lambda do |str| {:conditions => [''lower(name) like ?'', "#{str.downcase}%"]} end ) end


Descargo de responsabilidad: Soy nuevo en Ruby and Rails, y todavía estoy tratando de aprender la Manera de Ruby para hacer cosas, pero he estado codificando para más de la mitad de mi vida, y profesionalmente durante una década. DRY es un concepto con el que estoy muy familiarizado. Así es como lo implementé. Es muy similar a la respuesta de Narsk, que creo que también es buena.

# name_searchable.rb # mix this into your class using # extend NameSearchable module NameSearchable def search_by_prefix (prefix) self.where("lower(name) LIKE ''#{prefix.downcase}%''") end end

Y luego en tu modelo:

class User < ActiveRecord::Base extend NameSearchable ... end

Y luego cuando quieras usarlo:

User.search_by_prefix(''John'') #or User.search_by_prefix("#{name_str}")

Una cosa para llamar:

Las bases de datos relacionales tradicionales no son extremadamente buenas para satisfacer este tipo de consultas. Si está buscando una implementación altamente receptiva que no mate sus bases de datos bajo carga, probablemente debería usar una solución que se adapte a su propósito. Los ejemplos populares incluyen Solr o Sphinx, y hay muchos otros también. Con esta implementación, dado que DRY, podría sustituir la implementación con un indexador separado en un solo lugar y estaría listo para rockear.


Muy parecido a la respuesta anterior, pero si está utilizando ActiveRecord ... 2.1 o superior, podría usar un alcance con nombre que le permita usar este "buscador" en los registros recuperados a través de asociaciones:

class User named_scope :with_name_like, lambda {|str| :conditions => [''lower(name) like ?'', %(%#{str.downcase}%)] } end

Usado como:

User.with_name_like("Samson")

(devuelve todos los usuarios en su base de datos con un nombre como "Samson").

O:

some_association.users.with_name_like("Samson")

Los usuarios de esa asociación solo con un nombre como "Samson".


No quiero escribir un alcance cada vez que quiero ver si una columna específica se inicia_ con un prefijo.

# initializers/active_record_initializers.rb class ActiveRecord::Base # do not accept a column_name from the outside without sanitizing it # as this can be prone to sql injection def self.starts_with(column_name, prefix) where("lower(#{column_name}) like ?", "#{prefix.downcase}%") end end

Llámalo así:

User.starts_with(''name'', ''ab'').limit(1)


Recomiendo encarecidamente el complemento Searchlogic .

Entonces es tan fácil como:

@search = Model.new_search(params[:search]) @search.condition.field_starts_with = "prefix" @models = @search.all

Searchlogic es lo suficientemente inteligente, como ActiveRecord, para recoger el nombre del campo en la condición starts_with . También manejará toda la paginación.

Este método ayudará a prevenir la inyección de SQL y también será independiente de la base de datos. Searchlogic termina manejando la búsqueda de manera diferente según el adaptador de base de datos que esté utilizando. ¡Tampoco tiene que escribir ningún SQL!

Searchlogic tiene una gran documentación y es fácil de usar (soy nuevo en Ruby and Rails). Cuando me quedé atrapado, el autor del complemento incluso respondió un correo electrónico directo en pocas horas y me ayudó a solucionar mi problema. No puedo recomendar Searchlogic lo suficiente ... como puedes ver.


Si buscas hacer la búsqueda en la base de datos, entonces necesitarás usar SQL.

Y, por supuesto, deberá hacer la búsqueda en la base de datos; de lo contrario, deberá cargar todos los objetos en Ruby (lo cual no es bueno).

Entonces, necesitarás algo como

MyModel.find(:all, :conditions => ["field LIKE ?", "#{prefix}%"])

donde el prefix es una variable con la cadena que estás buscando.

En Rails 3.0+ esto se convierte en:

MyModel.where("field LIKE :prefix", prefix: "#{prefix}%")


Una sintaxis muy escueta para lo mismo podría ser:

Model.where(field: (''prefix''...''prefiy''))

Esto rinde:

WHERE ( field >= ''prefix'' AND field < ''prefiy'')

Esto hace el trabajo ya que ''prefiy'' es la primera cadena alfabéticamente que no coincide con el prefijo '' prefijo '' .

No lo usaría normalmente (iría por squeel o por saqueo), pero puede salvarle el día si por alguna razón tiene que apegarse a la sintaxis hash para las consultas ...