Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Rails 2.3.8: Hash#deep_merge fails for HashWithIndifferentAccess

#4702

The following test fails with Rails 2.3.8

class HashTest < ActiveSupport::TestCase
  def test_deep_merge_for_hash_with_indifferent_access
    hash1 = { :k => { :v1 => 1 } }.with_indifferent_access
    hash2 = { :k => { :v2 => 2 } }

    assert_equal({ "k" => { "v1" => 1, "v2" => 2 } }, hash1.deep_merge(hash2))
  end 
end

Seems to be similar to #2732

Reported by Georg Ledermann · May 26th, 2010 @ 08:11 AM

State: duplicate
Milestone: 2.3.9
Assigned to: Jeremy Kemper Jeremy Kemper
Importance: none

Activity

  1. Neeraj Singh
    Neeraj Singh

    It is properly fixed in rails3. However if you need this functionality in rails 2.3.8 then a quick hack would be like this. I tested it and it is working although did not do any extensive test.

    class HashWithIndifferentAccess 
      def deep_merge(other_hash)
        orig_hash = self
        other_hash.each_pair do |key, value| 
          key = convert_key(key)
          oldval = orig_hash[key]
          newval = convert_value(value)
          
          oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
          newval = newval.to_hash if newval.respond_to?(:to_hash)
    
          merged_value = oldval.kind_of?(Hash) && newval.kind_of?(Hash) ?  oldval.deep_merge(newval) : newval
          orig_hash.regular_writer(key, merged_value)
        end
        self
      end
    end
    

    May 26th, 2010 @ 03:53 PM

  2. Santiago Pastorino
    Santiago Pastorino
    • Milestone set to 2.3.9
    • State changed from new to open

    Please do a patch file acording to the guidelines and a patch could be nice too ;).
    You have the code there :).
    Thanks.

    May 26th, 2010 @ 05:00 PM

  3. Neeraj Singh
    Neeraj Singh

    @Santiago I will have the patch and the test soon. Did not think that the fix would be backported since it is already fixed in rails3.

    May 26th, 2010 @ 07:10 PM

  4. Santiago Pastorino
    Santiago Pastorino

    Neeraj please review the latests tickets i think this one is duplicated

    May 26th, 2010 @ 07:24 PM

  5. Neeraj Singh
    Neeraj Singh

    I could not find any other open ticket about the same issue.

    Anyway here is a patch with test against rails 2-3-stable.

    May 27th, 2010 @ 02:13 AM

  6. Georg Ledermann
    Georg Ledermann

    IMHO this patch introduces another bug, because it changes self.

    Here is a failing test (based on my test above):

    class HashTest < ActiveSupport::TestCase
      def test_deep_merge_for_hash_with_indifferent_access
        hash1 = { :k => { :v1 => 1 } }.with_indifferent_access
        hash2 = { :k => { :v2 => 2 } }
    
        # First, check the result of a deep merge => OK
        assert_equal({ "k" => { "v1" => 1, "v2" => 2 } }, hash1.deep_merge(hash2))
    
        # Second, check if the originals are unchanged =====> FAILS!
        assert_equal({ "k" => { "v1" => 1 } }, hash1)
      end 
    end
    

    May 27th, 2010 @ 10:36 AM

  7. Neeraj Singh
    Neeraj Singh

    @Georg Good catch.

    Attached is an updated patch. I have included your test condition in the test this time. Thanks for the review.

    May 27th, 2010 @ 02:28 PM

  8. Lawrence Pit
    Lawrence Pit

    If it's properly fixed in rails 3, why can't that code be used instead of the code proposed in the patch?

    May 31st, 2010 @ 05:40 AM

  9. Neeraj Singh
    Neeraj Singh

    In rails3 the fix is much more elegant and requires changing a few more files.

    Patch that I have attached basically does the same thing.

    May 31st, 2010 @ 05:59 AM

  10. Santiago Pastorino
    Santiago Pastorino

    Neeraj this is not related with this issue https://rails.lighthouseapp.com/projects/8994/tickets/2732-deep_mer... i didn't review the issues but seems similar, please take a look

    May 31st, 2010 @ 10:21 PM

  11. Neeraj Singh
    Neeraj Singh

    going to class Hash from module Hash requires a lot more changes than it seems.

    June 1st, 2010 @ 08:40 AM

  12. Santiago Pastorino
    Santiago Pastorino
    • State changed from open to duplicate

    June 1st, 2010 @ 09:48 AM