Doesn''t it depend on which direction you decide to conduct the merge?
E.g.:
existing_options.merge(new_options)
will overwrite existing keys (which is normally what you want if existing
options specify defaults). However:
new_options.merge(existing_options)
will cause any keys present in new_options to be overwritten by those in
existing_options (if they exist).
I don''t know if this answers the question, but I hope it helps...
Michael Schuerig wrote:>
>
>
> I''m looking for a nice and idiomatic way to merge options hashes.
The
> usual ways for scalar-valued options are
>
> def my_method(options = {})
> options = {
> :foo => ''something'',
> :bar => ''else''
> }.update(options)
> ...
> end
>
> and
>
> def my_method(options = {})
> options = options.reverse_merge(
> :foo => ''something'',
> :bar => ''else''
> )
> ...
> end
>
> The cases I''m interested in are different. For illustration,
let''s take
> a helper method that inserts a text field into the page and adds the
> class attribute "special". In particular, it should not overwrite
> existing class attribute options, only add a new one.
>
> def my_special_text_field1(object, field, options = {})
> if options[:class]
> options[:class] += '' special''
> else
> options[:class] = ''special''
> end
> text_field(object, field, options)
> end
>
> That''s rather clumsy. How about this, then
>
> def my_special_text_field2(object, field, options = {})
> options[:class] =
> (String(options[:class]).split(/\s+/) |
[''special'']) * '' ''
> text_field(object, field, options)
> end
>
> Ugh. Well, it has the added advantage that duplicates are not added.
> Alas, the code is not very obvious. But with a bit of encapsulation and
> class opening that can be rectified.
>
> def my_special_text_field3(object, field, options = {})
> text_field(object, field,
> options.merge_multivalued(:class => ''special''))
> end
>
> class Hash
> def merge_multivalued(other_hash)
> merge_arrays(other_hash) do |old_value, other_array|
> (String(old_value).split(/\s+/) | other_array) * ''
''
> end
> end
>
> private
>
> def merge_arrays(other_hash, &block)
> # add values from other_hash to already present values
> merged_old = inject({}) do |memo, (key, value)|
> if other_value = other_hash[key]
> other_array = other_value.kind_of?(Array) ?
> other_value : other_value.split(/\s+/)
> memo[key] = block[value, other_array]
> else
> memo[key] = value
> end
> memo
> end
> # add new values from other_hash
> other_hash.merge(merged_old)
> end
> end
>
> That does look a bit over-engineered. Here''s a minimalist (and
slightly
> rogueish) alternative.
>
> def my_special_text_field4(object, field, options = {})
> options[:class] = (Array(options[:class]) |
[''special'']) * '' ''
> text_field(object, field, options)
> end
>
> After all this, I still can''t say that I''m fully
satisfied with any of
> the options. I''m looking forward to suggestions.
>
> Michael
>
> --
> Michael Schuerig
> mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org
> http://www.schuerig.de/michael/
>
> >
>
>
--
View this message in context:
http://www.nabble.com/-Rails--Idiomatic-way-to-merge-%22multivalued%22-options-tf3133390.html#a8682416
Sent from the RubyOnRails Users mailing list archive at Nabble.com.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---