From dfb238a0d04be235a2f2d1bc54fbdd088850d79c Mon Sep 17 00:00:00 2001 From: Lawrence Pit Date: Thu, 26 Jun 2008 09:58:56 +1000 Subject: [PATCH] Nested with_options merge hashes within options --- activesupport/lib/active_support/option_merger.rb | 10 ++++--- activesupport/test/option_merger_test.rb | 27 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/activesupport/lib/active_support/option_merger.rb b/activesupport/lib/active_support/option_merger.rb index 1a4ff9d..3e83646 100644 --- a/activesupport/lib/active_support/option_merger.rb +++ b/activesupport/lib/active_support/option_merger.rb @@ -15,10 +15,12 @@ module ActiveSupport end def merge_argument_options!(arguments) - arguments << if arguments.last.respond_to? :to_hash - @options.merge(arguments.pop) - else - @options.dup + arguments << (arguments.last.respond_to?(:to_hash) ? merge_hashes(@options, arguments.pop) : @options.dup) + end + + def merge_hashes(outer, inner) + outer.merge(inner) do |key, oldval, newval| + oldval.respond_to?(:to_hash) && newval.respond_to?(:to_hash) ? merge_hashes(oldval, newval) : newval end end end diff --git a/activesupport/test/option_merger_test.rb b/activesupport/test/option_merger_test.rb index 509c6d3..0d72314 100644 --- a/activesupport/test/option_merger_test.rb +++ b/activesupport/test/option_merger_test.rb @@ -38,6 +38,33 @@ class OptionMergerTest < Test::Unit::TestCase end end + def test_nested_method_with_options_containing_hashes_merge + with_options :conditions => { :method => :get } do |outer| + outer.with_options :conditions => { :domain => "www" } do |inner| + expected = { :conditions => { :method => :get, :domain => "www" } } + assert_equal expected, inner.method_with_options + end + end + end + + def test_nested_method_with_options_containing_hashes_overwrite + with_options :conditions => { :method => :get, :domain => "www" } do |outer| + outer.with_options :conditions => { :method => :post } do |inner| + expected = { :conditions => { :method => :post, :domain => "www" } } + assert_equal expected, inner.method_with_options + end + end + end + + def test_nested_method_with_options_containing_hashes_going_deep + with_options :html => { :class => "foo", :style => { :margin => 0, :display => "block" } } do |outer| + outer.with_options :html => { :title => "bar", :style => { :margin => "1em", :color => "#fff" } } do |inner| + expected = { :html => { :class => "foo", :title => "bar", :style => { :margin => "1em", :display => "block", :color => "#fff" } } } + assert_equal expected, inner.method_with_options + end + end + end + # Needed when counting objects with the ObjectSpace def test_option_merger_class_method assert_equal ActiveSupport::OptionMerger, ActiveSupport::OptionMerger.new('', '').class -- 1.5.5.1