1

我正在研究电子商务解决方案,它在单个 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

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

4

2 回答 2

0

没有理由不保留类属性,直到它们下一次更新。

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

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

于 2013-03-09T09:41:25.713 回答
0

我终于想出了一个解决方案,如何坚持所提到的初始计划,但不存在“类缓存”问题。

它基于我对这个主题的另一个问题的回答。

无论如何这里是新的 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.nameandShop.current.tax它对应于在applicationController或spec_helper中设置的商店。

于 2013-03-09T21:45:01.360 回答