I wrote the following code:
class Actions
def initialize
@people = []
@commands = {
"ADD" => ->(name){@people << name },
"REMOVE" => ->(n=0){ puts "Goodbye" },
"OTHER" => ->(n=0){puts "Do Nothing" }
}
end
def run_command(cmd,*param)
@commands[cmd].call param if @commands.key?(cmd)
end
def people
@people
end
end
act = Actions.new
act.run_command('ADD','joe')
act.run_command('ADD','jack')
puts act.people
This works, however, when the @commands
hash is a class variable, the code inside the hash doesn't know the @people
array.
How can I make the @commands
hash be a class variable and still be able to access the specific object instance variables?
You could use instance_exec
to supply the appropriate context for the lambdas when you call them, look for the comments to see the changes:
class Actions
# Move the lambdas to a class variable, a COMMANDS constant
# would work just as well and might be more appropriate.
@@commands = {
"ADD" => ->(name) { @people << name },
"REMOVE" => ->(n = 0) { puts "Goodbye" },
"OTHER" => ->(n = 0) { puts "Do Nothing" }
}
def initialize
@people = [ ]
end
def run_command(cmd, *param)
# Use instance_exec and blockify the lambdas with '&'
# to call them in the context of 'self'. Change the
# @@commands to COMMANDS if you prefer to use a constant
# for this stuff.
instance_exec(param, &@@commands[cmd]) if @@commands.key?(cmd)
end
def people
@people
end
end