在rails app中随处访问对象

时间:2013-03-09 12:33:56

标签: ruby-on-rails ruby global-variables

我知道这是关于全局对象的第100个问题,但我认为我的情况略有不同。

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

有一个类商店,提供商店特定的逻辑和选项。例如:

应该可以在模型中访问

@shop.tax。税收可能因商店而异。例如9%,18%。

应该可以在控制器和视图中访问

@shop.name@shop.layout

邮件

@shop.email.general

我需要能够在应用程序控制器中创建Shop的实例,并以某种方式将其传递给所有应用程序部分。

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

  protected

  def set_shop
    requested_shop = if request.domain.match(/^.*shop1\.com$/)
      :shop_1
    elsif request.domain.match(/^.*shop2\.com$/)
      :shop_2
    end
    @shop = Shop.new(requested_shop)
  end
end

我知道基于请求的逻辑不应该用在模型中,但我真的需要那里的商店选择。在测试中,我可以像spec_helper中的Shop.new(:test_shop)一样模拟这个“全局”对象。

全局变量是我唯一的选择吗?我从来没有用过它们。

我尝试使用Settingslogic gem,但它为商店特定的选项定义了attr_accessors,并且它们在请求之间保持不变,这不是我需要的。

1 个答案:

答案 0 :(得分:1)

这样做的一种方法就是

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

  def self.current
    Thread.current[:current_shop]
  end
end

这使您可以为每个请求维护一个单独的当前商店。

另一种方法是通过现有的商店。一开始可能看起来很乏味,但最终可能比全局或伪全球行为更容易推理