ActiveRecord - ポリモーフィックな関連付けのクエリ
-
22-08-2019 - |
質問
プロジェクト内のコメントを追跡するためにポリモーフィックな関連付けを使用しています。どれも非常に単純明快なものばかりです。
私が抱えている問題は、ポリモーフィックな関連付けに基づいてクエリを実行し、コメント モデルからその所有者に結合することです。
それで ...
コメントモデルがあります
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
そして、ForumTopics モード:
class ForumTopic < ActiveRecord::Base
has_many :comments, :as => :commentable
end
他にも「コメント可能な」モデルがいくつかありますが、現時点では重要ではありません。これはすべて機能します。
私がやろうとしているのは、指定された条件 (この場合は 'featured' == true) を持つ ForumTopic に属するすべてのコメントを検索することです。
ファインダーを使用してモデルを結合しようとすると、次のようになります。
@comments = Comment.find(:all
:joins => :commentable
:conditions => ["forum_topics.featured = ? ", true]
)
次のエラーが表示されます。
多態性関連付けを熱心にロードできません:commentable
AR「インクルード構文」を使用する:
@comments = Comment.find(:all
:include => :forum_topics
:conditions => ["forum_topics.featured = ? ", true]
)
戻り値:
「forum_topics」という名前の関連付けが見つかりませんでした。おそらくスペルを間違えましたか?
アソシエーション名の代わりにテーブル名(シンボルではなく文字列)を使用して結合しようとすると、次のようになります。
@comments = Comment.find(:all,
:joins => "forum_topics",
:conditions => ["forum_topics.featured = ? ", true]
)
なるほど:
Mysql::エラー:不明なテーブルの「コメント」:コメントを選択します。 FROM コメント forum_topics WHERE (forum_topics.featured = 1 )*
(ここで、基になるクエリの構文が完全に外れており、結合が完全に欠落していることがわかります)。
私がやっていることは可能かどうかさえわかりません、そして必要な結果を達成する他の方法はありますが、それはそうであるように思えます すべき 実行可能であること。
何か案は?何か足りないものはありますか?
解決
なんてこった!
私は、問題を見つけたと思う。
を経由して結合する場合:
@comments = Comment.find(:all,
:joins => "forum_topics",
:conditions => ["forum_topics.featured = ? ", true]
)
あなたは、全体が参加する必要があります!
:joins => "INNER JOIN forum_topics ON forum_topics.id = comments.commentable_id",
これまで、素晴らしいを参照してください。 http://guides.rubyonrails.org/active_record_querying.html#joining-tablesする
他のヒント
古い質問を、しかし多型と一緒に、特定のタイプのための直接的な関連を設定することによって、これを達成するためのクリーンな方法があります:
は#comment.rb
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
belongs_to :forum_topics, -> { where( comments: { commentable_type: 'ForumTopic' } ).includes( :comments ) }, foreign_key: 'commentable_id'
...
end
あなたは参加し、その後汚いの必要性を取り除く:forum_topics
するincludes
を渡すことができます:
@comments = Comment
.includes( :forum_topics )
.where( :forum_topics => { featured: true } )
あなたはその後さらにスコープにクエリを移動することで、これをクリーンアップすることができます:
#comment.rb
class Comment < ActiveRecord::Base
...
scope :featured_topics, -> {
includes( :forum_topics )
.where( :forum_topics => { featured: true } )
}
...
end
タグだけで行うことができるようにあなたを残します
@comments = Comment.featured_topics
あなたは必要条件、プラスのRails 3 +
多くの人が回答やコメント欄でそれに言及したが、私は自分自身を含め、人々は、私がここに上陸した場合、最大つまずいになるだろうし、完全に十分読んでいないことを感じました。
だから、ここの絶対の必要がある条件を含む適切な答えは、です。
@comments = Comment.joins( "INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id" )
.where( comments: { commentable_type: 'ForumTopic' } )
.where( forum_topics: { featured: true } )
の彼らのコメントのためのすべてのおかげで、特に@Jits、@Peter、および@prograils。の
受け入れソリューションは動作しません。 commentable_idが一意でないため、間違ったコメントの取得を開始します。
例
は、
...コメントを受け付けニュースのモデルを追加することを決定しますclass News < ActiveRecord::Base
has_many :comments, :as => :commentable
end
あなたは1のIDと1のIDは、クエリを使用したとのニュース記事でforum_topicにコメントをした場合は、今、あなたは二つのレコード取り戻すことがあります:
:joins => "INNER JOIN forum_topics ON forum_topics.id = comments.commentable_id"
あなたはおそらくあなたの条件の一つとしてcommentable_typeを供給することによってこの問題を解決することができますが、私はそれがこの問題にアプローチする最良の方法だとは思わない。
私はこの記事に出くわしたし、それは私のソリューションに私をリードしています。私の条件の一つとしてcommentable_typeを使用したが、LEFT OUTERを使用する代わりに、登録しよう。そのようにコメントなしフォーラムのトピックが含まれます。
LEFT OUTER JOIN `comments` ON `comments`.`commentable_id` = `forum_topics`.`id` AND `comments`.`commentable_type` = 'ForumTopic'
以下で動作するようにチェックされています レール5:
解決策 1:
@comments = Comment
.where(commentable_type: "ForumTopic")
.joins("INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id")
.where(forum_topics: {featured: true})
.all
または
解決策 2:
@comments = Comment
.joins("INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id AND comments.commentable_type = 'ForumTopic'")
.where(forum_topics: {featured: true}).all
生の SQL 構文に注意してください。バッククォートは使用できません。見る http://guides.rubyonrails.org/active_record_querying.html#joining-tables .
個人的には、生の SQL 構文が少ないため、解決策 1 の方が好みです。
Railsは多型がデフォルトで加入含まれていませんが、この宝石は、あなたが簡単にあなたの多型の関係に参加するために役立つだろう。 https://github.com/jameshuynh/polymorphic_joinする