2010-03-25 89 views
5

我有一些初始化函数,用于在PostgreSQL中设置数据库服务器端的审计日志记录(即不是rails)。至少有一个在将数据插入或更新任何审计表之前发布(设置当前用户),否则整个查询将失败壮观。如何在Rails中的数据库连接上执行查询?

在代码中运行任何保存操作之前,我可以很容易地调用这些代码,但DRY让我觉得我应该让代码在尽可能少的地方重复使用,特别是因为这与数据库不可知论的理想差异很大。目前我试图在初始化器中重写ActiveRecord :: Base.establish_connection来设置它,以便在我自动连接时立即运行查询,但它不像我期望的那样运行。这里是初始化代码:

 
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 

这不会给我任何错误,不幸的是我无法检查什么方法看起来像内部(我用的ActiveRecord :: Base.method (:establish_connection),但显然每次调用时都会创建一个新的Method对象,这看起来毫无价值,因为我无法检查object_id是否有任何有价值的信息,而且我也无法撤消编译)。

但是,代码似乎永远不会被调用,因为任何尝试在数据库对象上运行保存或更新都失败,正如我之前所预测的那样。如果这不是在连接数据库时立即执行代码的正确方法,那么是什么?

回答

3

Rails使用连接池,所以最好的办法是使用ActiveRecord的:: ConnectionAdapters的alias_method_chain ::连接池#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

我相信alias_method_chain需要在声明该方法后运行。 – Kevin 2010-03-29 16:35:29

+0

在声明该方法后,需要调用alias_method_chain,否则将无法找到该方法。另外,运行c的方法是执行的,而不是exec(我相信它给我的错误是exec是私有的)。但否则,这解决了我遇到的问题。谢谢! – sycobuny 2010-03-31 16:02:32

+0

以及如何在此上下文中获取*当前用户* – mlt 2016-10-06 21:22:32

0

你知道你的初始化器在数据库连接建立之前被调用吗?

如果没有可能出现错误的权威信息,我会利用ActiveRecord的源位于我的硬盘上。

挖掘基类并做一些调试,以查看何时调用ActiveRecord establish_connection相对于初始化程序的调用时间。无论是或者只是打开额外的详细调试。

0

在写代码挂钩的条款轨数据库调用和初始化,您可能想要使用db-charmer中的代码作为模板。它演示了一些与ActiveRecord交互的有趣方法,其中一个可能会按照你的意愿做。