I'm trying to use the excellent idea of the QueryCache rather than reimplement the wheel (I want to use the query cache for some tables which rarely change, but avoid it for regularly changing tables)
class MyRarelyChangingThingy < ActiveRecord::Base
establish_connection :adapter => mysql, ...
:query_cache => true
end
(Alternatively, defining it as a specialised database adapter):
module ActiveRecord
class Base
def self.cached_connection(config)
config = config.symbolize_keys
raise ArgumentError, "No connection specified" unless
config.has_key? :connection
QueryCache.new(config[:connection])
end
end
end
class MyRarelyChangingThingy < ActiveRecord::Base
establish_connection :adapter => 'cached', :connection => self.connection
end
However, my attempts always fail at the same problem:
NoMethodError: undefined method `symbolize_keys' for #<ActiveRecord::ConnectionAdapters::MysqlAdapter:0xb7736a4c>
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/query_cache.rb:41:in `send'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/query_cache.rb:41:in `method_missing'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:207:in `establish_connection'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:266:in `connection_without_query_cache='
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/query_cache.rb:54:in `connection='
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:262:in `connection_without_query_cache='
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/query_cache.rb:54:in `connection='
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:230:in `retrieve_connection'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:78:in `connection'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/base.rb:1140:in `add_limit!'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/base.rb:1102:in `construct_finder_sql'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/base.rb:997:in `find_every'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/base.rb:418:in `find'
The reason for this seems to be that assigning a connection to a class now believes ONLY children classes of AbstractAdapter can be valid connections, which QueryCache isn't. QueryCache is wrongly presumed to be a connection specification rather than an connection itself.
Rather than make QueryCache a child class of AbstractAdapter (which would inherit a number of functions and mask them rather than pass them on to the real connection), I changed the inheritance check. Here is the patch:
Index: trunk/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
===================================================================
--- trunk/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb (revision 6176)
+++ trunk/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb (working copy)
@@ -255,7 +255,7 @@
# Set the connection for the class.
def self.connection=(spec) #:nodoc:
- if spec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter)
+ if spec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter) or spec.kind_of?(ActiveRecord::QueryCache)
active_connections[name] = spec
elsif spec.kind_of?(ConnectionSpecification)
config = spec.config.reverse_merge(:allow_concurrency => @@allow_concurrency)