2

I have a Ruby object User, which has a :first_name member variable. I would like to be able to access that variable with a string.

So if I have a user called u:

u.'first_name' should be equivalent to u.first_name

How could I use reflection to get u.first_name through the string, which is passed in as a variable?

nao
  • 1,128
  • 1
  • 14
  • 37
  • 1
    Your question is unclear. There is no such thing as a "member variable" in Ruby. There are only global variables (also thread-local global variables and method-local global variables), constants, class variables, instance variables, local variables, and the pseudo-variables `self`, `nil`, `true`, and `false`. `u.first_name` is a message send, it has nothing to do with variables. – Jörg W Mittag Dec 07 '17 at 14:45

1 Answers1

15

I think what you mean with "member variable", is that you have a model that has an attribute called first_name. If so, then you can access that attribute as you'd do in a "plain" ("plain" because the question is focused to Rails) Ruby class:

class Foo
  attr_accessor :name
  def initialize(name)
    @name = name
  end
end

foo = Foo.new('bar')
p foo.instance_variables             # [:@name]
p foo.instance_variable_get('@name') # "bar"

The most idiomatic way to get dynamically an instance variable is using instance_variable_get, but you can also use send, or better using __send__, or even better in your case using public_send:

foo = Foo.new('bar')
p foo.instance_variables             # [:@name]
p foo.instance_variable_get('@name') # "bar"
p foo.send('name')                   # "bar"
p foo.public_send('name')            # "bar"

The way Rails handles your models and attributes is almost the same (NOTE: opened to edition). By instantiating one of your models, you can get the attribute you need:

user = User.first
user.email                # email@mail.com
user.public_send('email') # email@mail.com
Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59