Dup a Constant

I have a constant in my helper :
MYCONSTANT = { :opt => { :title => "abcdef" } }

In my view :
<%
joke = PeopleHelpers::MYCONSTANT.dup
joke[:opt][:title] = nil
#if i debug there, PeopleHelpers::MYCONSTANT = {:opt => {:title =>
nil}}
%>

I can't understand this behaviour and how fix it ?
Is it a bug ?

In fact the previous example doesn't change the value of
PeopleHelpers::MYCONSTANT

but if I do :
<%
joke = PeopleHelpers::MYCONSTANT.dup
joke[:opt][:title].sub!('a','b')
#if i debug there, PeopleHelpers::MYCONSTANT = {:opt => {:title =>
bbcdef}}
%>

the value changed.. why ?

I have a constant in my helper :
MYCONSTANT = { :opt => { :title => "abcdef" } }

In my view :
<%
joke = PeopleHelpers::MYCONSTANT.dup
joke[:opt][:title] = nil
#if i debug there, PeopleHelpers::MYCONSTANT = {:opt => {:title =>
nil}}
%>

I can't understand this behaviour and how fix it ?
Is it a bug ?

No, #dup and #clone typically make shallow copies.

orig = { :opt => { :title => 'hello' } }

=> {:opt=>{:title=>"hello"}}

dup = orig.dup

=> {:opt=>{:title=>"hello"}}

dup[:opt][:title]

=> "hello"

dup[:opt][:title] = nil

=> nil

dup

=> {:opt=>{:title=>nil}}

orig

=> {:opt=>{:title=>nil}}

orig = { :opt => { :title => 'hello' } }

=> {:opt=>{:title=>"hello"}}

clone = orig.clone

=> {:opt=>{:title=>"hello"}}

clone[:opt][:title]

=> "hello"

clone[:opt][:title] = nil

=> nil

clone

=> {:opt=>{:title=>nil}}

orig

=> {:opt=>{:title=>nil}}

If you want a "deep" copy, usually you Marshal and un-Marshal:

orig = { :opt => { :title => 'hello' } }

=> {:opt=>{:title=>"hello"}}

marshaled = Marshal.load(Marshal.dump(orig))

=> {:opt=>{:title=>"hello"}}

marshaled[:opt][:title]

=> "hello"

marshaled[:opt][:title] = nil

=> nil

marshaled

=> {:opt=>{:title=>nil}}

orig

=> {:opt=>{:title=>"hello"}}

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

My understanding is that dup makes a copy of the hash contents, but
since the contents are themselves references rather than simple
objects you end up with a new hash containing references to the same
objects, which can then be modified as you have noted (even though
they are notionally constant).

Colin

Thank you very much for your explanations :slight_smile:

adrien