Rails uses Hashes a lot for passing options to methods. I typically use Hash#merge
to add any default options to them but I’ve always hated the syntax and frequently got it backwards.
1 |
options = {:value => 'default', :size => 30}.merge(options) |
Facets has a Hash#reverse_merge
that gets the order right. And the implementation is so simple, I’m kicking myself for not using it sooner.
The Code
1 2 3 4 |
# File lib/core/facets/hash/merge.rb, line 15 def reverse_merge(other) other.merge(self) end |
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#!/usr/bin/ruby -wKU # # Code Reading #4 require '../base' require "facets/hash/merge" class Example def self.create { :users => [:edavis], :servers => [:app1, :app2, :app3] } end end ap(Example.create.reverse_merge({ :shell => '/bin/bash', :users => [:rails] })) class HashReverseMerge '/bin/bash'}) assert_equal '/bin/bash', @example[:shell] assert_equal [:edavis], @example[:users] end def test_should_let_the_caller_win @example = Example.create.reverse_merge({ :shell => '/bin/bash', :users => [:rails] }) assert_equal '/bin/bash', @example[:shell] assert_equal [:edavis], @example[:users] end end |
Review
Now I can rewrite the default options like:
1 |
options = options.reverse_merge({:value => 'default', :size => 30}) |
(There are also bang versions, #merge!
and #reverse_merge!
)