Ruby on rails rails活动记录选择

Ruby on rails rails活动记录选择,ruby-on-rails,activerecord,select,include,arel,Ruby On Rails,Activerecord,Select,Include,Arel,Q:在一个查询中选择所有帖子和相关评论,将评论关系加载到p.comments中,但仅从评论中选择标题 职位 如果第一部分由完成。包括: posts = Post.includes(:comments).select('posts.*, comments.title') posts.first.comments.loaded? # true =>选择posts.id为t0_r0,posts.title为t0_r1,posts.text为t0_r2,posts.created_为t0_r3,pos

Q:在一个查询中选择所有帖子和相关评论,将评论关系加载到p.comments中,但仅从评论中选择标题

职位

如果第一部分由完成。包括:

posts = Post.includes(:comments).select('posts.*, comments.title')
posts.first.comments.loaded? # true
=>选择posts.id为t0_r0,posts.title为t0_r1,posts.text为t0_r2,posts.created_为t0_r3,posts.updated_为t0_r4,comments.id为t1_r0,comments.title为t1_r1,comments.text为t1_r2,comments.post_id为t1_r3,comments.created_为t1_r4,comments.updated_at AS t1_r5 FROM posts LEFT OUTER JOIN comments.post_id=posts.id

它完全忽略了select

好的,让我们试试连接:

Post.joins(:comments).select('posts.*, comments.title')
=>选择posts.*,comments.title FROM posts内部加入comments.post\u id=posts.id上的注释

更好,但我们需要表别名-Rails不处理关系为什么

posts = Post.joins(:comments).select('posts.*, comments.title as comments_title').first
=>选择posts.*,comments.title作为comments\u title从posts内部加入comments.post\u id=posts.id

好的,让我们试试阿雷尔

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,并在comments.post\u id=posts.id上加入评论

相同的故事-ActiveRecord不处理关系

有什么建议吗

UPD

如果这个问题没有直接的解决方案,也许有一种方法可以使用一些AR方法来转换生成的查询。因为,AR使用ARel,然后对其调用find_by_sql,然后执行一些我找不到的神奇操作,以及viola:生成的别名和加载关联

也许有一对一关系的解决方案

posts=Post。选择“posts.id,posts.title,comments.id,comments.title”。包括:comment posts.first.comment.loaded?真的


=>选择posts.id为t0_r0,posts.title为t0_r1,posts.text为t0_r2,posts.created_为t0_r3,posts.updated_为t0_r4,comments.id为t1_r0,comments.title为t1_r1,comments.text为t1_r2,comments.post_id为t1_r3,comments.created_为t1_r4,comments.updated_at AS t1_r5 FROM posts LEFT OUTER JOIN comments.post_id=posts.id

我恐怕没有任何建议,因为您描述的所有场景都按预期工作

:includes=>即时加载 :joins=>非即时加载 因此,如果您希望直接加载注释,则必须使用includes,连接将永远无法工作

接下来,由于SQL查询中使用了特定的select语法,因此即时加载可以正常工作。换句话说,当与include一起使用时,指定的select将被忽略,默认情况下将加载所有列

我认为最近添加您正在寻找的功能的尝试是通过在对includes的调用中添加except参数来解决的。不过,它似乎还没有得到任何回应


就我个人而言,我会选择您指定的第一个包含示例,但跳过select并接受comment.text已加载的事实。比我能想到的任何其他场景都要好。

解决方案之一是切换到DataMapper而不是ActiveRecort。对我来说,这比AR好得多。

您还可以通过执行以下操作,将原始SQL查询与活动记录一起使用:

post_comment = Post.find_by_sql("SELECT p.*, c.title AS comment_title FROM posts p JOIN comments c ON p.id=c.post_id").first
post_comment.comment_title

有点不对劲,但似乎有用。ActiveRecord还公开了connection属性,供您执行更复杂的查询

链接的tnx。如果我找不到任何解决方案,这将是有用的你的意思是你仍然想创建一个注释类,但是只在那里有标题,而不是有完整属性集的对象?
posts = Post.joins(:comments).select('posts.*, comments.title as comments_title').first
posts.first.comments.loaded? # false
posts.first.comments_title # "Comment 1.1"
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
)
post_comment = Post.find_by_sql("SELECT p.*, c.title AS comment_title FROM posts p JOIN comments c ON p.id=c.post_id").first
post_comment.comment_title