2010-08-20 14 views
7

estoy usando Memcached como un almacén de objetos con mi aplicación Rails donde almaceno resultados de la búsqueda que son objetos de usuario en memcachedmemcached como un almacén de objetos en los carriles

Ahora, cuando voy a buscar los datos fuera Me da la Indefinido clase Memcached/Error de módulo. He encontrado una solución para este problema en este blog

http://www.philsergi.com/2007/06/rails-memcached-undefinded-classmodule.html

before_filter :preload_models 
    def preload_models 
    Model1 
    Model2 
    end 

que recomienda pre-carga los modelos antes de la mano. Me gustaría saber si hay una solución más elegante para este problema y existen inconvenientes en el uso de la técnica de precarga.

Gracias de antemano

Respuesta

8

tuve este problema también y creo que me ocurrió una buena solución.

Puede sobrescribir el método de búsqueda y rescatar el error y cargar las constantes correctas.

module ActiveSupport 
    module Cache 
    class MemCacheStore 
     # Fetching the entry from memcached 
     # For some reason sometimes the classes are undefined 
     # First rescue: trying to constantize the class and try again. 
     # Second rescue, reload all the models 
     # Else raise the exception 
     def fetch(key, options = {}) 
     retries = 2 
     begin 
      super 
     rescue ArgumentError, NameError => exc   
      if retries == 2 
      if exc.message.match /undefined class\/module (.+)$/ 
       $1.constantize 
      end 
      retries -= 1 
      retry   
      elsif retries == 1 
      retries -= 1 
      preload_models 
      retry 
      else 
      raise exc 
      end 
     end 
     end 

     private 

     # There are errors sometimes like: undefined class module ClassName. 
     # With this method we re-load every model 
     def preload_models  
     #we need to reference the classes here so if coming from cache Marshal.load will find them  
     ActiveRecord::Base.connection.tables.each do |model|  
      begin  
      "#{model.classify}".constantize 
      rescue Exception  
      end  
     end  
     end 
    end 
    end 
end 
+0

Esta solución es grande, pero es limitada a los modelos de registro activos. A veces estarás almacenando en caché clases que no son AR, en cuyo caso creo que tendrías que recurrir a la primera solución en este hilo. –

+0

Esto funcionó muy bien para mí, gracias! –

+0

@KonstantinGredeskoul Simplemente salte la parte de preload_models –

5

Corrimos a través de esto hoy, logramos encontrar una solución más concisa que debería funcionar para todas las clases.

Rails.cache.instance_eval do 
    def fetch(key, options = {}, rescue_and_require=true) 
    super(key, options) 

    rescue ArgumentError => ex 
    if rescue_and_require && /^undefined class\/module (.+?)$/ =~ ex.message 
     self.class.const_missing($1) 
     fetch(key, options, false) 
    else 
     raise ex 
    end 
    end 
end 

No sé por qué es no tener [MemCacheStore] es [MemCacheStore.const_missing] método llamado y todo siendo llamados en los carriles normales “-y” camino. Pero, esto debería emular eso!

Saludos,

Chris

+0

funciona para mí. buena solución – ifightcrime

Cuestiones relacionadas