更少的 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 视图查询的主要内容,如果未能解决你的问题,请参考以下文章

左连接在查询后返回更多和更少的行

使用媒体查询中的类集作为更少的mixin

Rails 可以期待每秒 100 个或更少的请求(对于非缓存页面)吗?

Ruby on Rails 更少的源地图和资产管道?

SQL 查询来自不同区域的选择行

减少查询中的资源使用