1. Ruby accessor methods
Ruby does not allow instance variables to be accessed outside of methods for that object.
class Person def initialize(name) @name = name @age = 10 end end p = Person.new('steve') p.name # => undefined method `name=' for #<Person ..> This design ensures OOP encapsulation - an object’s data is protected from the outside world.
In some languages like Java, to access private instance variables, you must define getter/setter methods for each attribute. But in Ruby, you can generate getter/setter methods by using one of the methods in the Module#attr_* family.
class Person attr_reader :name, :age # getter attr_writer :name, :age # setter # attr_accessor :name, :age # getter + setter # other code .... end p = Person.new('steve') p.name # => steve p.age = 20 p.age # => 20 It just takes one or two lines for all of the attributes. These methods are called Class Macros which are class methods only used when in a class definition.
2. DIY accessor methods
There are advanced ways to access instance variables, like instance_variable_get, instance_eval.
For example:
p = Person.new('steve') p.instance_variable_get(:@name) p.instance_eval { @name } Using some metaprogramming techniques, we can build attribute accessor methods by myself.
module GetterSetter def attr_getter(*attributes) attributes.each do |attribute| define_method attribute do instance_variable_get("@#{attribute}") end end end def attr_setter(*attributes) attributes.each do |attribute| define_method "#{attribute}=" do |value| instance_variable_set("@#{attribute}", value) end end end def attr_getter_and_setter(*attributes) attr_getter(*attributes) attr_setter(*attributes) end end For simplicity, I define getter/setter in separated module and include in Person class.
class Person extend GetterSetter def initialize(name) @name = name @age = 10 end attr_getter :name, :age attr_setter :name, :age # or # attr_getter_and_setter :name, :age end p = Person.new('Luke') p.name = 'anakin' p.name # => anakin Summary
Class macros are one of Ruby's magic methods that help developers get rid of a lot of tedious, boilerplate methods. In rails, class macros are used a lot, for associations ( has_many, belongs_to ), validation, ...
You can learn more about Ruby class macros or other metaprogramming techniques in the Metaprogramming Ruby book ( https://pragprog.com/titles/ppmetr2/metaprogramming-ruby-2/)
Top comments (0)