From b17bc58c76c580911e18f2dd90a17aaae192a2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 15 Dec 2011 20:46:30 +0100 Subject: [PATCH] Move delegation reponsibilities of Relation to a module. Also precompile method missing calls for rofscale. --- activerecord/lib/active_record.rb | 1 + activerecord/lib/active_record/relation.rb | 23 +--------- .../lib/active_record/relation/delegation.rb | 42 +++++++++++++++++++ 3 files changed, 44 insertions(+), 22 deletions(-) create mode 100644 activerecord/lib/active_record/relation/delegation.rb diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index b1377c24dd..92f3666378 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -51,6 +51,7 @@ module ActiveRecord autoload :SpawnMethods autoload :Batches autoload :Explain + autoload :Delegation end autoload :Base diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 8aaab10b1e..0f78fe1ab7 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- require 'active_support/core_ext/object/blank' -require 'active_support/core_ext/module/delegation' module ActiveRecord # = Active Record Relation @@ -10,13 +9,7 @@ module ActiveRecord MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq] - include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain - - # These are explicitly delegated to improve performance (avoids method_missing) - delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :to => :to_a - delegate :ast, :engine, :to => :arel - delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, - :connection, :columns_hash, :auto_explain_threshold_in_seconds, :to => :klass + include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation attr_reader :table, :klass, :loaded attr_accessor :extensions, :default_scoped @@ -519,20 +512,6 @@ module ActiveRecord end end - protected - - def method_missing(method, *args, &block) - if Array.method_defined?(method) - to_a.send(method, *args, &block) - elsif @klass.respond_to?(method) - scoping { @klass.send(method, *args, &block) } - elsif arel.respond_to?(method) - arel.send(method, *args, &block) - else - super - end - end - private def references_eager_loaded_tables? diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb new file mode 100644 index 0000000000..c1fcd48a8e --- /dev/null +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -0,0 +1,42 @@ +require 'active_support/core_ext/module/delegation' + +module ActiveRecord + module Delegation + # These are explicitly delegated to improve performance (avoids method_missing) + delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :to => :to_a + delegate :ast, :engine, :to => :arel + delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, + :connection, :columns_hash, :auto_explain_threshold_in_seconds, :to => :klass + + def self.delegate_to_scoped_klass(method) + if method.to_s =~ /[a-z]\w*!?/ + module_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args, &block) + scoping { @klass.#{method}(*args, &block) } + end + RUBY + else + module_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args, &block) + scoping { @klass.send(#{method.inspect}, *args, &block) } + end + RUBY + end + end + + protected + + def method_missing(method, *args, &block) + if Array.method_defined?(method) + to_a.send(method, *args, &block) + elsif @klass.respond_to?(method) + ::ActiveRecord::Delegation.delegate_to_scoped_klass(method) + scoping { @klass.send(method, *args, &block) } + elsif arel.respond_to?(method) + arel.send(method, *args, &block) + else + super + end + end + end +end \ No newline at end of file