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
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})
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 })
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}
)
Je trouve que c'est plus facile.
Score.joins(:submission).merge(Submission.where(task_id: 1))
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 })