Skip to content

Instantly share code, notes, and snippets.

@FranckyU
Last active August 29, 2015 13:56
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 FranckyU/9024949 to your computer and use it in GitHub Desktop.
Save FranckyU/9024949 to your computer and use it in GitHub Desktop.
# V2, please see https://gist.github.com/FranckyU/9024250 for V1
# UPDATES
# - Monkey patching ActiveRecord::Base to to handle it all
# - The 'with_..._connection' methods get native without having to include any module
# -----------------------------------
# PUT THE FOLLOWING IN AN INITIALIZER
# -----------------------------------
# Monkey patching ActiveRecord
# TODO move these connections configs into the config/database.yaml instead and load them from
module ActiveRecord
class Base
CONNECTIONS = {
read: [
{host: "any_host", adapter:"postgresql", encoding:"unicode", database:"db_name", pool: 5, username: "username", password:"xxxxxx"},
{host: "any_host", adapter:"postgresql", encoding:"unicode", database:"db_name", pool: 5, username: "username", password:"xxxxxx"},
{host: "any_host", adapter:"postgresql", encoding:"unicode", database:"db_name", pool: 5, username: "username", password:"xxxxxx"}
],
write: [
{host: "any_host", adapter:"postgresql", encoding:"unicode", database:"db_name", pool: 5, username: "username", password:"xxxxxx"},
{host: "any_host", adapter:"postgresql", encoding:"unicode", database:"db_name", pool: 5, username: "username", password:"xxxxxx"},
{host: "any_host", adapter:"postgresql", encoding:"unicode", database:"db_name", pool: 5, username: "username", password:"xxxxxx"}
]}
class << self
def with_connection(connexion_list, &block)
# randomly pick a connection
# acting as a load balancer
# connections are picked in a uniform way
connexion = connexion_list[rand(connexion_list.length)]
establish_connection(connexion) unless connection_config == connexion
yield
end
end
def with_connection(connexion_list, &block)
self.class.with_connection(connexion_list, block)
end
CONNECTIONS.each do |mode, connexion_array|
define_method "with_#{mode.to_s}_connection" do |&block|
with_connection(connexion_array, block)
end
self.class.instance_eval do
define_method "with_#{mode.to_s}_connection" do |&block|
with_connection(connexion_array, block)
end
end
end
end
end
# -----------------------------------
# USAGE
# -----------------------------------
# In a model
class Customer < ActiveRecord::Base
def a_complex_operation_method
# ....
with_read_connection do
# any db reaching code ....
end
# ....
with_write_connection do
# any db reaching code ....
end
# ....
end
end
# In a controller
class AnyController < ApplicationController
def any_action
# ....
Customer.with_read_connection do
# any db reaching code ....
end
# ....
Product.with_write_connection do
# any db reaching code ....
end
# ....
end
end
@FranckyU
Copy link
Author

And why not making a convention to put those read/write blocks in database.yaml and refactor ActiveRecord usual methods like save, create, update_attributes, find etc to use those with_..._connection blocks automatically then abstracting the complex stuffs to the end user

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment