我有一个下拉菜单,根据用户选择的内容,我需要执行不同的查询。做到这一点的最佳方法是什么?能否有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
答案 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
)时,您仍然会限制所获取的记录。