sql - por - query builder arcgis not
Rails 3 consulta ActiveRecord utilizando operadores SQL IN y SQL OR (4)
SQL sin procesar
SELECT *
FROM table
WHERE user_id in (LIST OF friend.ids) OR target in (LIST OF friends.usernames)
con cada coma de lista por separado. No sé bien las cosas de Rails ActiveRecord. Para AND, simplemente pondría una coma entre esas dos condiciones, pero no sé si
Estoy escribiendo una consulta ActiveRecord de Rails 3 utilizando la sintaxis "where", que utiliza tanto el operador SQL IN como el operador SQL OR y no puedo encontrar la manera de usarlos juntos.
Este código funciona (en mi modelo de usuario):
Question.where(:user_id => self.friends.ids)
#note: self.friends.ids returns an array of integers
pero este código
Question.where(:user_id => self.friends.ids OR :target => self.friends.usernames)
devuelve este error
syntax error, unexpected tCONSTANT, expecting '')''
...user_id => self.friends.ids OR :target => self.friends.usern...
¿Alguna idea de cómo escribir esto en Rails, o simplemente cuál debería ser la consulta SQL sin formato?
Aunque Rails 3 AR no le proporciona un operador u operador, puede obtener el mismo resultado sin bajar completamente a SQL y usar Arel directamente. Con eso quiero decir que puedes hacerlo así:
t = Question.arel_table
Question.where(t[:user_id].in(self.friends.ids).or(t[:username].in(self.friends.usernames)))
Algunos podrían decir que no es tan bonito, algunos podrían decir que es bastante simple porque no incluye SQL. De todos modos, sin duda podría ser más bonito y también tiene una joya: MetaWhere
Para obtener más información, consulte esta transmisión de rails: http://railscasts.com/episodes/215-advanced-queries-in-rails-3 y el sitio de MetaWhere: http://metautonomo.us/projects/metawhere/
ACTUALIZACIÓN: Más tarde, Ryan Bates ha hecho otro railscast sobre metawhere y metasearch: http://railscasts.com/episodes/251-metawhere-metasearch Más tarde, aunque Metawhere (y la búsqueda) se han convertido en gemas más o menos heredadas. Es decir, ni siquiera funcionan con Rails 3.1. El autor sintió que (Metawhere y búsqueda) necesitaba una reescritura drástica. Tanto que en realidad fue por una nueva joya todos juntos. El sucesor de Metawhere es Squeel. Lea más sobre el anuncio de los autores aquí: http://erniemiller.org/2011/08/31/rails-3-1-and-the-future-of-metawhere-and-metasearch/ y revise la página principal del proyecto: http://erniemiller.org/projects/squeel/ "Metasearch 2.0" se llama Ransack y puedes leer algo al respecto desde aquí: http://erniemiller.org/2011/04/01/ransack-the-library-formerly -known-as-metasearch-2-0 /
Alternativamente, puedes usar Squeel. Para mí, es más simple. Puede realizar las operaciones IN ( >>
) y OR ( |
) con la siguiente sintaxis:
Question.where{(:user_id >> my{friends.id}) | (:target >> my{friends.usernames})}
Por lo general, envuelvo mis condiciones en (...)
para garantizar el orden de funcionamiento apropiado; ambas IN ocurren antes del quirófano.
El bloque my{...}
ejecuta métodos desde el contexto self
como se definió antes de la llamada Squeel, en este caso, la Question
. Dentro del bloque Squeel, self
refiere a un objeto Squeel y no al objeto Question
( ver el archivo Readme de Squeel para más información ). Lo solucionas utilizando my{...}
envoltorio para restaurar el contexto original.
No necesita usar SQL sin formato, solo proporcione el patrón como una cadena y agregue parámetros con nombre:
Question.where(''user_id in (:ids) or target in (:usernames)'',
:ids => self.friends.ids, :usernames => self.friends.usernames)
O parámetros posicionales:
Question.where(''user_id in (?) or target in (?)'',
self.friends.ids, self.friends.usernames)
También puede usar la excelente gema Squeel , como @erroric señaló en su respuesta (el bloque my { }
solo es necesario si necesita acceder a variables self
o de instancia):
Question.where { user_id.in(my { self.friends.ids }) |
target.in(my { self.friends.usernames }) }