我想编写一个行为记录查询,其行为类似于:
User.joins(:comment).where(comments: {replies: []})
返回其评论没有回复的用户。
User.first.comment.first.replies => [] returns an empty array
我需要这只是一个activerecord关系,所以使用ruby代码将无法正常工作。有没有办法使用activerecord检查空数组?
编辑: 示例模式
create_table "users", force: :cascade do |t|
t.string "email",
t.string "password"
end
create_table "comments" do |t|
t.string "content"
end
create_table "replies" do |t|
t.string "content"
end
User.rb
class User < ActiveRecord::Base
has_many :comments
end
Comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
has_many :replies
end
Reply.rb
class Reply < ActiveRecord::Base
belongs_to :comment
belongs_to :user
end
这些只是示例模型,但这应该说明与这些相关的模型的问题。
因此,如果用户(ID为1)发表了3条评论,并且这3条评论中只有1条有回复,那么我如何在activerecord关系中获得其他2条评论?
答案 0 :(得分:4)
您可以使用counter_cache
使设计更简单在回复中添加counter_cache
class Reply < ActiveRecord::Base
belongs_to :comment, counter_cache: true
belongs_to :user
end
在评论表中添加计数器列
create_table "comments" do |t|
t.string "content"
t.integer "replies_count"
end
replies_count的简单使用条件
User.joins(:comment).where(comments: {replies_count: 0})
有关详细信息,请参阅rails doc
答案 1 :(得分:0)
您需要使用LEFT JOIN
到comments
的{{1}},无论是否每条评论都有回复,都会返回所有评论。通常的rails连接,即replies
或@comment.replies
执行时的连接是User.joins(comments: :replies)
。 INNER JOIN
没有用于编写左连接查询的漂亮DSL,但确实以下列方式允许它们:
ActiveRecord
我添加了两个代码段,因为在您的问题中,您不清楚是否要查找某个没有回复的用户的用户或评论。
# Find all users who have at least one comment with no replies
User.joins(:comments)
.joins("LEFT JOIN replies ON replies.comment_id = comments.id")
.where("replies.id IS NULL")
# Find all comments for a user that don't have replies
@user.comments
.joins("LEFT JOIN replies ON replies.comment_id = comments.id")
.where("replies.id IS NULL")
是过滤器,它会查找where("replies.id IS NULL")
中没有匹配回复的每条评论,并提供您想要的结果。对于未来的数据挖掘,这是一个非常常见的LEFT JOIN
技巧。