【问题标题】:Avoid current_user hitting db every time? Ruby on Rails避免 current_user 每次都点击 db? Ruby on Rails
【发布时间】:2013-11-21 16:46:49
【问题描述】:

我关注Ruby on Rails Tutorial。代码已给出,

在会话助手中:

  def sign_in(user)
    remember_token= User.new_remember_token
    cookies.permanent[:remember_token]=remember_token #save the unencrypted token to browser cookies
    user.update_attribute(:remember_token, User.encrypt(remember_token))
    self.current_user= user
  end

  def current_user=(user)
    @current_user= user
  end

  def current_user
    encrypted_token=User.encrypt(cookies[:remember_token])
    @current_user ||=User.find_by(remember_token:encrypted_token)
  end

  def sign_in?
    !current_user.nil?
  end

在导航器视图中:

<% if sign_in? %>
          <li><%= link_to "Profile",current_user %></li>
<% end %>

我的问题是:

  1. 每次访问者刷新导航器时是否都会访问数据库?
  2. 我能否通过在视图中使用@current_user 并将sign_in? 函数更改为:
def sign_in?
  if @current_user.nil?
    !current_user.nil?
  else
    false
  end
end

3.解决这个问题的最佳实践是什么?

提前致谢。

【问题讨论】:

    标签: ruby-on-rails ruby database cookies


    【解决方案1】:

    我认为您的解决方案很好,不需要修复。

    如果您对当前的情况不满意,我确实有两个建议/替代方案可供您探索(但是,我不会推荐这些替代您的解决方案,我只是说明替代方案):

    1. 使用会话而不是数据库。 HTTP 是无状态的。但是,发明了会话来制作 http 有状态的。您可以使用会话,并存储对 那里的当前用户。然后,您可以检查会话中是否存在 user_id,而不是每次都访问数据库。这当然会降低您的安全性。您是否可以接受这取决于您的应用程序的性质。
    2. 仅在访问级别更改时检查凭据。这是一种更加实用/宽松的用户授权方法。 您是否认为这种安全性下降对您的情况是可以接受的。 它的工作原理如下:例如,我们有一个带有页面的简单网站。最低的访问级别是读级别,如果用户决定编辑一个页面,他会进入写级别。在这种方法中,访问级别的更改将是您再次进行完整的身份验证检查的时刻。因此,不是每次,只有当您更改访问级别重新验证并重新授权用户时。也许您还想随机确定是否要重新验证/重新授权,这避免了可预测性。

    【讨论】:

      【解决方案2】:

      没有“解决方案”。

      HTTP 服务器是无状态的。每个请求都是新的。实例变量只存在于每个请求中,这意味着在下一个请求中它不会存在。

      记住该用户“状态”的唯一方法是将一些数据保存到数据库并在他每次请求时对其进行身份验证。

      不用担心数据库,它们被设计为运行 :)

      【讨论】:

      • 我不确定无状态 HTTP 服务器如何影响我的方法。还是它是一个安全问题?您能否详细说明我的方法将如何失败?我已经在 heroku sample-app-ivan.herokuapp.com 上部署了我的方法
      • 因为 HTTP 服务器是无状态的,所以每次请求都需要对用户进行身份验证。所以在每个请求中都有一个 db hit,从数据库中找到这个用户。我不知道您的方法为什么以及如何失败,因为您刚刚问为什么 db 受到了质疑。
      • 更好的方法是使用实​​例变量来缓存控制器中方法中的数据库搜索,例如def current_user; @current_user || User.find(...); end; 原因是您需要大量时间的 current_user。下次,在同一个请求中,您无需再次点击 db 即可找到它。但是,不鼓励将其用作视图中的实例变量。
      • 知道了。我相信我对“sign_in”的更改?是不必要的。无论如何,服务器将在下一个请求中忘记@current_user。我的 heroku 工作正常,但实际上并没有保存 db hits。每次加载页面时,仍然必须至少点击一次 Db。因此也不需要使用“@current_user”。在视图中弄乱 var "@current_user" 只会让其他开发者感到困惑。
      【解决方案3】:

      如果记录加载很简单,您可以使用second-level-cache 来保存数据库请求。但是,由于您使用某种密钥查找用户,这将不起作用。

      但是每次都从数据库加载用户应该没问题。这是 Rails 项目中的常见做法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 1970-01-01
        • 2020-08-25
        • 2011-03-29
        • 1970-01-01
        • 2014-10-31
        • 2021-12-16
        相关资源
        最近更新 更多