A Beginner’s Guide to Ruby Getters and Setters

In Ruby, getters and setters are typically defined by using the class method `attr_accessor`. Normally you see this at the top of the class and it sort of defines what properties that instances of the class will have. I feel like this method causes some confusion for Ruby beginners and it is something I had trouble with myself when I was first starting out. So let’s take a look:

class Foo  attr_accessor :bar, :bazend
foo => #<Foo:0x007fada99c2d00>> = 'jelly'=> "jelly"> "jelly"foo.baz=> nilfoo.baz = 'time'=> "time"foo.baz=> "time"

The first thing to note is that attr_accessor is different than Rails’ attr_accessible. attr_accessor is a RUBY method, it has nothing to do with Rails.

Anyway, attr_accessor automatically sets up getters and setters for those instance variables. That’s it. So in the above example, Foo will gain these methods:

def bar  @barenddef bar=(value)  @bar = valueenddef baz  @bazenddef baz=(value)  @baz = valueend

So this is somewhat similar to Objective-C’s synthesize method. Instance variables are private to the class so you expose them with these automatically generated getters and setters. Also note that since it’s Ruby, you are not restricted to the true definition of “private” and you can still retrieve instance variables with instance_variable_get("@bar") and instance_variable_set("@bar", value) if you have to do some hacks. It has some interesting documentation.


Gripe about getters

Reminder that Ruby getters DO NOT CONTAIN “get_”. There is not a single “get_” in the entire Rails repository. It is not Ruby-like so don’t try to bring that Java junk in here.

If you only need to generate the getters or setters there are also two other methods. attr_reader will define only the getter methods. attr_writer will defined only the setter methods. So all attr_accessor really does is combined those two methods into one call.


Rails and ActiveRecord

ActiveRecord defines getters and setters for you as methods. When you call you are calling the name method on current_user. There are not properties in Ruby like you might see on other languages. There are only getter methods that provide access to the instance variables inside of them.

So how is name defined? Luckily in Ruby you can do whatever you want, so ActiveRecord will read your database schema and generate methods on the fly when your Rails application starts. You can do this in a number of ways if you ever need to on your own, for example:

# Re-opening the User class and sticking the method into itclass User  def name; "Whatever"; endend# Using class_eval to add arbitrary blocks of code to the classUser.class_eval do  def name; "Whatever"; endend# Using define_methodclass User  define_method(:name) do    "Whatever"  endend

ActiveRecord uses module_eval (same as class_eval) to add the getters to your model. This is done in rails/activerecord/lib/active_record/attribute_methods/read.rb (in ActiveRecord 4.1). Read is one of many modules included into your model.

Overriding ActiveRecord getters is sometimes very useful. If you do need to override something in your model then you will definitely have to call super because ActiveRecord does so much shit behind the scenes that it’s useful to gain all of that for free. One nice use is when you want to use a Null Object when an attribute is nil:

def address  super || NullAddress.newend

Maybe you need to override a setter so you can parse a string date into a DateTime so ActiveRecord can read it and store it in a datetime column:

def started_at=(date) super DateTime.parse(date) # or the Chronic gemend


Logan Serman
Logan Serman