Sinatra using ActiveRecord's Query Caching ability across multiple Databases : http://proccli.com/active-record-query-caching-sinatra-multiple-databases
require 'rubygems' | |
require 'sinatra/base' | |
require 'active_record' | |
require 'logger' | |
# override some instance variables and _force_ query caching to be enabled on databases other than AR::Base's connection | |
module ARQueryCachingHack | |
def self.included(klass) | |
# make sure you call this _AFTER_ a connection has been established, otherwise the connection | |
# will override these. it is kind of a pain, so the best bet is to include this in the initialization | |
def klass.enable_query_caching | |
self.connection.instance_variable_set(:@query_cache_enabled, true) | |
self.connection.instance_variable_set(:@query_cache, {}) | |
end | |
def klass.disable_query_caching | |
self.connection.instance_variable_set(:@query_cache_enabled, false) | |
end | |
end | |
end | |
ActiveRecord::Base.configurations = { | |
# this is a garbage connection so we can make sure AR::Base is on a different connection. If we are sharing | |
# the connection it kind of renders this moot since AR::Base is always query cached with the AR::QueryCache | |
# middleware | |
'test' => { | |
'adapter' => 'mysql', | |
'host' => 'localhost', | |
'username' => 'root', | |
'password' => '', | |
'database' => 'testing' # change this to some other DB besides +mysql+ | |
}, | |
# our separate target database. if we are on an app that uses multiple DB's then this would be the +other+ db, not | |
# AR::Base | |
'mysql' => { | |
'adapter' => 'mysql', | |
'host' => 'localhost', | |
'username' => 'root', | |
'password' => '', | |
'database' => 'mysql' | |
} | |
} | |
# AR::Base needs a connection before AR::QueryCache can take effect | |
ActiveRecord::Base.establish_connection 'test' | |
ActiveRecord::Base.logger = Logger.new($stdout) | |
# just to keep things separate, tuck all external models in their own module | |
module MySQL | |
# this would be a common base for all models that need a different DB, since all AR:Base models will just | |
# inherit from AR::Base | |
class Base < ActiveRecord::Base | |
self.abstract_class = true | |
establish_connection 'mysql' | |
end | |
# some model in a different database | |
class User < Base | |
include ARQueryCachingHack | |
set_table_name :user | |
end | |
# enable query caching on each model you want | |
def self.query_cache_models | |
[User].each &:enable_query_caching | |
end | |
end | |
class Demo < Sinatra::Base | |
use ActiveRecord::QueryCache | |
before do | |
# enable query caching by default. this probably isn't where you _want_ to put this, an initializer is probably best | |
MySQL.query_cache_models | |
ActiveRecord::Base.logger.info '-- enabling up per-model query caching --' | |
end | |
get '/' do | |
# with query caching | |
10.times{ MySQL::User.first } | |
# => CACHE (0.0ms) SELECT * FROM `user` LIMIT 1 | |
# without query caching | |
ActiveRecord::Base.logger.info '-- disabling up per-model query caching --' | |
MySQL::User.disable_query_caching | |
10.times{ MySQL::User.first } | |
# => MySQL::User Load (0.3ms) SELECT * FROM `user` LIMIT 1 | |
"Hack0rific!" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment