public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Allow deep merging of hash values for nested with_options. [#490 state:resolved]


Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
lawrencepit (author)
Sun Jul 13 18:53:41 -0700 2008
lifo (committer)
Wed Jul 16 17:59:08 -0700 2008
commit  40dbebba28bfa1c55737da7354542c3bdca4e1a1
tree    f21c9a31379dae25b5cedae5ea00053a272d9408
parent  cd6301557005617583e3f9ca5fb56297adcce7cc
...
1
 
2
3
4
5
6
7
 
8
9
10
...
 
1
2
3
4
5
6
7
8
9
10
11
0
@@ -1,10 +1,11 @@
0
-%w(keys indifferent_access reverse_merge conversions diff slice except).each do |ext|
0
+%w(keys indifferent_access deep_merge reverse_merge conversions diff slice except).each do |ext|
0
   require "active_support/core_ext/hash/#{ext}"
0
 end
0
 
0
 class Hash #:nodoc:
0
   include ActiveSupport::CoreExtensions::Hash::Keys
0
   include ActiveSupport::CoreExtensions::Hash::IndifferentAccess
0
+  include ActiveSupport::CoreExtensions::Hash::DeepMerge
0
   include ActiveSupport::CoreExtensions::Hash::ReverseMerge
0
   include ActiveSupport::CoreExtensions::Hash::Conversions
0
   include ActiveSupport::CoreExtensions::Hash::Diff
...
10
11
12
13
 
14
15
16
17
18
19
20
21
22
23
24
25
...
10
11
12
 
13
14
15
 
 
 
 
 
 
 
 
16
17
0
@@ -10,16 +10,8 @@ module ActiveSupport
0
 
0
     private
0
       def method_missing(method, *arguments, &block)
0
-        merge_argument_options! arguments
0
+        arguments << (arguments.last.respond_to?(:to_hash) ? @options.deep_merge(arguments.pop) : @options.dup)
0
         @context.send!(method, *arguments, &block)
0
       end
0
-
0
-      def merge_argument_options!(arguments)
0
-        arguments << if arguments.last.respond_to? :to_hash
0
-          @options.merge(arguments.pop)
0
-        else
0
-          @options.dup
0
-        end
0
-      end
0
   end
0
 end
...
245
246
247
 
 
 
 
 
 
 
 
 
 
248
249
250
...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
0
@@ -245,6 +245,16 @@ class HashExtTest < Test::Unit::TestCase
0
     assert(!indiff.keys.any? {|k| k.kind_of? String}, "A key was converted to a string!")
0
   end
0
 
0
+  def test_deep_merge
0
+    hash_1 = { :a => "a", :b => "b", :c => { :c1 => "c1", :c2 => "c2", :c3 => { :d1 => "d1" } } }
0
+    hash_2 = { :a => 1, :c => { :c1 => 2, :c3 => { :d2 => "d2" } } }
0
+    expected = { :a => 1, :b => "b", :c => { :c1 => 2, :c2 => "c2", :c3 => { :d1 => "d1", :d2 => "d2" } } }
0
+    assert_equal expected, hash_1.deep_merge(hash_2)
0
+
0
+    hash_1.deep_merge!(hash_2)
0
+    assert_equal expected, hash_1
0
+  end
0
+
0
   def test_reverse_merge
0
     defaults = { :a => "x", :b => "y", :c => 10 }.freeze
0
     options  = { :a => 1, :b => 2 }
...
38
39
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
42
43
...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
0
@@ -38,6 +38,33 @@ class OptionMergerTest < Test::Unit::TestCase
0
     end
0
   end
0
 
0
+  def test_nested_method_with_options_containing_hashes_merge
0
+    with_options :conditions => { :method => :get } do |outer|
0
+      outer.with_options :conditions => { :domain => "www" } do |inner|
0
+        expected = { :conditions => { :method => :get, :domain => "www" } }
0
+        assert_equal expected, inner.method_with_options
0
+      end
0
+    end
0
+  end
0
+
0
+  def test_nested_method_with_options_containing_hashes_overwrite
0
+    with_options :conditions => { :method => :get, :domain => "www" } do |outer|
0
+      outer.with_options :conditions => { :method => :post } do |inner|
0
+        expected = { :conditions => { :method => :post, :domain => "www" } }
0
+        assert_equal expected, inner.method_with_options
0
+      end
0
+    end
0
+  end
0
+
0
+  def test_nested_method_with_options_containing_hashes_going_deep
0
+    with_options :html => { :class => "foo", :style => { :margin => 0, :display => "block" } } do |outer|
0
+      outer.with_options :html => { :title => "bar", :style => { :margin => "1em", :color => "#fff" } } do |inner|
0
+        expected = { :html => { :class => "foo", :title => "bar", :style => { :margin => "1em", :display => "block", :color => "#fff" } } }
0
+        assert_equal expected, inner.method_with_options
0
+      end
0
+    end
0
+  end
0
+
0
   # Needed when counting objects with the ObjectSpace
0
   def test_option_merger_class_method
0
     assert_equal ActiveSupport::OptionMerger, ActiveSupport::OptionMerger.new('', '').class

Comments