What is the difference between the "__send__" and "instance_variable_get / instance_variable_set" methods?
Everything is indicated in the question. Both of these methods can access instance variables (read / write) using their codename:
__send__
instance_variable_set
instance_variable_get
Can anyone explain this with examples?
Metaprogramming sometimes melts out of our brains when we examine it in abstraction.
=== EDIT ===
Good. I am making a summary of the answers as an example for later reference if my brain melts again.
Class declaration :
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def full_name
@first_name + ' ' + @last_name
end
end
Initialization :
actor = Person.new('Donald', "Duck")
=> #<Person:0xa245554 @first_name="Donald", @last_name="Duck">
using send (read):
actor.send('first_name')
=> "Donald"
actor.send(:first_name)
=> "Donald"
actor.send("last_name")
=> "Duck"
actor.send(:last_name)
=> "Duck"
actor.send('full_name')
=> "Donald Duck"
actor.send(:full_name)
=> "Donald Duck"
using instance_variable_get (read)
actor.instance_variable_get('@first_name')
=> "Donald"
actor.instance_variable_get(:@first_name)
=> "Donald"
actor.instance_variable_get('@last_name')
=> "Duck"
actor.instance_variable_get(:@last_name)
=> "Duck"
using send (write):
actor.send('first_name=', 'Daisy')
actor.send('full_name')
=> "Daisy Duck"
actor.send(:first_name=, "Fifi")
actor.send("full_name")
=> "Fifi Duck"
using instance_variable_set (write)
actor.instance_variable_set('@first_name', 'Pluto')
actor.send("full_name")
=> "Pluto Duck"
actor.instance_variable_set(:@last_name, 'Dog')
actor.send(:full_name)
=> "Pluto Dog"
INCORRECT use of instance_variable_get (read)
actor.instance_variable_get('full_name')
#NameError: `full_name' is not allowed as an instance variable name
actor.instance_variable_get('last_name')
#NameError: `last_name' is not allowed as an instance variable name
I was confused with Rails ActiveRecord and its associations.
Thanks for answers!
source to share
__send__
methods call a method that is defined in your class, if the method is not defined then you cannot use the method send
, but methods instance_variable_get
and set
change the value of the instance variable unnecessarily for any encapsulation methods (like getters or setters).
__send__
used when you want to call a method identified by a symbol and pass any argument as needed.
eg.
class Test
def sayHello(*args)
"Hello " + args.join(' ')
end
end
k = Test.new
k.send :sayHello, "readers" #=> "Hello readers"
instance_variable_get
Returns the value of this instance variable, or nil if no instance variable is set. Use this method without the need for encapsulation
eg
class Test
def initialize(p1)
@a = p1
end
end
test = Test.new('animal')
test.instance_variable_get(:@a) #=> "animal"
instance_variable_set
used to set a value for an instance variable without the need for encapsulation techniques. eg
class Test
def initialize(p1)
@a = p1
end
end
test = Test.new('animal')
test.instance_variable_set(:@a, 'animal')
source to share