Q:1つのクエリですべての投稿と関連するコメントを選択し、コメントの関係をp.commentsにロードしますが、コメントからタイトルのみを選択します
役職
#db
create_table :posts do |t|
t.string :title
t.text :text
t.timestamps
end
#modlel
class Post < ActiveRecord::Base
has_many :comments
end
コメント
#db
create_table :comments do |t|
t.string :title
t.text :text
t.integer :post_id
t.timestamps
end
#model
class Comment < ActiveRecord::Base
belongs_to :post
end
必要なもの:1つのクエリですべての投稿と関連するコメントを選択し、コメントの関係をp.commentsにロードしますが、コメントからタイトルのみを選択します。
posts = Post.includes(:comments).select("posts.*, comments.title")
posts.each do |p|
puts(p.title)
puts(p.text)
p.comments.each do |c|
puts(c.title)
end
end
最初の部分が.includesによって行われる場合:
posts = Post.includes(:comments).select('posts.*, comments.title')
posts.first.comments.loaded? # true
=>SELECT posts
。id
AS t0_r0 、posts
。title
AS t0_r1 、posts
。text
AS t0_r2 、posts
。created_at
AS t0_r3 、posts
。updated_at
AS t0_r4 、comments
。id
AS t1_r0 、comments
。title
AS t1_r1 、comments
。text
AS t1_r2 、comments
。post_id
AS t1_r3 、comments
。created_at
AS t1_r4 、comments
。updated_at
AS t1_r5 FROM posts
LEFT comments
OUTERJOINON comments
。post_id
= posts
。id
selectを完全に無視します。
では、参加してみましょう。
Post.joins(:comments).select('posts.*, comments.title')
=> SELECT posts。*、comments.title FROM posts
INNERJOINON 。= 。comments
comments
post_id
posts
id
より良いですが、テーブルエイリアスが必要です-Railsはリレーションを処理しません(なぜですか?)
posts = Post.joins(:comments).select('posts.*, comments.title as comments_title').first
=> SELECTposts。*、comments.title ascomments_title FROM posts
INNERJOINON 。= 。comments
comments
post_id
posts
id
posts.first.comments.loaded? # false
posts.first.comments_title # "Comment 1.1"
OK、ARelを試してみましょう
p = Post.arel_table
c = Comment.arel_table
posts = Post.find_by_sql(
p.join(c).on(c[:post_id].eq(p[:id])) \
.project(p[:id],p[:title],c[:id],c[:title]).to_sql
)
=>SELECT posts
。id
、posts
。title
、comments
。id
、comments
。title
内部posts
結合comments
からcomments
。post_id
= posts
。id
同じ話-ActiveRecordはリレーションを処理しません。
助言がありますか?
UPD
この質問が直接的な解決策ではない場合は、いくつかのARメソッドを使用して結果のクエリを変換する方法があるかもしれません。なぜなら、ARはARelを使用し、それに対してfind_by_sqlを呼び出してから、魔法をかけます。これは、いつ実行されたかを見つけることができず、ビオラ:生成されたエイリアスと読み込みの関連付けです。
たぶん、1対1の関係の解決策はありますか?
投稿=Post.select('posts.id、posts.title、comments.id、comments.title')。includes(:comment)posts.first.comment.loaded?#true
=>SELECT posts
。id
AS t0_r0 、posts
。title
AS t0_r1 、posts
。text
AS t0_r2 、posts
。created_at
AS t0_r3 、posts
。updated_at
AS t0_r4 、comments
。id
AS t1_r0 、comments
。title
AS t1_r1 、comments
。text
AS t1_r2 、comments
。post_id
AS t1_r3 、comments
。created_at
AS t1_r4 、comments
。updated_at
AS t1_r5 FROM posts
LEFT comments
OUTERJOINON comments
。post_id
= posts
。id