aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/core.rb
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2014-02-17 14:55:54 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2014-02-17 14:55:54 -0800
commit77b18d7ef47f4dd6bf39853ac83cc19a3593406f (patch)
treed5d7f6d993fe363bf0bbd79d642d9c860abcbc99 /activerecord/lib/active_record/core.rb
parent23ce2f61b5a7699af8213bf1b5d581da194ab8f4 (diff)
downloadrails-77b18d7ef47f4dd6bf39853ac83cc19a3593406f.tar.gz
rails-77b18d7ef47f4dd6bf39853ac83cc19a3593406f.tar.bz2
rails-77b18d7ef47f4dd6bf39853ac83cc19a3593406f.zip
add AST cache to the find_by method
Diffstat (limited to 'activerecord/lib/active_record/core.rb')
-rw-r--r--activerecord/lib/active_record/core.rb35
1 files changed, 35 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index d9aaf8597f..adc9383bdc 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -94,6 +94,7 @@ module ActiveRecord
end
class_attribute :default_connection_handler, instance_writer: false
+ class_attribute :find_by_statement_cache
def self.connection_handler
ActiveRecord::RuntimeRegistry.connection_handler || default_connection_handler
@@ -107,6 +108,40 @@ module ActiveRecord
end
module ClassMethods
+ def initialize_find_by_cache
+ self.find_by_statement_cache = {}.extend(Mutex_m)
+ end
+
+ def inherited(child_class)
+ child_class.initialize_find_by_cache
+ super
+ end
+
+ def find_by(*args)
+ return super if current_scope || args.length > 1 || reflect_on_all_aggregations.any?
+
+ hash = args.first
+
+ return super if hash.values.any? { |v| v.nil? || Array === v }
+
+ key = hash.keys
+
+ klass = self
+ s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
+ find_by_statement_cache[key] ||= StatementCache.new { |params|
+ wheres = key.each_with_object({}) { |param,o|
+ o[param] = params[param]
+ }
+ klass.where(wheres).limit(1)
+ }
+ }
+ begin
+ s.execute(hash).first
+ rescue TypeError => e
+ raise ActiveRecord::StatementInvalid.new(e.message, e)
+ end
+ end
+
def initialize_generated_modules
super