Peter
Peter

Reputation: 69

Accessing a variable's name from an object

Given an object:

object_name = "hello"

is there any way to get the variable's name "object_name"? I need to create a string with the variable's name and the value in it, e.g.

"The name of the variable is 'object_name' and its value is 'hello'"

I tried:

object_name.object_id
# => 20084556

Upvotes: 1

Views: 229

Answers (4)

Peter
Peter

Reputation: 69

Took me a while, but I solved this eventually. Thanks to all for the above answers. Here are the feature file, step definitions and methods I used to work it out.

Feature: try and work out a simple version of the f2d pages that could be used for all

  Scenario Outline: first go
    Given I set up an object for these things
      | page_1   | page_2   |
      | <page_1> | <page_2> |
    Then I create objects and output two things for one

    Examples:
      | page_1    | page_2      |
      | elephants | scary pants |

Step Definitions:

Given(/^I set up an object for these things$/) do |table|
  set_up_a_hash_from_a_table(table)
end

Then(/^I create objects and output two things for one$/) do
  do_something_with_a_hash
end

Methods:

def set_up_a_hash_from_a_table(table)
  @objects = Hash.new
  @summary = Array.new
  data = table.hashes

  data.each do |field_data|
    @objects['page_1'] = field_data['page_1']
    @objects['page_2'] = field_data['page_2']
  end
end

def do_something_with_a_hash

  show_me_page_1

  show_me_page_2

  puts "Summary is #{@summary}"

end

def show_me_page_1
  do_stuff_for_a_page('page_1')
end

def show_me_page_2
  do_stuff_for_a_page('page_2')
 end

def do_stuff_for_a_page(my_object)
  puts "key is #{my_object} and value is #{@objects[my_object]}"
  @summary.push("#{my_object} - #{@objects[my_object]}")
  end

Result:

#=> key is page_1 and value is elephants

#=> key is page_2 and value is scary pants

#=> Summary is ["page_1 - elephants", "page_2 - scary pants"]

Upvotes: 0

Michael Kohl
Michael Kohl

Reputation: 66837

The only way I can come up with is something along these lines:

binding.local_variables.each do |var|
  puts "The name of the variable is '#{var}' and its value is '#{eval(var.to_s)}'"
  # or
  # puts "The name of the variable is '#{var}' and its value is '#{binding.local_variable_get(var)}'"
end
# The name of the variable is 'object_name' and its value is 'hello'

Of course this will output all local variables that are currently in scope and, well, eval.

Upvotes: 1

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

Just out of curiosity:

object_name = "hello"
var_name = File.readlines(__FILE__)[__LINE__ - 2][/\w+(?=\s*=)/]
puts "Variable named '#{var_name}' has value '#{eval(var_name)}'"

> ruby /tmp/d.rb
#⇒ Variable named 'object_name' has value 'hello'

Upvotes: 1

ndnenkov
ndnenkov

Reputation: 36101

def find_var(in_binding, object_id)
  name = in_binding.local_variables.find do |name|
    in_binding.local_variable_get(name).object_id == object_id
  end

  [name, in_binding.local_variable_get(name)]
end

the_answer = 42
find_var binding, the_answer.object_id # => [:the_answer, 42]

foo = 'bar'
baz = [foo]
find_var binding, baz.first.object_id # => [:foo, "bar"]

Obvious downfall - two variables pointing to the same object. Aka

a = b = 42

Upvotes: 3

Related Questions