Q:在一个查询中选择所有帖子和相关评论,将评论关系加载到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
我需要的:
在一个查询中选择所有帖子和相关评论并将评论关系加载到 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
=> 选择
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 来自 posts
左外连接comments
开启 comments
. post_id
= posts
. id
它完全忽略了选择。
好的,让我们尝试加入:
Post.joins(:comments).select('posts.*, comments.title')
=> 选择帖子。*,评论。标题来自
posts
内连接comments
开启 comments
. post_id
= posts
. id
更好,但我们需要表别名——Rails 不处理关系(为什么?)
posts = Post.joins(:comments).select('posts.*, comments.title as comments_title').first
=> 选择帖子。*,comments.title 作为comments_title FROM
posts
内连接comments
开启 comments
. post_id
= posts
. id
posts.first.comments.loaded? # false
posts.first.comments_title # "Comment 1.1"
好的,让我们试试 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
)
=> 选择
posts
. id
, posts
. title
, comments
. id
, comments
. title
发件人 posts
内连接comments
开启 comments
. post_id
= posts
. id
同样的故事——ActiveRecord 不处理关系。
有什么建议?
UPD
posts = Post.select('posts.id,posts.title,comments.id,comments.title').includes(:comment)
post.first.comment.loaded? #true
=> 选择
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 来自 posts
左外连接 comments
开启 comments
. post_id
= posts
. id
最佳答案
恐怕我没有任何建议,因为您描述的所有场景都按预期工作。
所以如果你想直接加载评论,你必须使用包含,连接永远不会工作。
接下来,由于 SQL 查询中使用了特定的 select 语法,所以预加载可以工作。换句话说,当与包含结合使用时,您指定的选择将被忽略,并且默认情况下将加载所有列。
我认为最近尝试添加您正在寻找的功能的描述是 in this ticket通过在对includes的调用中添加一个except参数来解决它。不过似乎还没有得到任何回应。
就我个人而言,我会使用您指定的第一个示例,但跳过选择并接受 comment.text 已加载的事实。比我能想到的任何其他场景都要好。
关于ruby-on-rails - rails 事件记录选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4862804/