3

我们在 Rails 3.0.6 上。

以下代码会在 Rails 中的页面加载和用户之间持续存在吗?还是每次请求都会重新定义它?代码位于控制器的顶部。

@@list = []

hero = {}
hero['name'] = 'so'
hero['superpowers'] = ['coding', 'qa', 'spec_writing']
@@list.push hero

hero2 = {}
hero2['name'] = 'so2'
hero2['superpowers'] = ['coding']
@@list.push hero2
... more Hashes pushed into @@list

该列表每月仅更改一次,我们希望高效、快速地将这些数据提供给页面请求。我们最终将使用 Rails.cache 从数据库中读取,但我们现在使用以下方法(假设它有效)。

4

5 回答 5

11

在开发中,默认行为是在每次请求时重新加载类,从而重置您的类变量。然而,在生产中,类被初始化一次,因此类变量将在多个请求和多个会话中持续存在。

您应该尽快使用适当的缓存技术。显然,当应用程序重新启动时,您不能在重新加载类之后保留该值。此外,如果 Web 服务器是多线程的(很可能是),它可能会在共享类变量的不同线程上运行应用程序的多个实例,从而可能在请求之间造成不一致。

于 2012-04-09T15:13:26.117 回答
1

我刚刚遇到了同样的问题并找到了这篇文章。我知道这是一个老问题,但发布我的答案以防其他人面临类似问题......

我认为对于由于某种原因无法使用数据库Rails.cache的情况,放置这些值的最佳位置是 Application 类。只需定义一些属性并初始化它。然后就可以像Rails.application.heros一样轻松访问它。下面的快速和肮脏的样本:

在 config/application.rb

module YourRailsApp
  class Application < Rails::Application
    attr_reader :heros

    initializer "init heros" do 
      @heros = []

      hero = {}
      hero['name'] = 'so'
      hero['superpowers'] = ['coding', 'qa', 'spec_writing']
      @heros.push hero

      hero2 = {}
      hero2['name'] = 'so2'
      hero2['superpowers'] = ['coding']

      @heros.push hero2
    end

    #Other application sutff...
  end
end
于 2012-10-15T15:17:02.333 回答
0

我有时会使用我所谓的穷人缓存

它的工作方式如下:

  • 在初始化程序中,添加:MY_CACHE_HASH = {}

  • 哪里都行:MY_CACHE_HASH[:foo] = :bar

  • 任何你需要的地方MY_CACHE_HASH[:foo] #=> :bar

不过我不推荐它:如果你的服务器崩溃了,你会怎么做?

于 2012-04-09T15:13:37.933 回答
0

如果您有在 rails 运行时不会更改的数据,那么可以使用@@class_variable.

请记住(在默认开发配置中)控制器类在每次请求时都会重新加载,因此如果您需要说,从文件中读取数据,请考虑将初始化数据的代码放入 config/application.rb 中一个$globalCONSTANT_VAR

于 2012-04-09T15:33:22.200 回答
0

所以你描述的是一个不是数据库的数据结构。我认为在您的代码中而不是在您的数据库中拥有“从不”更改的项目是完全合理的。

例如,您可以:

在 app/models/hero.rb

class Hero
  @@all_heros = []
  def self.all_heros
    @@all_heros
  end
  def self.add_hero(hero)
    @@all_heros << hero
  end
  def initialize(name, superpowers=[])
    @name = name
    @superpowers = superpowers
  end
end

# this will get executed on load
Hero.add_hero( Hero.new("so", ['coding', 'qa', 'spec_writing']))

然后稍后在您的代码中,您将访问:

@heros = Hero.all_heros

稍后,如果需要,您可以换成数据库支持的存储。

于 2012-04-09T18:23:43.513 回答