Reputation: 305
So I am trying to create dynamic variables, and then use them again later without having to type out the full name. The test code I made is as follows
players = [1, 2, 3, 4]
players.each |player|
instance_variable_set("@player_#{player}_hand", "foo")
instance_variable_set("@player_#{player}_value", "bar")
}
puts @player_1_hand # => foo
puts @player_3_value # => bar
players.each { |player|
puts "@player_#{player}_hand"
}
# => @player_1_hand
# => @player_2_hand
# => @player_3_hand
# => @player_4_hand
I want to call and/or update these variables dynamically but I don't know how to do that after I initialize them. The documentation I have found has been more confusing than helpful. Can someone explain how to use these correctly?
Upvotes: 1
Views: 113
Reputation: 432
When a you want an attr_accessor for every property, a Struct instead of a class will make them for you automatically.
Player = Struct.new(:number, :hand, :value)
players = Array.new
(1..4).each do |i|
player = Player.new(i)
player.hand = 'something'
player.value = 'blah'
players.push player
end
players.each do |player|
puts "Player #{player.number} has hand #{player.hand} with value #{player.value}"
end
Output:
Player 1 has hand something with value blah
Player 2 has hand something with value blah
Player 3 has hand something with value blah
Player 4 has hand something with value blah
Upvotes: 1
Reputation: 10536
I want to warn you that the answer I'm going to give you will work for what you are trying to accomplish, but the way you're going about it is akin to using a wrench when you need a hammer. Sure, the wrench might work, but I'd fire any plumber that didn't use the right tools.
players.each { |p| puts instance_variable_get("@player_#{p}_hand") }
More about instance_variable_get
can be found at apidock.
In general though, you should stay away from instance variables unless you are creating instances of a class. But for a script like this, stick with normal variables and stay away from instance variables.
Upvotes: 2
Reputation: 447
I recommend that you follow OOP concepts creating a Player object instead of many instance variables, one for each attribute. So, instead of
@player_1_hand
@player_3_value
Try with a Player
class
class Player
attr_accessor :number, :hand, :value
def initialize(number)
@number = number
end
end
And then
p1 = Player.new(1)
p2 = Player.new(2)
p3 = Player.new(3)
p4 = Player.new(4)
[p1,p2,p3,p4].each do |player|
player.hand = ...
player.value = ...
end
p1.hand #=> ...
p1.value #=> ...
Upvotes: 8
Reputation: 16224
players = [1, 2, 3, 4]
players.each { |player|
instance_variable_set("@player_#{player}_hand", "foo")
instance_variable_set("@player_#{player}_value", "bar")
}
To call your variables use eval
players.each { |player|
puts instance_variable_get("@player_#{player}_hand")
puts instance_variable_get("@player_#{player}_value")
}
To update your variables use instance_variable_set again
players.each { |player|
instance_variable_set("@player_#{player}_hand", instance_variable_get("@player_#{player}_hand") + (player + 5).to_s)
puts instance_variable_get("@player_#{player}_hand")
}
all that prints:
foo
bar
foo
bar
foo
bar
foo
bar
foo6
foo7
foo8
foo9
Upvotes: 2