From b77dd218ce845f01753d02fcbc2605c9a5ee93e1 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Fri, 2 Apr 2010 17:34:48 +0100 Subject: Add Relation extensions --- activerecord/lib/active_record/named_scope.rb | 7 ++---- activerecord/lib/active_record/relation.rb | 8 +++++-- .../lib/active_record/relation/query_methods.rb | 25 ++++++++++++++++++---- .../lib/active_record/relation/spawn_methods.rb | 11 ++++++---- 4 files changed, 36 insertions(+), 15 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 9abf979cd0..3456332227 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -133,19 +133,16 @@ module ActiveRecord delegate :scopes, :with_scope, :with_exclusive_scope, :scoped_methods, :scoped, :to => :klass def self.init(klass, options, &block) - relation = new(klass, klass.arel_table) + relation = new(klass, klass.arel_table, &block) scope = if options.is_a?(Hash) - klass.scoped.apply_finder_options(options.except(:extend)) + klass.scoped.apply_finder_options(options) else options ? klass.scoped.merge(options) : klass.scoped end relation = relation.merge(scope) - Array.wrap(options[:extend]).each {|extension| relation.send(:extend, extension) } if options.is_a?(Hash) - relation.send(:extend, Module.new(&block)) if block_given? - relation.current_scoped_methods_when_defined = klass.send(:current_scoped_methods) relation end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 8577ec58f7..dde20532af 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -4,7 +4,7 @@ module ActiveRecord class Relation JoinOperation = Struct.new(:relation, :join_class, :on) ASSOCIATION_METHODS = [:includes, :eager_load, :preload] - MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having] + MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :extends] SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from] include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches @@ -13,8 +13,9 @@ module ActiveRecord delegate :insert, :to => :arel attr_reader :table, :klass + attr_accessor :extensions - def initialize(klass, table) + def initialize(klass, table, &block) @klass, @table = klass, table @implicit_readonly = nil @@ -22,6 +23,9 @@ module ActiveRecord SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)} (ASSOCIATION_METHODS + MULTI_VALUE_METHODS).each {|v| instance_variable_set(:"@#{v}_values", [])} + @extensions = [] + + apply_modules(Module.new(&block)) if block_given? end def new(*args, &block) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index e224781016..b5e8b7570a 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -10,8 +10,9 @@ module ActiveRecord next if [:where, :having].include?(query_method) class_eval <<-CEVAL - def #{query_method}(*args) + def #{query_method}(*args, &block) new_relation = clone + new_relation.send(:apply_modules, Module.new(&block)) if block_given? value = Array.wrap(args.flatten).reject {|x| x.blank? } new_relation.#{query_method}_values += value if value.present? new_relation @@ -21,8 +22,9 @@ module ActiveRecord [:where, :having].each do |query_method| class_eval <<-CEVAL - def #{query_method}(*args) + def #{query_method}(*args, &block) new_relation = clone + new_relation.send(:apply_modules, Module.new(&block)) if block_given? value = build_where(*args) new_relation.#{query_method}_values += [*value] if value.present? new_relation @@ -34,8 +36,9 @@ module ActiveRecord attr_accessor :"#{query_method}_value" class_eval <<-CEVAL - def #{query_method}(value = true) + def #{query_method}(value = true, &block) new_relation = clone + new_relation.send(:apply_modules, Module.new(&block)) if block_given? new_relation.#{query_method}_value = value new_relation end @@ -43,8 +46,16 @@ module ActiveRecord end end - def lock(locks = true) + def extending(*modules) + new_relation = clone + new_relation.send :apply_modules, *modules + new_relation + end + + def lock(locks = true, &block) relation = clone + relation.send(:apply_modules, Module.new(&block)) if block_given? + case locks when String, TrueClass, NilClass clone.tap {|new_relation| new_relation.lock_value = locks || true } @@ -191,6 +202,12 @@ module ActiveRecord private + def apply_modules(modules) + values = Array.wrap(modules) + @extensions += values if values.present? + values.each {|extension| extend(extension) } + end + def reverse_sql_order(order_query) order_query.to_s.split(/,/).each { |s| if s.match(/\s(asc|ASC)$/) diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 63246079cb..8fdd64afcc 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -7,9 +7,8 @@ module ActiveRecord return merged_relation unless r (Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS).reject {|m| [:joins, :where].include?(m)}.each do |method| - unless (value = r.send(:"#{method}_values")).blank? - merged_relation.send(:"#{method}_values=", value) - end + value = r.send(:"#{method}_values") + merged_relation.send(:"#{method}_values=", value) if value.present? end merged_relation = merged_relation.joins(r.joins_values) @@ -34,6 +33,9 @@ module ActiveRecord merged_relation.lock_value = r.lock_value unless merged_relation.lock_value + # Apply scope extension modules + merged_relation.send :apply_modules, r.extensions + merged_relation end @@ -69,7 +71,7 @@ module ActiveRecord result end - VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, + VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend, :order, :select, :readonly, :group, :having, :from, :lock ] def apply_finder_options(options) @@ -84,6 +86,7 @@ module ActiveRecord relation = relation.where(options[:conditions]) if options.has_key?(:conditions) relation = relation.includes(options[:include]) if options.has_key?(:include) + relation = relation.extending(options[:extend]) if options.has_key?(:extend) relation end -- cgit v1.2.3