web-dev-qa-db-fra.com

Comment spécifier des conditions sur des tables jointes dans rails

J'essaie de faire une requête dans in Rails avec ActiveRecord qui spécifie une condition sur une table jointe. Et je n'arrive pas à la faire fonctionner, même si je suis les exemples d'ici :

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

Des guides :

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

Mon schéma de base de données ressemble à ceci, avec les tables scores, submissions et 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

Je veux donc faire une requête où je peux trouver tous les "scores" qui ont une relation avec une tâche spécifique. La soumission appartient aux tâches et aux scores.

Ma requête ressemble maintenant à ceci:

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

Cela génère la syntaxe suivante:

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

Ce qui génère l'erreur suivante:

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

Mais il y a une colonne submission.task_id, que vous pouvez voir dans le schéma db. Et je peux le faire avec succès:

SELECT "submissions".* FROM "submissions" WHERE "submissions"."task_id" = 1
39
espenhogbakk

Le nom dans la clause doit être pluriel pour faire référence au nom de la table:

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

Le nom de la clause doit être pluriel pour faire référence au nom de la table.

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

Si la partition a de nombreuses soumissions, le symbole de jointure doit également être pluriel pour faire référence à la relation entre la partition et la soumission.

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

Une mise en garde: si vous utilisez des noms de table non standard, ce qui précède échouera comme suit:

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

Pour résoudre ce problème, mettez (joined-model-class).table_name comme clé dans le hachage where:

Score.joins(:submission).where(
  Submission.table_name => {task_id: 1}
)
4
Matt Hucke

Je trouve que c'est plus facile.

Score.joins(:submission).merge(Submission.where(task_id: 1))
4
thedanotto

Votre requête ressemble à ceci:

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

Votre #joins est correct, mais :submission doit être pluriel:

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