Augusto
Augusto

Reputation: 1150

Why does string replace modifies the original variable value?

9.3 I'm getting a strange behaviour and I cannot understand why:

s = self.shopify_p
s.title
=> "Disco (Wholesale)"

Right now I'd like to have a new variable with the content of s.title without the " (Wholesale)" part. So I do the following:

original_title = s.title
=> "Disco (Wholesale)" 
original_title[" (Wholesale)"] = ""
=> ""

Now if I do:

original_title
=> "Disco"

Which is ok but the strange thing is that it seems that the last string replace affected even the original s variable:

s.title
=> "Disco"

I really cannot understand this...can you tell me what is happening here?

s.title should still be "Disco (Wholesale)"...or not?

Upvotes: 5

Views: 2631

Answers (3)

Stefan
Stefan

Reputation: 114178

After original_title = s.title both original_title and s.title reference the same object.

To actually copy the string either use Object#dup:

original_title = s.title.dup

dup → an_object

Produces a shallow copy of obj

or String.new:

original_title = String.new(s.title)

new(str="") → new_str

Returns a new string object containing a copy of str.

Upvotes: 7

Paul Rubel
Paul Rubel

Reputation: 27222

Variables in ruby reference the objects they point to rather than copying them by default. So, if you change the underlying object, any changes will show up in any variables that contain a reference to that object.

If a, b, c and d all point to the same object, changes to any will "change" (be visible through) all of them.

  a  b  c
   \ | /
   Object
     |
     d

If you want to keep your original value you'll need to somehow create a new variable.

irb(main):001:0> a = "Foo"
=> "Foo"
irb(main):002:0> b = a
=> "Foo"
irb(main):003:0> a << " Bar"
=> "Foo Bar"
irb(main):004:0> b
=> "Foo Bar"
irb(main):005:0> a
=> "Foo Bar"
irb(main):006:0> a += " Baz"
=> "Foo Bar Baz"
irb(main):007:0> a
=> "Foo Bar Baz"
irb(main):008:0> b
=> "Foo Bar"

For your case @wlad's gsub (note that he didn't use gsub!) suggestion seems like a good one.

original_title = s.title.gsub(" (Wholesale)","")

Upvotes: 3

vvlad
vvlad

Reputation: 579

It is the same because you're accessing the same object.

irb(main):006:0> x = "aaaa"
=> "aaaa"
irb(main):007:0> y = x 
=> "aaaa"
irb(main):008:0> x.object_id 
=> 70358166435920
irb(main):009:0> y.object_id
=> 70358166435920
irb(main):010:0> 

What you could do instead is

original_title = s.title.gsub(" (Wholesale)","")

Upvotes: 10

Related Questions