Rails 5 在会话中的任何位置访问配置文件数据而无需每次查询数据库

Rails 5 access profile data anywhere in session without querying database each time

我有一个用户配置文件(带有名称、徽标、about_me),它是在用户创建(使用 Devise)之后创建的。配置文件 table 使用 user_id 作为主键。

现在我希望每当用户 creates/updates 一个 post 时,在填写表单时,一些详细信息是从配置文件中获取的,因此配置文件数据或@profile 可以在 post 表单中使用因为我不能以形式公开我的模型。 要在创建和#update 中设置 post.myname 属性,我正在这样做:

@myprofile = Profile.find_by_user_id(current_user)
write_attribute(:myname, @myprofile.name)

我从各种来源阅读,但给出的 4 个解决方案中最好的解决方案是什么?如果有人可以用简单的代码支持,因为我不想做一些广泛的事情?提前致谢。

1) 表单隐藏字段 - 就像在 #edit 中的散列中获取配置文件数据,然后在 #update 中传递表单和访问字段,但这样我们将分别传递每个字段。可以传一个@myprofile吗?

2) 会话 - 我觉得如果配置文件数据存储在会话中并且有人更新配置文件,那么更新的数据将不会在该会话中可用 session.So 不确定它是否合理。

3) 缓存 - 实现缓存的简单方法?

4)polymorphic profile---试过了但是没有得到相关的例子。我对将什么作为可配置的 ID 和类型以及如何在代码中使用它们感到困惑。

如果您的个人资料模型和用户模型之间存在一对一的关系,最简单的解决方案是完全删除个人资料模型并将其字段移至用户模型中。

Devise 已经查询数据库以获取 current_user 对象。所以,你的例子会像这样:

write_attribute(:myname, current_user.name)

不会访问数据库(在 Devise 检索到 current_user 对象之后)。


如果您被迫保留 Profile 模型,请查看您的四种情况...

  1. 可以使用会话变量。类似于:

    session[:profile_name] ||= @myprofile.name
    

    这将进入控制器操作。

    这里的技巧是,如果配置文件更新,您将需要重新定义每个相关的会话变量。因为您无权访问模型中的会话,所以最好在控制器中执行该操作。所以,不漂亮,但它可以工作。

  2. 您还可以使用低级缓存,并保存用户的配置文件关系。通常,您可以在用户模型中使用这样的方法:

    def profile_cached
      Rails.cache.fetch(['Profile', profile.id]) do
        profile
      end
    end
    

    在这里,您也必须知道缓存何时过期。这种方法的好处是您可以将此代码放入模型中,这意味着您可以在回调中挂钩它的过期时间。

    Caching with Rails 中阅读更多相关信息。

我会避免隐藏字段,我不确定多态关系如何解决您不访问数据库的问题。所以,#2 和#3 是选项,但是如果你可以将两个模型合二为一,那应该会简化它。