2013-03-09 4 views
2

Я знаю, что это 1001-й вопрос о глобальных объектах, но я думаю, что моя ситуация немного отличается.Доступ к объекту повсюду в приложении rails

Я работаю над решением для электронной коммерции, которое предоставляет несколько различных магазинов в рамках одного приложения для рельсов.

Существует классный магазин, который предоставляет специфическую для магазина логику и опции. Например:

@shop.tax должен быть доступен в моделях. Налог может отличаться в зависимости от магазина. например, 9%, 18%.

@shop.name и @shop.layout должны быть доступны в контроллерах и видеонаблюдения.

@shop.email.general для почтовых отправлений.

Мне нужно создать экземпляр магазина в контроллере приложений и как-то передать его всем частям приложения.

# 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 

Я знаю, что логику, основанную на запросах, не следует использовать в моделях, но мне действительно нужны варианты магазина. В тестах я мог издеваться над этим «глобальным» объектом, подобным этому Shop.new(:test_shop) в spec_helper.

Является ли глобальная переменная моим единственным выбором? Я никогда их не использовал.

Я попытался использовать жгутик Settingslogic, но он определяет attr_accessors для определенных для магазина опций, и они сохраняются между запросами, что не то, что мне нужно.

+0

выглядит хорошо для меня .. что сломано? – AJcodez

+0

Если 'Shop' является моделью, то он уже должен быть доступен во всех частях вашего приложения: модели, виды, контроллеры, почтовые программы –

+0

@BenjaminSullivan Да,' Shop' доступен, но мне нужен '@ shop', который я определил в 'ApplicationController'. Для eaxample мне нужно рассчитать налог для текущего магазина в модели 'Order'. Я мог бы создать еще один экземпляр 'Shop', но у меня нет доступа к запросу. –

ответ

1

Один из способов сделать это было бы что-то вроде

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

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

, которая позволяет поддерживать отдельный магазин тока для каждого запроса.

Альтернативой является передача текущего магазина. Вначале это может показаться утомительным, но в конечном счете может быть проще рассуждать, чем глобальное или псевдо-глобальное поведение.

+0

Спасибо за ответ. Мне нравится первый вариант, потому что 'Shop' - это такая фундаментальная вещь в этом приложении, что передача его кажется подавляющей. Считаете ли вы, что этот подход будет отлично работать в Rails4 с помощью потокобезопасности! на? –

+0

Да - Shop.current - вещь для каждой нити –

+0

Рассмотрите возможность использования https://github.com/steveklabnik/request_store в качестве замены для Thread.current.он по существу «привязывает» переменную к времени жизни запроса, так что последующие запросы, которые не связаны друг с другом, не будут видеть остатки от предыдущих запросов. –

Смежные вопросы