0

I need to be able to pass the name of a variable into an expression (in cucumber) and would like to be able to convert that string into a reference (i.e. not a copy) of the variable.

e.g.

Given /^I have set an initial value to @my_var$/ do
  @my_var = 10
end

# and now I want to change the value of that variable in a different step
Then /^I update "([^"]*)"$/ do |var_name_string|
  # I know I can get the value of @my_var by doing:
  eval "@my_var_copy = @#{var_name_string}"

  # But then once I update @my_var_copy I have to finish by updating the original
  eval "@#{var_name_string} = @my_var_copy"

  # How do instead I create a reference to the @my_var object?
end

Since Ruby is such a reflective language I'm sure what I'm trying to do is possible but I haven't yet cracked it.

Peter Nixey
  • 16,187
  • 14
  • 79
  • 133

3 Answers3

2
  class Reference
    def initialize(var_name, vars)
      @getter = eval "lambda { #{var_name} }", vars
      @setter = eval "lambda { |v| #{var_name} = v }", vars
    end
    def value
      @getter.call
    end
    def value=(new_value)
      @setter.call(new_value)
    end
  end

Got this from http://onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc. Good luck!

RubyFanatic
  • 2,241
  • 3
  • 22
  • 35
  • Very good - this does what I ned, thank you. It's still not 100% there in that I need to use ref_name.value but it's better than what I've got. – Peter Nixey Mar 08 '11 at 17:15
  • The link that I provided above has example usages of ref_name.value. It should probably have what you need. – RubyFanatic Mar 08 '11 at 18:37
1

A solution might be to wrap things into an array. Which can easily be passed around by reference.

irb(main):001:0> my_var = [10]
=> [10]
irb(main):002:0> my_var_copy = my_var
=> [10]
irb(main):003:0> my_var[0] = 55
=> 55
irb(main):004:0> my_var_copy
=> [55]

See here - http://www.rubyfleebie.com/understanding-fixnums/

And (slightly off topic, but gave me the initial idea for a solution) here - http://ruby.about.com/od/advancedruby/a/deepcopy.htm

bluekeys
  • 2,217
  • 1
  • 22
  • 30
  • I have actually been using a hash to date and referencing variables them by their string based key. It's not as close as I'd like to get but does the job – Peter Nixey Mar 08 '11 at 17:17
0

Could obj.instance_variable_get and obj.instance_variable_set help you?

Julian Maicher
  • 1,793
  • 14
  • 13
  • It's close but it feels like it's just a slightly cleaner way of doing an eval. As far as I can tell it still doesn't return a reference to the object itself – Peter Nixey Mar 06 '11 at 12:52
  • In an amazing coincidence though this was exactly what I needed to do some RSpec testing of a controller :) – Peter Nixey Mar 06 '11 at 13:22
  • No you're right. It won't return the reference but sets or gets the value of an instance variable. In my understanding of your cucumber stepts that's what you need. Anyway, at least it helped you in some way :-) – Julian Maicher Mar 06 '11 at 14:02