aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2013-08-30 16:48:20 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2013-08-30 16:48:20 -0700
commit74abdb1eab2dffea6247af7653b994c1f1bfe2ef (patch)
tree7fcbead76e4d42dad7485a2b41fda9237ac7d9a1 /activerecord/lib/active_record
parent1b84df430c324ff90b0a180039de0a345184ec94 (diff)
downloadrails-74abdb1eab2dffea6247af7653b994c1f1bfe2ef.tar.gz
rails-74abdb1eab2dffea6247af7653b994c1f1bfe2ef.tar.bz2
rails-74abdb1eab2dffea6247af7653b994c1f1bfe2ef.zip
move the cache to the AR models and populate it on inherited
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/base.rb2
-rw-r--r--activerecord/lib/active_record/relation/delegation.rb49
2 files changed, 31 insertions, 20 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index b06add096f..04e3dd49e7 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -18,6 +18,7 @@ require 'arel'
require 'active_record/errors'
require 'active_record/log_subscriber'
require 'active_record/explain_subscriber'
+require 'active_record/relation/delegation'
module ActiveRecord #:nodoc:
# = Active Record
@@ -290,6 +291,7 @@ module ActiveRecord #:nodoc:
extend Translation
extend DynamicMatchers
extend Explain
+ extend Delegation::DelegateCache
include Persistence
include ReadonlyAttributes
diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb
index 2b132d517d..31f924ba52 100644
--- a/activerecord/lib/active_record/relation/delegation.rb
+++ b/activerecord/lib/active_record/relation/delegation.rb
@@ -1,8 +1,33 @@
-require 'thread'
-require 'thread_safe'
+require 'active_support/concern'
module ActiveRecord
module Delegation # :nodoc:
+ module DelegateCache
+ def relation_delegate_class(klass) # :nodoc:
+ @relation_delegate_cache[klass]
+ end
+
+ def initialize_relation_delegate_cache # :nodoc:
+ @relation_delegate_cache = cache = {}
+ [
+ ActiveRecord::Relation,
+ ActiveRecord::Associations::CollectionProxy,
+ ActiveRecord::AssociationRelation
+ ].each do |klass|
+ delegate = Class.new(klass) {
+ include ActiveRecord::Relation::ClassSpecificRelation
+ }
+ const_set klass.name.gsub('::', '_'), delegate
+ cache[klass] = delegate
+ end
+ end
+
+ def inherited(child_class)
+ child_class.initialize_relation_delegate_cache
+ super
+ end
+ end
+
extend ActiveSupport::Concern
# This module creates compiled delegation methods dynamically at runtime, which makes
@@ -71,30 +96,14 @@ module ActiveRecord
end
module ClassMethods # :nodoc:
- @@subclasses = ThreadSafe::Cache.new(:initial_capacity => 2)
-
def create(klass, *args)
relation_class_for(klass).new(klass, *args)
end
private
- # Cache the constants in @@subclasses because looking them up via const_get
- # make instantiation significantly slower.
- def relation_class_for(klass)
- klass_name = klass.name
-
- if klass_name
- my_cache = @@subclasses.compute_if_absent(self) { ThreadSafe::Cache.new }
- # This hash is keyed by klass.name to avoid memory leaks in development mode
- my_cache.compute_if_absent(klass_name) do
- # Cache#compute_if_absent guarantees that the block will only executed once for the given klass_name
- subclass_name = "#{name.gsub('::', '_')}_#{klass_name.gsub('::', '_')}"
- const_set(subclass_name, Class.new(self) { include ClassSpecificRelation })
- end
- else
- self
- end
+ def relation_class_for(klass)
+ klass.relation_delegate_class(self)
end
end