Internetbureau Holder

Fixing i18n backend cache key when using memcached and Ruby 1.8.6

Paul Engel vr 11 jun 10

Implementing internationalization for Rails sites is a common thing. Most of you are likely using the i18n library developed by Sven Fuchs.

Backends and chaining them together

The default backend (I18n::Backend:: Simple) reads its translations from YAML files stored in the /config/locales directory and uses an in-memory hash to ensure efficiency. In most cases, this backend is sufficient enough when the application doesn’t require translation management by end-users. But if so, storing translations within YAML files isn’t preferred. You want to use a database for doing this.

Fortunately, i18n also provides a backend for database storage (I18n::Backend::ActiveRecord). Chaining both backends enables you to define translations within the YAML files and to override them with translations stored in the database.

I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)

The usage of memcached ensures efficiency.

require "memcache"

yaml   = YAML.load(File.read(File.join(RAILS_ROOT, "config", "memcached.yml")))
config = yaml["defaults"].merge yaml[RAILS_ENV || "development"]

mem_cache               = MemCache.new config
mem_cache.servers = config["servers"]

I18n.cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store, mem_cache

The problem

Using this setup in Ruby 1.8.6 can raise an error caused by an invalid memcached cache key. This key is generated by the protected method I18n::Backend::Cache.cache_key which doesn’t provide a clean key in Ruby 1.8.6 as it uses the Hash.hash method to create the key. The pitfall is that isn’t reliable in Ruby < 1.8.7:

{}.hash != {}.hash.

The fix

A solution is to upgrade Ruby, but doing this can bring a lot of side effects to Ruby dependent libraries on your system. We are clearly searching for some 1.8.7 goodies to use in 1.8.6. Fortunately, Marc-André Lafortune has created the gem Backports which provides us just that.

But as backports is not endorsed by ruby-core and you’re noted to use this with caution!

To fix the I18n cache key problem, just extract the hash method backport and use it in your project:

class Hash
  
  def hash
    h = 0
    each do |key, value|
      h ^= key.hash ^ value.hash
    end
    h
  end unless {}.hash == {}.hash
  
end

Enjoy!

Gepost in hor |  0 reacties

Plaats je reactie





Welcome to Holland On Rails

This weblog is the official Ruby techblog from the guys at Holder, a Ruby development company. Holder is also the company behind the RubyAndRails Europe Conference in Amsterdam.

Recente Jobs


Bekijk alle jobs »»

Gereedschapskist

Onmisbare tools voor
iedere developer!
Ruby On Rails
Framework voor de web 2.0 developer. Eindelijk vooruitgang!
TextMate
Editor for true pro's
Typ, tab, top :-)
Nee, niet voor Win.
Made On A Mac
En nou is het over met die saaie grijze Windows bak van je!

Auteurs op deze site

Chris Obdam

'Less is more' evangelist, past dit ook dagelijks toe op zijn tandenborstel.

Chiel Wester

Snelheidswonder op Ruby wielen. Leuk om mee te pair-programmen ;-) Recommend Me

Stephan Kaag

Het eerste Rails coreteam- member uit Nederland? Rails evangelist van het eerste uur.

Paul Engel

Én Rails programmeren én interfaces designen? Je zou hem superman kunnen noemen..

Dax Huiberts

Official Zip-Programmer, skinny code is helemaal zijn ding. Haalt meer code weg dan dat er bij komt.

Freek Monteban

Het nieuwste telg uit het Holland on Rails nest! Hij doet niets anders meer!

Johan Vermeulen

De stylesheet-koning uit de kop van Noord-Holland!