开发者

Rails cannot cache precalculated values across browser requests? (such as remembering n factorial results)

开发者 https://www.devze.com 2023-01-22 12:45 出处:网络
For example, the following code: class FoosController < ApplicationController def index if !@foo.nil?

For example, the following code:

class FoosController < ApplicationController
  def index
    if !@foo.nil?
      render :locals => {:bar => @foo}
      return
    else 
      @foo = rand 10
      render :locals => {:bar => @foo}
    end
  end
end

if I load localhost:3000/foos multiple times, it will show different values, and it is no surprise if it is development mode, because Rails reload the controller (and model and view) every time a browser request comes in.

But even when in production mode, when everything is loaded and stay there, @foo's value won't stay across browser requests? Every time reloading the page on the web browser, a different number is shown. So Rails will wipe all values clean each time? Is there a way to cache or "memoize" the results across requests if we don't use a DBMS?


Surprisingly, I just tried using a class variable, and in development mode, it gives a different number each time. In production mode, the number stays the same on F开发者_StackOverflow中文版irefox, and then Chrome will also show that number all the time, until the server is restarted:

class FoosController < ApplicationController
  @@foo = nil

  def index
    if !@@foo.nil?
      render :locals => {:bar => @@foo}
      return
    else 
      @@foo = rand 10
      render :locals => {:bar => @@foo}
    end
  end
end

Why can a class variable memoize but an instance variable can't? Is using a class variable a reliable way to "remember things" across request reliably in Rails 2.x, 3.x and Ruby 1.8.7 and 1.9.2?


This is a deliberate and desired behavior, every request instantiates a new controller instance, so that a request doesn't have any trouble dealing with leftovers from the previous requests.

You may want to use the session or the flash hashes to store @foo across requests.

class FoosController < ApplicationController
  def index
    @foo = session[:foo] ||= rand(10)
    render :locals => {:bar => @foo}
  end
end

session[:foo] will be persistent all along the way, but you can use flash[:foo] if you just want to persist it across one request.


@@foo designates a class variable, @foo an instance variable. A new instance of a controller is created on every request. And for caching, I really recommend memcache or something similar (due to the forking nature of production rails servers).


Even if you meemoize the way edgerunner suggests, in production you may have multiple mongrel or thin instances running and each of those controllers will have different flash variables and current approach wont work. Go ahead with what Tass says something like memcache or redis to persist such stuff in memory.

0

精彩评论

暂无评论...
验证码 换一张
取 消