Created
March 24, 2010 19:00
-
-
Save robhurring/342648 to your computer and use it in GitHub Desktop.
Sinatra using ActiveRecord's Query Caching ability across multiple Databases : http://proccli.com/active-record-query-caching-sinatra-multiple-databases
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'sinatra_query_caching_demo' | |
run Demo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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