Alex Antonov
Alex Antonov

Reputation: 15146

Ruby assign one value to two variables in one line

I'm in the process of building my own webserver and want to make a logger. After server get a message, I want both to log it and send the message to the parsers. I need to make some moditications to the message for logging (eg remove the password), but when I change second variable, first is changed too!

msg = log_msg = JSON.parse(something)

log_msg[:password] = '[FILTERED]'

raise msg.inspect # => {..., :password => '[FILTERED]'}

How can I avoid this behavior of my code?

UPDATED It seems more strange, because of irb:

2.2.1 :001 > a = b = 1
 => 1 
2.2.1 :002 > b = 2
 => 2 
2.2.1 :003 > b
 => 2 
2.2.1 :004 > a
 => 1

Upvotes: 0

Views: 960

Answers (2)

Yu Hao
Yu Hao

Reputation: 122383

After the assignment, msg and log_msg reference to the same object. If this is not what you expected, try this:

log_msg = JSON.parse(something)
msg = log_msg.dup

Note that the other example behave differently because Fixnum is special. From the manual:

Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object.

Upvotes: 2

twonegatives
twonegatives

Reputation: 3438

This question is tightly linked to the following duscussions:

  1. Object assignment in ruby
  2. Does ruby pass by reference or by value
  3. Ruby parameters by reference or by value

Please read them carefully to understand what's going on (this addressed your code snippet with assigning integer values aswell).

To assign by value you could clone or dup methods. Check the value of object_id to realize if you're working on the same object or not.

a = {}      # => {} 
b = a       # => {} 
b.object_id # => 114493940 
a.object_id # => 114493940 
b = a.clone # => {} 
b.object_id # => 115158164
a.object_id # => 114493940 

Upvotes: 1

Related Questions