我正在开发电子商务解决方案,它在单个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
但它没有帮助。我觉得缺乏关于范围界定的知识。 你有什么想法吗?提前谢谢。
答案 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.name
和Shop.current.tax
,它对应于在applicationController或spec_helper中设置的商店。