将Rails条件语句传递给where子句

时间:2018-11-30 22:21:41

标签: ruby-on-rails ruby

我有一个下拉菜单,根据用户选择的内容,我需要执行不同的查询。做到这一点的最佳方法是什么?能否有2个函数可以获取privacy_level,然后处理要使用的查询才能将该值传递给2nd函数?

  def get_article_restrictions(privacy_level)
     case privacy_level
     when 0
       "#{@authenticated_user.id} = articles.user_id"
     when 1
       "query 1"
     when 2
       "query 2"
     end
  end

在第二个函数中,我将使用从第一个函数返回的任何查询。

def display_articles
  privacy_level = get_article_restrictions(params[:privacy_level])
  @articles = Article.includes(:user).where(privacy_level)
end

2 个答案:

答案 0 :(得分:2)

这取决于您需要执行的查询。如果只是简单的where,则可以使用where参数传递哈希:

  def get_article_restrictions(privacy_level)
     case privacy_level
     when 0
       { "articles.user_id": @authenticated_user.id }
     when 1
       { param1: value1, param2: value2 }
     when 2
       { param3: value3, param4: value4 }
     end
  end

def display_articles
  privacy_level = get_article_restrictions(params[:privacy_level])
  @articles = Article.includes(:user).where(privacy_level)
end

我建议反过来做:将范围传递给方法:

def fetch_articles(scope, privacy_level)
     case privacy_level
     when 0
       scope.where("articles.user_id": @authenticated_user.id)
     when 1
       scope.where(param1: value1, param2: value2)
     when 2
       scope.where(param3: value3, param4: value4)
     end
end

def display_articles
  @articles = fetch_articles(Article.includes(:user), params[:privacy_level])
end

我还建议将fetch_articles移至模式,因为调用活动记录方法(如where)会导致过多的耦合并使测试更加困难。

答案 1 :(得分:0)

mrzasa在his answer中建议将方法移至模型。这是一个看起来如何的示例。

class Article < ApplicationRecord
  # ...

  def self.privacy_level(level, user)
    case level
    when 0
      where(user_id: user.id)
    when 1
      where(attribute: 'value')
    when 2
      where(attribute: 'value')
    else
      # Return the current scope without adding constraints.
      where(nil)
    end
  end

  # ...
end

然后在控制器中简单地调用范围。

def display_articles
  @articles = Article.includes(:user)
                     .privacy_level(params[:privacy_level], @authenticated_user)
end

请记住,大多数请求参数都以字符串形式存在,这意味着只有 else 大小写会匹配。您可以通过将大小写更改为when 0, '0'而不是when 0来解决此问题。

您可能还希望将默认大小写移动到else语句中。这样,当没有给出任何级别(params[:privacy_level]等于nil)时,您仍然会限制所获取的记录。