2010-03-25 20 views
5

Tengo ciertas funciones de inicialización que utilizo para configurar el registro de auditoría en el lado del servidor de BD (es decir, no en los rieles) en PostgreSQL. Al menos un tiene que emitirse (configuración del usuario actual) antes de insertar datos en o actualizar cualquiera de las tablas auditadas, o de lo contrario toda la consulta fallará espectacularmente.¿Cómo ejecuto consultas sobre la conexión de DB en Rails?

Puedo llamarlos fácilmente cada vez antes de ejecutar cualquier operación de guardado en el código, pero DRY me hace pensar que debería repetir el código en el menor número de lugares posibles, especialmente porque esto difiere mucho del ideal de agnosticidad de la base de datos. Actualmente estoy intentando anular ActiveRecord :: Base.establish_connection en un inicializador para configurarlo para que las consultas se ejecuten tan pronto como me conecte automáticamente, pero no se comporta como esperaba. Aquí está el código en el inicializador:

 
class ActiveRecord::Base 
    # extend the class methods, not the instance methods 
    class << self 
    alias :old_establish_connection :establish_connection # hide the default 

    def establish_connection(*args) 
     ret = old_establish_connection(*args) # call the default 

     # set up necessary session variables for audit logging 
     # call these after calling default, to make sure conn is established 1st 
     db = self.class.connection 
     db.execute("SELECT SV.set('current_user', '[email protected]')") 
     db.execute("SELECT SV.set('audit_notes', NULL)") # end "empty variable" err 

     ret # return the default's original value 
    end 
    end 
end 

puts "Loaded custom establish_connection into ActiveRecord::Base" 
 
sycobuny:~/rails$ ruby script/server 
=> Booting WEBrick 
=> Rails 2.3.5 application starting on http://0.0.0.0:3000 
Loaded custom establish_connection into ActiveRecord::Base 

Esto no me da ningún error, y por desgracia no se puede comprobar lo que el método se parece a nivel interno (yo estaba usando ActiveRecord :: Base.method (: establecer_conexión), pero aparentemente eso crea un nuevo objeto Método cada vez que se invoca, lo cual es aparentemente inútil porque no puedo verificar la información valiosa de object_id y tampoco puedo revertir la compilación).

Sin embargo, nunca parece que se llame al código, porque cualquier intento de ejecutar un guardado o una actualización en un objeto de base de datos falla como predije anteriormente. Si esta no es una forma adecuada de ejecutar el código de forma inmediata al conectarse a la base de datos, entonces ¿qué es?

Respuesta

3

Rails utiliza la agrupación de conexiones, así que lo mejor es utilizar un alias_method_chain de ActiveRecord :: :: ConnectionAdapters ConnectionPool # new_connection

module ActiveRecord 
    Module ConnectionAdapters 
    class ConnectionPool 
     alias_method_chain :new_connection, :my_stuff 
     private 
     def new_connection_with_my_stuff 
     c = new_connection_without_my_stuff 
     # Do your stuff with 
     # c.exec(<your sql command>) 
     c 
     end 
    end 
    end 
end 
+0

Creo que alias_method_chain debe ejecutarse después de que se declare el método. – Kevin

+0

alias_method_chain necesita ser llamado después de que se declare el método, o de lo contrario no encontrará el método. Además, el método para ejecutar fuera de c es ejecutar, en lugar de ejecutar (creo que el error que me dio fue que el ejecutivo era privado). Pero, de lo contrario, esto resuelve el problema que estaba teniendo. ¡Gracias! – sycobuny

+0

¿Y cómo obtener * usuario actual * en este contexto? – mlt

0

¿Sabe que se está llamando a su inicializador antes de que se establezca la conexión a la base de datos?

Sin información autorizada sobre lo que podría estar mal, me gustaría aprovechar el hecho de que la fuente de ActiveRecord está en mi disco duro.

Adéntrese en la clase base y realice una pequeña depuración de errores para ver cuándo se está llamando a ActiveRecord establish_connection en relación a cuando se llama a su inicializador. O eso o simplemente activa la depuración extra verbosa.

0

En cuanto a la necesidad de escribir código para conectar los carriles llamadas bases de datos y las inicializaciones, es posible que desea utilizar el código de db-charmer como plantilla. Demuestra una serie de formas interesantes de interactuar con ActiveRecord y una de ellas probablemente hará lo que usted desea.

Cuestiones relacionadas