【问题标题】:How do I cache ActiveRecord model objects across redirects?如何跨重定向缓存 ActiveRecord 模型对象?
【发布时间】:2010-01-10 18:11:43
【问题描述】:

这可能是一个新手问题,但我不确定要搜索什么字词。

假设我有一个 CUSTOMER 对象,我想向该客户发送一条 MESSAGE。

我首先要做的是在 CUSTOMER 控制器上添加一个 SENDMESSAGE 操作,它会构建消息对象。 (假设这是正确的做法?)

然而,在这种情况下,我需要转发到 MESSAGE 的编辑视图以捕获正文等,而不是实际从该操作中发送消息。

问题:我想在不持久化对象的情况下执行此操作。我想在这里构建对象,然后将其交给另一个视图完成。

def sendmessage
    @message = Message.new
    @message.title = 'WIBBLE'
    @message.thecustomer = self
    @message.save    
    respond_to do |format|
      format.html { redirect_to(edit_message_path(@ message)) }
      format.xml  { render :xml => @ message }
    end
end

也许我的问题归结为,跨请求和多个屏幕缓存参数和对象的“rails 方式”是什么。

很高兴指向 Web URL,因为我认为这很简单。

谢谢

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    在构建 Web 应用程序时,跨请求保存数据的标准方法是使用 HTTP 会话。 Rails 为此目的提供了一个隐式会话哈希。它是这样使用的:

    session[:message] = @message #store
    @message = session[:message] #retrieve
    

    您还可以使用 Rails flash 会话包装器将信息从当前操作传递到下一个操作。它通常用于存储要在 UI 中显示的文本,但您可以使用它来持久化任何对象:

    flash[:message] = @message #store
    @message = flash[:message] #retrieve
    

    在这两种情况下,您存储的对象都必须是可序列化的。请注意,默认情况下,Rails 将会话数据存储在客户端上的加密 cookie 中;认为这是一个强烈的暗示,即在 Rails 世界中不赞成在会话中存储大量数据。

    【讨论】:

    • 非常感谢约翰。 cookie 中的会话内容听起来像是一个奇怪的设计决定!
    • 我也可以问一下,你会使用会话缓存跨控制器操作吗?例如我的 INDEX 操作根据传入的参数执行一个时髦的查询。我想为后续调用 SENDMESSAGE 缓存该特定结果列表。 (这可能意味着会话 cookie 中存储了数千个对象,所以猜测不会。)但是,在调用 SENDMESSAGE 时,我没有再次重建 CUSTOMER 列表所需的所有参数?也许缓存这些参数? (有很多方法可以做到这一点,但要寻找轨道方式!
    • 这听起来像缓存参数,以便您可以重建查询将是要走的路。请注意,我说过 cookie 会话存储是 Rails 的默认设置。 environment.rb 中的 config.action_controller.session_store 选项让您可以使用数据库进行会话存储。
    • 不存储实际对象:存储 ID。这使得会话更小。
    • 我在其他地方的研究与这里的观点一致,即在会话/闪存中存储模型实例等复杂对象可能是一个坏主意。我已经看到了一些奇怪的效果,还发现了一个page written in 2007 which lists some specific issues associated with it
    【解决方案2】:

    这实际上是一项非常常见的任务,但您过于复杂了。 Rails 处理这个问题的方法不是持久化有问题的对象,而是只渲染将完成操作的视图。

    class CustomersController < Application Controller
      def sendmessage
        @message = Message.new
        @message.title = 'WIBBLE'
        @message.thecustomer = self
        respond_to do |format|
          format.html { render "messages/edit" }
          format.xml  { render :xml => @ message }
        end
      end
    end
    

    一般来说,在 Rails 中跨 HTTP 请求持久化整个对象是一个坏主意,唯一真正的方法是通过会话或闪存哈希,正如 John Topley 所建议的那样,但这两者的数量都是有限的可用空间。这就是为什么 François Beausoleil 建议只在会话中存储对象 ID。无论哪种方式,您都应该在完成后清除其中一个哈希。

    您应该在这里做的是设计您的控制器动作,以便每个动作完全完成一项任务。完成一半任务并重定向以便第二个动作可以完成任务可能会稍微干燥一些,但是它不能很好地与 Rails 控制流融合。如示例所示,控制器操作完成了呈现视图所需的所有处理。

    基本上,如果您希望保留信息,因为您正在重定向。你会发现渲染你重定向到的视图更容易。

    【讨论】:

    猜你喜欢
    • 2014-03-25
    • 2012-11-17
    • 1970-01-01
    • 2018-12-25
    • 2017-11-16
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多