更少的 Rails 视图查询
Posted
技术标签:
【中文标题】更少的 Rails 视图查询【英文标题】:Fewer queries on Rails views 【发布时间】:2013-10-22 13:57:18 【问题描述】:在我的应用程序中,我有一个包含许多规则的标题,因为我有许多类型的配置文件。
我只想进行 一个 查询(可能两个)来获取用户并进行我需要的所有检查
在我的应用程序控制器中,我有这个方法:
def current_user
@current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
要检查当前用户,但我一直在我的 header.html.erb 上调用它,如果我检查它,比如,10 次,我会做 10 次查询...
据我所知,当我第一次调用 current_user
时,我会得到一个变量 @current_user
来使用。但是当我有一个控制器时,这对我来说很清楚。我打电话给current_user
,在我看来,我只是检查@current_user.something
。由于 /layouts/_header.html.erb 没有控制器,我该怎么做?
【问题讨论】:
你所做的是正确的。但是在你的视图中使用current_user
,而不是@current_user
。如果调用 10 次,它不会执行 10 次查询;它将第一次执行一个查询,然后在接下来的 9 次中简单地加载变量@current_user
。
是什么让您认为您正在执行 10 个查询?
【参考方案1】:
你不应该执行多个查询如果查找成功 - 它会将@current_user
设置为查询的返回值,然后在将来返回它。但是,如果找不到用户,@current_user
将被初始化为 nil
,因此对current_user
的额外调用将再次执行查询。
一种可能的解决方法是像这样使用defined?
运算符:
def current_user
return @current_user if defined?(@current_user)
@current_user = User.find_by_remember_token(cookies[:remember_token])
end
但是我不喜欢这个实现,因为如果 anything 在当前闭包中定义了@current_user
,那么无论查找是否完成,这都会返回值。您还可以设置 另一个 变量来跟踪当前用户是否已被查找,并且仅在已查找时才执行查询,但这对我来说也很丑陋。
有关此一般问题的更强大的解决方案,请参阅memoist gem。或者更好的是,您是否考虑过devise 和/或warden 是否适合您的身份验证需求?
【讨论】:
【参考方案2】:由于 /layouts/_header.html.erb 没有控制器,我该怎么做?
您的布局确实有控制器。以其他方式呈现它们是不可能的。
您现在所做的将按其编写的那样工作,并且它将最大限度地减少查询数量,并且您的布局文件将可以访问current_user
助手,前提是您已通过控制器中的 helper_method :current_user
将其提供给您的视图。
无论如何,您的代码没有任何问题;您认为自己遇到的所有问题,实际上可能并没有。
【讨论】:
【参考方案3】:来自以下
" 我有一个包含许多规则的标题,因为我有许多类型的配置文件"
我猜您正在根据用户角色验证多个条件。如果我的假设是正确的,那么
最好为每个角色创建单独的部分。例如,如果您有管理员角色,那么
在 layouts/_admin.html.erb 中创建部分
然后你可以将它包含为
<%= render "layouts/" + current_user.role %>
【讨论】:
以上是关于更少的 Rails 视图查询的主要内容,如果未能解决你的问题,请参考以下文章