Cómo especificar condiciones en tablas unidas en rieles


Estoy intentando hacer una consulta en in Rails con ActiveRecord que especifica alguna condición en una tabla unida. Y parece que no puedo hacer que funcione, a pesar de que sigo los ejemplos de aquí:

Http://guides.rubyonrails.org/active_record_querying.html#specifying-conditions-on-the-joined-tables

De las guías :

Client.joins(:orders).where(:orders => {:created_at => time_range})

Mi esquema de base de datos se ve así, con tablas scores, submissions y tasks:

  create_table "scores", :force => true do |t|
    t.integer  "value"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "scores", ["user_id"], :name => "index_scores_on_user_id"

  create_table "submissions", :force => true do |t|
    t.integer  "user_id"
    t.integer  "task_id"
    t.integer  "score_id"
    t.datetime "completed_at"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "submissions", ["score_id"], :name => "index_submissions_on_score_id"
  add_index "submissions", ["task_id"], :name => "index_submissions_on_task_id"
  add_index "submissions", ["user_id"], :name => "index_submissions_on_user_id"

  create_table "tasks", :force => true do |t|
    t.integer  "episode_id"
    t.integer  "score"
    t.string   "key"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

Así que quiero hacer una consulta donde pueda encontrar todas las "partituras" que tienen una relación con una tarea específica. La sumisión pertenece a tareas y puntuaciones.

Mi consulta ahora se ve así:

Score.joins(:submission).where(:submission => {:task_id => 1})

Esto genera la siguiente sintaxis:

SELECT "scores".* FROM "scores" INNER JOIN "submissions" ON "submissions"."score_id" = "scores"."id" WHERE "submission"."task_id" = 1

Que genera el siguiente error:

SQLite3::SQLException: no such column: submission.task_id

Pero hay una columna submission.task_id, que se puede ver en el esquema db. Y puedo hacer esto con éxito:

SELECT "submissions".* FROM "submissions" WHERE "submissions"."task_id" = 1
Author: Oxfist, 2012-01-27

5 answers

El nombre en la cláusula debe ser plural para hacer referencia al nombre de la tabla:

Score.joins(:submission).where(:submissions => {:task_id => 1})
 55
Author: Nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-15 18:55:24

El nombre de la cláusula debe ser plural para hacer referencia al nombre de la tabla.

Score.joins(:submission).where(submissions: { task_id: 1 })

Si la partitura tiene muchos envíos, el símbolo joins también debe ser plural para hacer referencia a la relación entre la Partitura y el Envío.

Score.joins(:submissions).where(submissions: { task_id: 1 })
 6
Author: leandrotk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-16 20:14:18

Una advertencia: si está utilizando nombres de tabla no estándar, lo anterior fallará de la siguiente manera:

ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "submissions"

Para arreglar esto, pon (joined-model-class).table_name como una clave en el hash where:

Score.joins(:submission).where(
  Submission.table_name => {task_id: 1}
)
 4
Author: Matt Hucke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-03 19:09:21

Me parece que esto es más fácil.

Score.joins(:submission).merge(Submission.where(task_id: 1))
 3
Author: thedanotto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-02 06:17:47

Su consulta se ve así:

Score.joins(:submission).where(:submission => { :task_id => 1 })

Su #joins es correcto, pero :submission debe ser plural:

Score.joins(:submission).where(:submissions => { :task_id => 1 })
 1
Author: jmmaniego,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-12 22:00:43