jaycode
jaycode

Reputation: 2958

Ruby weird assignment behaviour

Is this a ruby bug?

target_url_to_edit = target_url

if target_url_to_edit.include?("http://")
  target_url_to_edit["http://"] = ""
end

logger.debug "target url is now #{target_url}"

This returns target_url without http://

Upvotes: 2

Views: 185

Answers (4)

Jörg W Mittag
Jörg W Mittag

Reputation: 369420

No, this is not a bug in Ruby, this is just how shared mutable state works, not just in Ruby but in any programming language.

Think about it this way: my mom calls me "son", my friends call me "Jörg". If I cut my hair, then it doesn't matter which name you use to refer to me: I am the same person, regardless of whether you call me "son" or "Jörg" or "Mr. Mittag" or "hey, douchebag", therefore my hair will always be short. It doesn't magically grow back if you call me by a different name.

The same thing happens in your code: you refer to the string by two different names, but it doesn't matter which name you use; if the string changes, then it changes.

The solution is, of course, to not share mutable state and to not mutate shared state, like in @hurikhan77's answer.

Upvotes: 5

hurikhan77
hurikhan77

Reputation: 5931

You need to duplicate the in-memory object because variable names are just references to in-memory objects:

target_url_to_edit = target_url.dup

Now target_url_to_edit gets assigned a new copy of the original object.

For your case this code probably does the same in just one line (no dup, no if):

target_url_to_edit = target_url.sub(%r{^http://}, "")

Upvotes: 10

jaycode
jaycode

Reputation: 2958

Here is how to change its behaviour to force passing by value (note the star sign):

target_url_to_edit = *target_url.to_s

if target_url_to_edit.include?("http://")
  target_url_to_edit["http://"] = ""
end

logger.debug "target url is now #{target_url}"

And just like many things in ruby, hard to find where it's documented...

Upvotes: -1

alternative
alternative

Reputation: 13002

That is not a bug. It is the intended behavior because target_url_to_edit points to the same object in memory as target_url since Ruby uses references for object assignment. If you know C, it is similar to pointers.

Upvotes: 0

Related Questions