spring icon indicating copy to clipboard operation
spring copied to clipboard

ActiveRecord::Base isn't necessarily the only class with a connection

Open betesh opened this issue 10 years ago • 3 comments

Sometimes, different models need to connect to different databases or as different users.

In lib/spring/application.rb, we make the assumption that the only model that needs to connect to the database is ActiveRecord::Base.

This should be configurable, i.e.

Rails.application.config.established_connections = [ActiveRecord::Base, SomeModelWithItsOwnConnection]
# This could default to [ActiveRecord::Base] or to []

module Spring
  class Application
    def disconnect_database
      Rails.application.config.established_connections.each do |model_class|
        model_class.remove_connection if model_class.configurations.any?
      end
    end
    def connect_database
      Rails.application.config.established_connections.each do |model_class|
        model_class.establish_connection if model_class.configurations.any?
      end
    end
    def active_record_configured?
      # This method is no longer necessary
    end
  end
end

This, of course, assumes that the way the user is overriding the connection is by defining configurations on SomeModelWithItsOwnConnection and then calling establish_connection, so without first checking that the Rails docs identify that as the recommended practice, I don't know if the above is the right approach.

betesh avatar Nov 24 '15 14:11 betesh

Is not this already possible using the after_fork hook? https://github.com/rails/spring#running-code-after-forking

rafaelfranca avatar Nov 24 '15 14:11 rafaelfranca

It looks like is possible that way--thanks for pointing me to the correct docs.

IMO, there is still a strong argument for making this more easily configurable. The code is already there--it's just that ActiveRecord::Base is hard-coded into it. Copying the logic into an after_fork would be duplicating code that doesn't need to be duplicated.

betesh avatar Nov 24 '15 15:11 betesh

I know this is a bit of an old one but I also recently bumped into this issue which was causing some of my tests to randomly fail.

I'm not sure if it was possible at the time, but we should be able to extract the names of the existing database connections and then re-establish them quite reliably with something like this:

connection_names = ActiveRecord::Base.connection_handler.connection_pools.map(&:spec).map(&:name)

connection_names.each do |connection_name|
  ActiveRecord::Base.connection_handler.establish_connection(connection_name)  
end

I'd be happy to make a pull request for this to remove the need for the after_fork hook.

chrisface avatar May 09 '18 07:05 chrisface