【问题标题】:A callback for ActiveRecord database connections?ActiveRecord 数据库连接的回调?
【发布时间】:2014-02-22 03:24:47
【问题描述】:

有什么方法可以挂钩 ActiveRecord 连接创建?我想在刚刚创建连接时运行一些代码。

我觉得这可能是一种在连接上设置 MySQL 变量的方法,因为 database.yml 中的“变量”似乎对我不起作用。 (How to turn off MySQL strict mode in Rails)

【问题讨论】:

  • 这是针对特定型号还是一般型号?

标签: mysql ruby-on-rails activerecord ruby-on-rails-4 database-connection


【解决方案1】:

ConnectionAdapter 定义了两个回调函数:checkout(连接)和:checkin(断开连接)。您可以将它用于特定的适配器

ActiveRecord::ConnectionAdapters::MysqlAdapter.set_callback :checkout, :after do
  raw_connection.set_your_variables ...
end

或者您可以将ActiveRecord::Base.connection.class 用于当前在database.yml 中声明的任何适配器

【讨论】:

  • 请注意,从 Rails 5.2 开始,此回调不是在连接建立后触发一次,而是在每次从连接池中检出时触发(就像在处理每个 HTTP 请求之前一样)。此外,您不能从中调用模型方法(您将获得无限递归)。
  • @Vladimir 作为行级安全性的一部分,我们需要将tenantId 设置为应用程序建立的每个数据库连接的数据库会话变量。这是我的代码,ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback :checkout, :after, ->(conn) { unless (ActsAsTenant.current_tenant.nil?) res = conn.execute("SET session.current_co_id ='#{ ActsAsTenant.current_tenant.id}'") end } 您能否建议使用 AbstractAdapter 的结帐回调是否是正确的用例?
【解决方案2】:

另外,如果您需要在建立连接并检索列信息后配置您的模型,您可以在模型中重新定义load_schema!类方法。

见:https://github.com/rails/rails/pull/31681#issuecomment-357113030

【讨论】:

  • 作为行级安全性的一部分,我们需要将tenantId 设置为应用程序建立的每个数据库连接的数据库会话变量。这是我的代码,ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback :checkout, :after, ->(conn) { unless (ActsAsTenant.current_tenant.nil?) res = conn.execute("SET session.current_co_id ='#{ ActsAsTenant.current_tenant.id}'") end } 您能否建议使用 AbstractAdapter 的结帐回调是否是正确的用例?
【解决方案3】:

只是为了添加到已接受的解决方案中,如果您需要从回调中触发数据库查询,您可以通过以下方式进行:

ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback :checkout, :before, ->(conn) {
    res = conn.execute('SELECT COUNT(*) from table_name')
    puts "res is #{res.each { |tuple| puts tuple.inspect}}"
}

注意:由于回调是在 ActiveRecord::ConnectionAdapters::AbstractAdapter 上定义的,因此应在检查任何数据库类型的连接之前执行此操作

正如@Envek 在对已接受答案的评论中指出的那样,您不应该真正使用 ActiveRecord 模型,因为您可能会遇到无休止的递归。另外(@Envek 也指出)请记住,回调将在每次使用池连接检出时触发,而不仅仅是一次。

最后,很有可能,您想从 Rails 中使用它。如果是这样,您可以将此代码放在 config/initializers 文件夹下的文件中。然后它将在应用程序启动时运行。在您希望为如何建立数据库连接添加逻辑的情况下很有用,尤其是在精确操作取决于特定查询的结果时。

【讨论】:

  • 作为行级安全性的一部分,我们需要将tenantId 设置为应用程序建立的每个数据库连接的数据库会话变量。这是我的代码,ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback :checkout, :after, ->(conn) { unless (ActsAsTenant.current_tenant.nil?) res = conn.execute("SET session.current_co_id ='#{ ActsAsTenant.current_tenant.id}'") end } 您能否建议使用 AbstractAdapter 的结帐回调是否是正确的用例?
猜你喜欢
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-04
  • 1970-01-01
  • 2012-04-28
  • 1970-01-01
相关资源
最近更新 更多