Rails.cache.fetch, символы и Memcached

У меня есть приложение rails 2.3.4 и строка, которая выглядит так:

temp = Rails.cache.fetch(:temp_id) { User.find_by_name('Temp').id } 

и все работало нормально, пока я не решил переключить уровень кэширования на memcached, добавив в свой environment.rb следующее:

config.cache_store = :mem_cache_store

Теперь строка, которая раньше работала нормально, дает мне следующую ошибку:

 undefined method 'length' for :temp_id:Symbol           

/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.4/lib/active_support/vendor/memcache-client-1.7.4/memcache.rb:645:in 'get_server_for_key'

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

Спасибо


person gmoniey    schedule 25.02.2010    source источник


Ответы (2)


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

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

Поскольку кеши являются внешними, за исключением кеша в памяти, я не уверен, что вспомогательные символы будут полезны, кроме предотвращения таких случаев, как ваш. Ключ на самом деле будет записан куда-то в какой-то выход (это не только внутреннее приложение Ruby), поэтому концептуально ключ должен быть строкой.

Редактировать в ответ на комментарий: да, конечно, возможно и совершенно разумно в этом случае создать обезьяний патч, чтобы обойти необходимость изменять все вызовы. Что вы предлагаете, так это (скопировано в ответ для удобочитаемости):

class MemCache
  def get_server_for_key_with_symbols(key, options = {})
    key = key.to_s if key.is_a? Symbol
    get_server_for_key_without_symbols(key, options)
  end
  alias_method_chain :get_server_for_key, :symbols
end

Я бы также подумал о том, чтобы просто выполнить поиск и замену по всему проекту для \.fetch(:\w+) и заменить его на \.fetch("$1") (при необходимости повторить для read и write). Вероятно, это должно охватывать 95% всех случаев, а последующий запуск вашего набора тестов должен выявить остальные ошибки.

В целом: несмотря на то, что в наши дни документация по Rails довольно хороша, многие допущения, к сожалению, все еще неявны. Как правило, рекомендуется внимательно изучить примеры, приведенные в документации, и использовать тот же стиль. Задокументированные примеры всегда показывают, как предполагается использовать фреймворк.

person molf    schedule 25.02.2010
comment
использование строковых ключей может показаться очевидным решением, но разочаровывает то, что, поскольку символы изначально работали, все мои операторы кеша используют их. На данный момент это просто проще патчить обезьяны, похоже, что-то вроде этого работает: #это чтобы иметь возможность использовать символы для класса rails.cache MemCache def get_server_for_key_with_symbols(key, options = {}) key = key.to_s if key. это? Символ get_server_for_key_without_symbols(key, options) end alias_method_chain :get_server_for_key, :symbols end - person gmoniey; 25.02.2010
comment
спасибо за очистку редактирования моего патча обезьяны. Кажется, что вы не можете делать стили в комментариях. Честно говоря, единственная причина, по которой я не хочу выполнять поиск и замену по всему проекту, заключается в том, что я чувствую, что символы обеспечивают более удобочитаемость. Очевидно, что это полностью личное предпочтение, и оно сильно связано с моим редактором кода. Спасибо. - person gmoniey; 25.02.2010
comment
Вы can too выполняете стиль в комментариях. В основном. - person Sai; 07.03.2010

FWIW, это канонически Rails.cache.read и Rails.cache.write.

person Sai    schedule 07.03.2010
comment
Я не думаю, что это правильно - вариант .fetch предназначен для выполнения блока при промахе кеша. По-моему, это довольно распространенная идиома. - person Joe; 13.01.2012