从 Rails 个 ActiveRecord 集合中过滤结果

filter results from Rails ActiveRecord collection

如何筛选活动记录集合返回的结果?我并不是想从文章 table 中删除,只是想根据每篇文章的权限为每个用户过滤结果。

我可以使用 where 子句 @articles.where(some condition) 我相信,但我必须检查每篇文章的 privacy_level 并根据不同的隐私级别应用其他过滤器,所以我不确定是否会工作。

          @articles = Article.includes(:user, :country, :favorites)
                          .where(is_deleted: false)
                          .where("articles.organization_id is null OR articles.organization_id = #{@authenticated_user.organization.id}")
                          .filter(filter_items)
                          .order(sort_column + " " + sort_direction)
                          .paginate(page: params[:page])


          @articles.each do |article|

            if article.privacy_level == 0 and article.user_id != @authenticated_user.id
              # @articles.delete_at(article.id)
            end

            if article.privacy_level == 1 and article.organization_id != @authenticated_user.organization.id
               # remove from results
            end
          end

你已经让这个人过滤了你的文章:

.where("articles.organization_id is null OR articles.organization_id = #{@authenticated_user.organization.id}")

这应该已经过滤掉了第一个条件中的文章(它过滤掉了 organization_id 与经过身份验证的用户的组织不匹配的所有文章):

article.privacy_level == 0 and article.user_id != @authenticated_user.id

因此您可以将另一个 where 子句添加到第二个 if 条件的活动记录查询中:

.where('article.privacy_level != 0 or article.user_id == ?', @authenticated_user.id)

旁注:通常,您不想在 SQL 查询字符串中使用字符串插值,因为它会让您面临 SQL 注入攻击.

所以您可能想将您的第一个 where 更改为:

.where("articles.organization_id is null OR articles.organization_id = ?", @authenticated_user.organization.id)

查看 rails security guide 了解更多详情。

控制器中有相当多的逻辑要处理。我建议添加到您的文章模型中:

class Article < ApplicationRecord
  def self.articles_for_list(authenticated_user)
    where(privacy_level: 0).where.not(user_id: authenticated_user.id).or(
      where(privacy_level: 1).where.not(organization_id: authenticated_user.organization.id)
    )
  end
end

我想这就是您想将它们添加到列表中的方式,但我不确定。然后在你的控制器中:

@articles = Article.includes(:user, :country, :favorites)
                          .articles_for_list(@authenticated_user)
                          .where(is_deleted: false)
                          .where("articles.organization_id is null OR articles.organization_id = #{@authenticated_user.organization.id}")
                          .filter(filter_items)
                          .order(sort_column + " " + sort_direction)
                          .paginate(page: params[:page])

编辑:

rails 3+ 的较丑版本:

class Article < ApplicationRecord
  def self.articles_for_list(authenticated_user)
    ids_1 = where(privacy_level: 0).where.not(user_id: authenticated_user.id).collect(&:id)
    ids_2 = where(privacy_level: 1).where.not(organization_id: authenticated_user.organization.id).collect(&:id)
    where(id: (ids_1 + ids_2))
  end
end