2009-07-22 2 views
14

Скажем, я хочу сохранить некоторую переменную в моем контроллере. Я хочу инициализировать его в одном действии, увеличивать его в другом и читать в другом. Просто объявление этой переменной с @foo не работает, потому что @foo умирает после того, как созданное действие будет визуализировано.
Я не хочу, чтобы эта переменная хранилась в модели.Как сохранить переменную экземпляра для нескольких действий в контроллере?

Есть ли способ сохранить эту переменную, кроме сохранения ее в сеансе?
Кажется, я несколько раз сталкивался с этой простой проблемой, и я хочу знать, как лучше всего это решить.

ответ

22

Не совсем. Каждый вызов действия контроллера не имеет состояния. После завершения действия контроллера ничего не доступно. Новый экземпляр контроллера создается для каждого запроса и затем отбрасывается в конце запроса.

Если вы не хотите хранить его в сеансе или модели базы данных, у вас не так много параметров, если вы хотите, чтобы эта переменная была специфичной для определенного сеанса.

Если она глобальна во всех сессий, вы можете поместить его в @@class_variable, а не @instance_variable, но это может запутаться, как только вы начинаете иметь несколько Rails процессов (каждый, которые будут иметь свою собственную копию), или если вы работаете в потоковом режиме, вы можете столкнуться с неприятными ошибками параллелизма.

Я думаю, вы могли бы посмотреть на что-то вроде Memcached, но все равно нужно ввести, что в какой-то user_id или другого сеанса маркера (если это не глобальный)

7

Вы можете использовать встроенный в Rails.cache механизм для хранения значения, но, как упоминалось в первом ответе, вам нужно было бы отключить что-то вроде user_id. Это хороший способ, так как вы можете поддержать его с помощью разных механизмов хранения.

Rails.cache.write(:foo) 
# in later action 
Rails.cache.read(:foo) 

Еще одна вещь, которую вы могли бы смотреть на это флэш-хэш, который обеспечивает способ держать, чтобы сделать флэш-значение больше, чем в прошлом один последующий запрос.

Так в действии 1 можно создать значение:

flash[:foo] = some_value 
flash.keep(:foo) 

В действии 2 вы можете получить доступ к нему, и вызвать держать еще раз, если вы хотите, чтобы остаться в живых более последующих действий.

flash[:foo] #use it for something 
flash.keep(:foo) # keep it for another request 

Это немного сложная вещь, чтобы сделать чисто в контексте http-запросов.

+0

Кэш - хорошая идея, но я не думаю, что метод flash будет работать, если у вас есть несколько веб-серверов. – Scott

+0

Это зависит от вашего хранилища сеансов, потому что флэш-хэш фактически хранится в сеансе - например, если сеансы отключены, только flash.now будет работать – paulthenerd

+0

Кэш - это хорошая идея. Но если он использует MemoryStore, это для каждой памяти процесса, поэтому, если у вас нет одного процесса, который обрабатывает все запросы, последующие запросы могут не пострадать от процесса, который имеет его в памяти. Если память сохранена memcached, это будет намного лучше. –

1

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

Почему вы против использования сеанса для этого?

+0

Я довольно новичок в Rails, и я просто предположил, что сеанс был для * Important Things *, как идентификатор пользователя, а не что-то столь же тривиальное, как счетчик. Благодарю. –

11

Мне тоже интересно, почему вы против использования сеанса? Если вам не нравится работать с сеансом непосредственно в ваших действиях, вы можете эмулировать выживающую переменную экземпляра @foo с фильтрами. Что-то вроде этого, может быть?

class FooController < ApplicationController 
    before_filter :load_foo 
    after_filter :save_foo 

    private 
    def load_foo 
     @foo = session[:foo] || 0 
    end 

    def save_foo 
     session[:foo] = @foo 
    end 

end 

Ваши действия будет ли иметь возможность манипулировать значение через переменную экземпляра @count, и это будет автоматически сохраняется в сессии.

1

Не волнуйтесь, сеансы не кусаются.

Кроме того, это, вероятно, лучший способ сделать это.

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