Now we are ready to create our very own Address class. Let’s start simple. Let’s start with an address that only contains the “street” field.

This is how you define a class:

class Address
    def initialize(street)  
        @street = street 
    end
end

Let’s go through this:

Let’s use this class to create an address object.

address = Address.new("23 St George St.")  

That’s it. address is now an object of the class Address.

Reading the data in an object

Suppose that we want to read the data in the address object. To do this, we need to write a method that returns this data:

class Address
  def initialize(street)   
    @street = street 
  end

  # Just return @street
  def street
    @street
  end
end

Now the method Address#street lets you read the street of the address. In irb:

>> address.street 
=> "23 St George St."

A property of an object, which is visible outside, is called an attribute. In this case, street is is an attribute. In particular, it is a readable attribute. Because this kind of attribute is very common, Ruby offers you a shortcut through the attr_reader keyword:

class Address
  attr_reader :self
  def initialize(street)   
    @street = street 
  end
end

Changing the data in an object

We can also define a method to change the data in an object.

class Address
    attr_reader :street
    def initialize(street)  
        @street = street 
    end
    def street=(street)
        @street = street
    end
end

Ruby is pretty smart in its use of the street= method:

address.street = "45 Main St."

Notice that you can put spaces betten street and =. Now that we can change the address data, we can simplify the initialize method, and have it simply default the street to the empty string "".

class Address
  attr_reader :street
  def initialize
    @street = ""
  end
  def street=(street)
    @street = street  
  end
end

address = Address.new
address.street = "23 St George St."  

This might not seem like much of a simplification, but when we add the city, state and zip fields, and more methods this will make the class definition a bit simpler.

Now, street is also a writable attribute. As before, you can declare it as such with attr_writer:

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end

Accessing data

Very often, you have attributes that are both readable and writable attributes. Ruby lets you lump these together with attr_accessor. I guess these would be called “accessible attributes”, but I have never seen them be called that.

class Address
    attr_accessor :street  
    def initialize
        @street = ""
    end
end

With this knowledge, it is now easy to define the entire addressbook structure. As it turns out, attr_accessor and friends all accept multiple arguments.

class Address
    attr_accessor :street, :city, :state, :zip  
    def initialize
        @street = @city = @state = @zip = ""
    end
end

Exercises

Holiday Countdown