class DatabaseSlave::ConnectionHandler

Public Class Methods

establish_connection() click to toggle source

Description

该方法根据 DatabaseSlave::Configuration 的配置建立所有的数据库从库链接.

Rails在启动时会调用 ActiveRecord::Base.establish_connection 来建立database.yml连接, 以上方法定义在 active_record/connection_adapters/abstract/connection_specification.rb

故该方法的设计参考了以上方法, 遵循了以上方法的设计逻辑.

注意下面方法中 klass 的实现:

因为remove_connection方法需要一个类名作为参数, 然后会在该类名上调用name方法.
查看源码可知原方法传入的是self, 即当前调用类; 类自带了name方法.

同理, 这里我们也应该传入一个类名, 但self不是所期望的, 于是这里使用了

  self.const_set(slave_name.to_s.strip.camelize, Class.new)

的方式动态地创建了一个类.

此外, 还可以通过定义一个代理类Proxy然后实现name方法的方式来达到目的.
# File lib/database_slave/connection_handler.rb, line 24
def self.establish_connection
  ActiveRecord::Base.slave_connections ||= []

  DatabaseSlave.configurations.each do |slave_name, config|
    adapter_method = "#{config['adapter']}_connection"
    spec           = ActiveRecord::Base::ConnectionSpecification.new(config, adapter_method)
    klass          = self.const_set(slave_name.to_s.strip.camelize, Class.new)

    unless ActiveRecord::Base.respond_to?(spec.adapter_method)
      raise DatabaseSlave::AdapterNotFound,
        "database configuration specifies not include #{config['adapter']} adapter"
    end

    ActiveRecord::Base.slave_connections << klass.name
    ActiveRecord::Base.remove_connection klass
    ActiveRecord::Base.connection_handler.establish_connection klass.name, spec
  end
end