From 7fa9cb58c6e3b9311f0306173c48874ace7a6b04 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 13 Jul 2012 21:20:12 +0100 Subject: [PATCH] fix association :extend option --- .../associations/association_scope.rb | 8 ++------ .../associations/builder/association.rb | 5 +++++ .../builder/collection_association.rb | 18 ++++++++++++------ .../active_record/relation/query_methods.rb | 2 +- .../test/cases/associations/extension_test.rb | 2 +- activerecord/test/cases/relation_test.rb | 7 +++++-- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index 1c06fb2681c2e..1303822868703 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -15,9 +15,7 @@ def initialize(association) def scope scope = klass.unscoped - scope.extending!(*Array(options[:extend])) scope.merge! eval_scope(klass, reflection.scope) if reflection.scope - add_constraints(scope) end @@ -120,10 +118,8 @@ def table_name_for(reflection) end def eval_scope(klass, scope) - return scope if scope.is_a?(Relation) - - if scope.arity == 0 - klass.unscoped.instance_exec(&scope) + if scope.is_a?(Relation) + scope else klass.unscoped.instance_exec(owner, &scope) end diff --git a/activerecord/lib/active_record/associations/builder/association.rb b/activerecord/lib/active_record/associations/builder/association.rb index 331b72481486a..4a78a9c0764bf 100644 --- a/activerecord/lib/active_record/associations/builder/association.rb +++ b/activerecord/lib/active_record/associations/builder/association.rb @@ -23,6 +23,11 @@ def initialize(model, name, scope, options) @scope = nil @options = scope end + + if @scope && @scope.arity == 0 + prev_scope = @scope + @scope = proc { instance_exec(&prev_scope) } + end end def mixin diff --git a/activerecord/lib/active_record/associations/builder/collection_association.rb b/activerecord/lib/active_record/associations/builder/collection_association.rb index 98ca94b42a207..af81af4ad25d6 100644 --- a/activerecord/lib/active_record/associations/builder/collection_association.rb +++ b/activerecord/lib/active_record/associations/builder/collection_association.rb @@ -6,7 +6,7 @@ def valid_options super + [:table_name, :finder_sql, :counter_sql, :before_add, :after_add, :before_remove, :after_remove] end - attr_reader :block_extension + attr_reader :block_extension, :extension_module def initialize(*args, &extension) super(*args) @@ -27,18 +27,24 @@ def writable? private def wrap_block_extension - options[:extend] = Array(options[:extend]) - if block_extension + @extension_module = mod = Module.new(&block_extension) silence_warnings do - model.parent.const_set(extension_module_name, Module.new(&block_extension)) + model.parent.const_set(extension_module_name, mod) + end + + prev_scope = @scope + + if prev_scope + @scope = proc { |owner| instance_exec(owner, &prev_scope).extending(mod) } + else + @scope = proc { extending(mod) } end - options[:extend].push("#{model.parent}::#{extension_module_name}".constantize) end end def extension_module_name - @extension_module_name ||= "#{model.to_s.demodulize}#{name.to_s.camelize}AssociationExtension" + @extension_module_name ||= "#{model.name.demodulize}#{name.to_s.camelize}AssociationExtension" end def define_callback(callback_name) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index c567cc7cc43cf..c958fdb5d5616 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -529,7 +529,7 @@ def extending(*modules, &block) def extending!(*modules, &block) modules << Module.new(&block) if block_given? - self.extending_values = modules.flatten + self.extending_values += modules.flatten extend(*extending_values) if extending_values.any? self diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb index 91fd17e572b7e..917fe6cf52d1e 100644 --- a/activerecord/test/cases/associations/extension_test.rb +++ b/activerecord/test/cases/associations/extension_test.rb @@ -72,6 +72,6 @@ def test_proxy_association_after_scoped def extension_name(model) builder = ActiveRecord::Associations::Builder::HasMany.new(model, :association_name, nil, {}) { } builder.send(:wrap_block_extension) - builder.options[:extend].first.name + builder.extension_module.name end end diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 89f818a689865..034339e4136e2 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -191,11 +191,14 @@ def relation end test 'extending!' do - mod = Module.new + mod, mod2 = Module.new, Module.new assert relation.extending!(mod).equal?(relation) - assert [mod], relation.extending_values + assert_equal [mod], relation.extending_values assert relation.is_a?(mod) + + relation.extending!(mod2) + assert_equal [mod, mod2], relation.extending_values end test 'extending! with empty args' do