En ARel, los where()
métodos pueden tomar matrices como argumentos que generarán una consulta "WHERE id IN ...". Entonces, lo que ha escrito está en la línea correcta.
Por ejemplo, el siguiente código ARel:
User.where(:id => Order.where(:user_id => 5)).to_sql
... que es equivalente a:
User.where(:id => [5, 1, 2, 3]).to_sql
... generaría el siguiente SQL en una base de datos PostgreSQL:
SELECT "users".* FROM "users" WHERE "users"."id" IN (5, 1, 2, 3)"
Actualización: en respuesta a comentarios
Bien, entendí mal la pregunta. Creo que desea que la subconsulta enumere explícitamente los nombres de columna que se seleccionarán para no llegar a la base de datos con dos consultas (que es lo que hace ActiveRecord en el caso más simple).
Puede utilizar project
para select
en su sub-selección:
accounts = Account.arel_table
User.where(:id => accounts.project(:user_id).where(accounts[:user_id].not_eq(6)))
... que produciría el siguiente SQL:
SELECT "users".* FROM "users" WHERE "users"."id" IN (SELECT user_id FROM "accounts" WHERE "accounts"."user_id" != 6)
¡Espero sinceramente haberte dado lo que querías esta vez!
not
condición . Pude lograrlo en Rails 3 ajustando el enfoque en esta publicación :subquery = Profile.select("user_id").where(gender: 'm')).to_sql; Message.where('user_id NOT IN (#{subquery}))
Básicamente, losActiveRecord
métodos se utilizan para crear la subconsulta completada y citada correctamente, que luego se incluye en la consulta externa. El principal inconveniente es que los parámetros de las subconsultas no están vinculados.Message.where.not(user_id: Profile.select("user_id").where(gender: 'm'))
- que genera una subselección "NOT IN". Acabo de resolver mi problema ..