Skip to content

Instantly share code, notes, and snippets.

@wycleffsean
Last active July 15, 2020 18:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wycleffsean/bcdc9fe9ed5ad707abffafdcd0d4d638 to your computer and use it in GitHub Desktop.
Save wycleffsean/bcdc9fe9ed5ad707abffafdcd0d4d638 to your computer and use it in GitHub Desktop.
Defer class code until a db connection is established
# Enable class level code to lazily access database information.
# Often ActiveRecord class definitions will rely upon the table schema
# information. For example the following snippets would acquire a database
# connection:
# ignore_columns :foo
# # or
# attribute_names.each ...
# This results in rails accessing the database when booting, resulting in
# ridiculous behavior like this:
# bin/rake db:setup
# ActiveRecord::NoDatabaseError: Unknown database 'development'
#
# ...well yeah, duh. This module extends ActiveRecord to enable the lazy
# definition of class code - i.e. the code will execute the moment a
# connection is establish "naturally" rather than forcing one. e.g.
# once_connected { ignore_columns :foo }
module DeferredConnectionHandling
def self.extended(klass)
klass.class_eval do
@@database_has_connected = Concurrent::AtomicBoolean.new
end
end
def retrieve_connection
res = super
if @@database_has_connected.false?
@@database_has_connected.make_true
ActiveSupport.run_load_hooks(:database_connected)
end
res
end
def once_connected(&block)
ActiveSupport.on_load(:database_connected, self) do
class_eval(&block)
end
end
end
ActiveRecord::Base.extend(DeferredConnectionHandling)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment