2

I have the following loop:

(1..1000).each do |i|
  user1 = User.create(:name => "Bob#{i}")
  ...
end

How can I let the variable name user1 vary dynamically using i to get:

user1 == Bob1
user2 == Bob2
user3 == Bob3
sawa
  • 165,429
  • 45
  • 277
  • 381
AnnaSm
  • 2,190
  • 6
  • 22
  • 32
  • Why not use an array to store those users? `users = (1..1000).map{|i| User.create(...)}` – Aetherus Jun 27 '17 at 03:08
  • I need to do more within the loop – AnnaSm Jun 27 '17 at 03:09
  • 1
    A local variable declared inside a block is not accessible from outside of the block. So, you can just name your variable `user`. – Aetherus Jun 27 '17 at 03:10
  • what would be point if your local vars inside blocks are not gonna make their way out of the block. Their scope is limited. – Shiva Jun 27 '17 at 03:16
  • @AnnaSm _"I need to do more within the loop"_ – do you have to do more with the user of the loop's current iteration or with multiple users at once? – Stefan Jun 27 '17 at 08:40

1 Answers1

2

You can't, but you can use a Hash to get a similar result:

(1..1000).each_with_object({}) do |i, users|
  users["user#{i}"] = User.create(:name => "Bob#{i}")
end

If you need to access the hash outside the block, just assign it to a variable:

users = (1..1000).each_with_object({}) { |i, users| users["user#{i}"] = User.create(:name => "Bob#{i}") }

And access a specific user (e.g. user1) like this:

users["user1"]

Or you could use only i as a key:

users = (1..1000).each_with_object({}) { |i, users| users[i] = User.create(:name => "Bob#{i}") }

And access a specific user (e.g. user1) like this:

users[1]
Gerry
  • 10,337
  • 3
  • 31
  • 40
  • "Prior to Ruby 2.0"? You mean "Since Ruby 2.1"? – sawa Jun 27 '17 at 04:37
  • "Prior to Ruby 2.0, you could actually create local vars dynamically using `eval` or `binding.local_variable_set` methods." – This is wrong. a) You cannot create local variables using `Binding#local_variable_set`. You can only set existing ones. b) `Binding#local_variable_set` was added in Ruby 2.1, it is not available prior to Ruby 2.0. c) `eval` *did* leak scope in the past, but that was in Ruby 1.8 and earlier, which *technically* is "prior to Ruby 2.0", but that statement also includes Ruby 1.9, for which it is not true. – Jörg W Mittag Jun 27 '17 at 09:12
  • @JörgWMittag Thank you for the clarification, i've updated answer (removed that statement) to avoid confusion. – Gerry Jun 27 '17 at 09:57