0

How would I assign multiple instance variables the same value in the ruby initialize method? Looking to refactor the below:

def initialize
 @weekly_stats = Hash.new {|h, k| h[k]={}}
 @report_times = Hash.new {|h, k| h[k]={}}
 @email_stats = Hash.new {|h, k| h[k]={}}
end

3 Answers 3

3

Not sure what doing this in a one-liner buys you but you could do something like this:

%w{weekly_stats report_times email_stats}.each { |v| instance_variable_set("@#{v}", Hash.new {|h, k| h[k]={}} }

Or break it into two non-duplicating lines like:

vars = %w{weekly_stats report_times email_stats}
vars.each { |v| instance_variable_set("@#{v}", Hash.new {|h, k| h[k]={}} }

Or combining it with jvnill's answer:

value = Hash.new {|h, k| h[k]={}}
vars = %w{weekly_stats report_times email_stats}
vars.each { |v| instance_variable_set("@#{v}", value.dup }
Sign up to request clarification or add additional context in comments.

2 Comments

Thank You, this is helpful. Ditto my question below: Would you say keeping it status quo is optimal for readability or would it be better to use the above format?
Status quo works for me, though to reduce duplication maybe you could wrap up the Hash.new call into a private method
0

you can't do this in a single line because you're assigning a hash. Using Vinay's answer

>> a = b = c = { a: 'b', c: 'd' }
>> a # {:a=>"b", :c=>"d"}
>> a[:a] = 2 # 2
>> b # {:a=>2, :c=>"d"}

In the example above, b changed when you changed a. I'm not sure if there's a way to write this in a single line but try the following code instead

@weekly_stats = Hash.new {|h, k| h[k]={}}
@report_times = @weekly_stats.dup
@email_stats = @weekly_stats.dup

3 Comments

hmmm ok thank you. Would you say keeping it status quo is optimal for readability or would it be better to use the a=b=c format?
that depends. why do you need 3 variables with the same value?
those are the starting values, and then I am assigning different key/value data to each hash and passing it to another class
-1

Try this,

@weekly_stats = @report_times = @email_stats = Hash.new {|h, k| h[k]={}}

This works, but you should know that it's only safe for your situation if you're using the variables for numbers, which are immutable in Ruby. If you tried the same thing with a string, for example, you could end up with some behavior you didn't expect:

ruby-1.9.2-p180 :001 > foo = bar = "string"
 => "string" 
ruby-1.9.2-p180 :002 > foo.upcase!
 => "STRING" 
ruby-1.9.2-p180 :003 > bar
 => "STRING"

1 Comment

The hash will be shared, resulting in similar issues as your example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.