如何在请求之间重置ruby类访问器?

时间:2013-03-09 02:13:29

标签: ruby-on-rails ruby scoping settingslogic

我正在开发电子商务解决方案,它在单个rails应用程序中提供了几个不同的商店。

我有一个课程可以保存特定于商店的设置。

# models/shop.rb
class Shop < Settingslogic
  source "#{Rails.root}/config/shop.yml"

  def self.init!(shop)
    namespace shop.to_s
    load!
  end

end

商店::初始化!从配置文件

加载指定的部分

以下是yml文件以防万一:

# config/shop.yml
shop_1:
  shop_name: Shop 1
shop_2:
  shop_name: Shop 2

我在应用程序控制器中按域名匹配请求的商店。

# controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_filter :set_shop

  protected

  def set_shop
    Shop.init! if request.domain.match(/^.*shop1\.com$/)
      :shop_1
    elsif request.domain.match(/^.*shop2\.com$/)
      :shop_2
    end
  end
end

问题是Shop以某种方式保留了请求之间第一个请求商店的设置。 例如:

shop1.com

Shop.shop_name # => Shop 1

shop2.com

Shop.shop_name # => Shop 1

它保持初始设置,直到我对application_controller.rb或shop.rb进行一些更改。 (我认为这是答案的第一个关键)

我所知道的是,Settingslogic为shop.yml中的每个选项定义了attr_accessor(仅在首次调用时)。但是为什么他们在重新加载后仍然工作(我在开发环境中使用cache_classes = false)

当我这样做时:

# models/shop.rb
class Shop < Settingslogic
  source "#{Rails.root}/config/shop.yml"
  namespace  "shop_#{Random.rand(1..2)}"
  load!
end

它按预期工作 - 每次都会加载适当的设置。但是我不能在这个阶段按域名设置商店名称。当我无法从外部指定shop_name时,我也无法测试不同的商店。所以我需要一个方法。

我尝试了class_eval

def self.init!(shop)
  class_eval do
    namespace shop.to_s
    load!
  end
end

但它没有帮助。我觉得缺乏关于范围界定的知识。 你有什么想法吗?提前谢谢。

2 个答案:

答案 0 :(得分:0)

在下次更新之前,没有理由不保留类属性。

在rails应用程序的开发模式中,您的代码在更改时会重新加载,这会产生重置这些类变量的副作用,但您不想依赖它。

您之前的过滤器应该做的是设置@current_shop实例变量,该变量包含用于当前请求的商店。

答案 1 :(得分:0)

我终于想出了一个如何坚持有问题的初步计划的解决方案,但没有“课堂缓存”问题。

这是基于my another question对此主题的回答。

无论如何这里是新的Shop.rb

class Shop < Settingslogic
  source "#{Rails.root}/config/shop.yml"
  load!

  def self.current=(shop)
    Thread.current[:current_shop] = shop.to_sym
  end

  def self.current
    self.send(Thread.current[:current_shop])
  end
end

我决定加载shop.yml的所有部分,然后通过Shop :: current访问它们,将调用转发到相应的部分。

所以我可以在任何地方使用Shop.current.nameShop.current.tax,它对应于在applicationController或spec_helper中设置的商店。