【问题标题】:Listing users who have posts with Ruby on Rails 5列出使用 Ruby on Rails 5 发帖的用户
【发布时间】:2018-01-11 00:19:12
【问题描述】:

目前我有这个查询来拉出所有有头像的用户:

@users = User.all.order('RANDOM()').where.not(avatar: nil)

但是我还需要检查有帖子的用户。由于帖子位于不同的表格中,我该怎么做?

谢谢。

【问题讨论】:

    标签: sql ruby-on-rails ruby ruby-on-rails-5


    【解决方案1】:

    您可以只使用 User 和 Post 之间的关联(如果 Post 是您的模型),这将检查两种情况下的外键和主键是否匹配,最终检查用户是否记录了一些 Post:

    User.order('RANDOM()').joins(:posts).where.not(avatar: nil)
    # SELECT "users".*
    # FROM "users"
    # INNER JOIN "posts" ON
    # "posts"."user_id" = "users"."id"
    # WHERE ("users"."avatar" IS NOT NULL) ORDER BY RANDOM()
    

    通过其他方式,您可以检查关联模型(依赖于用户的模型)的 id 是否不为零,这意味着它作为关联记录存在,例如:

    User.order('RANDOM()').joins(:posts).where.not(avatar: nil)
                                        .where.not(posts: { id: nil })
    

    【讨论】:

    • 为避免获取重复的用户记录,您可以在查询中添加GROUP BY 子句:group('users.id')
    • 我喜欢这个解决方案的简单和优雅,但它并没有真正过滤。它仍然显示所有用户,包括那些没有帖子的用户?
    • 啊,这可能是关于我的 is_approved 布尔字段的帖子。这有效 User.order('RANDOM()').where.not(avatar: nil).joins(:posts).where(posts: {is_approved: true})
    • 事实上,如果用户没有对帖子的引用,那么INNER JOIN "posts" ON "posts"."user_id" = "users"."id" 不会将其添加到查询结果中。您还可以尝试结合 distinct 和 where 来检查这两个属性 User.distinct.joins(:posts).where.not(avatar: nil, posts: { id: nil })
    • @w_hile 感谢朋友的建议!这帮助很大!
    【解决方案2】:

    让用户同时拥有头像和帖子的一种方法是使用 SQL 的 EXISTS 运算符。然后我们可以利用 ActiveRecord 的作用域使这些查询可重用:

    # app/models/user.rb
    class User < ApplicationRecord
      scope :with_avatar, -> { where.not(avatar: nil) }
      scope :with_posts, -> { where('EXISTS(SELECT 1 FROM posts WHERE user_id = users.id)') }
    end
    

    现在您可以在控制器中执行以下操作:

    @users = User.order('RANDOM()').with_avatar.with_posts
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-09
      • 2023-03-10
      • 2011-06-02
      • 2017-12-14
      相关资源
      最近更新 更多