Passing a variable to lock in Ruby implicitly
I would like to rewrite this snippet:
Chips.fix_game(324565) do |game_id|
player1.chips.gain(game_id, 200) # chips qty
player2.chips.lose(game_id, 200)
end
thus:
Chips.fix_game(324565) do
player1.chips.gain(200)
player2.chips.lose(200)
end
passing game_id
to player1.chips
the API entry point.
The second snippet is more concise and there is no room for change game_id
inside the block.
How would you implicitly pass a value game_id
from a method Chips.fix_game
to an object player1.chips
?
source to share
Chips
can provide current_game_id
, which is installed with fix_game
, for example:
class Chips
@@current_game_id = nil
def self.current_game_id
@@current_game_id
end
def self.fix_game(game_id)
previous_game_id = current_game_id
@@current_game_id = game_id
yield
ensure
@@current_game_id = previous_game_id
end
end
class Player
def gain(amount)
puts "gaining #{amount} chips in game #{Chips.current_game_id}"
end
end
player = Player.new
Chips.fix_game(1) do
player.gain(100)
end
#=> "gaining 100 chips in game 1"
Chips.fix_game(2) do
player.gain(200)
end
#=> "gaining 200 chips in game 2"
Restoring the previous game ID after yield
allows you to block blocks:
Chips.current_game_id #=> nil
Chips.fix_game(1) do
Chips.current_game_id #=> 1
Chips.fix_game(2) do
Chips.current_game_id #=> 2
end
Chips.current_game_id #=> 1
end
Chips.current_game_id #=> nil
While this looks convenient, global state can lead to difficult tasks to debug. Be careful.
source to share