Basic
- Defining a class (cheat sheet)
First thing when starting writing OO programs, defining classes normally comes first. There can be many things inside the class, but there are things that can be considered class definition starters. The code below has the basic syntax for defining a class and has 4 blocks inside :
1) declaring a class variable @@all to store all the instances in the class.
2) an instance method to access the @@all variable.
3) attributes’ setter and getter methods. Try to put all the attributes in attr_reader at the beginning and put it into attr_accessor when necessary.
4) instance initialization method. If there are default values for some attributes, put them into the parameter area. By doing so, these attributes also become optional.
# the bolden text areas are the areas that need to be changed.class ClassName@@all = []def self.all
@@all
endattr_reader :attribute1, :attribute2, ..
attr_accessor :attribute_a, :attribute_b, ..def initialize attribute1, attribute2=default value, ...
@attribute1 = attribute1
@attribute2 = attribute2
attribute_a = attribute_a
.
.
@@all << self
endend
Side note: when there are limitations on the attributes’ input value, write instance methods to limit them.
2.Class variables(@@var_name) vs instance variable(@var_name) vs normal variable(var_name)
1)Class variables(@@var_name): defined in a class body that can be interacted with without an instance of such class. Class variables are shared among all instances of the class and its subclasses. Can be shared between methods. Static, meaning space for the variable gets allocated for the lifetime of the program, it also gets created when the codes begin to compile.
2)Instance variable(@var_name): defined in a class body but belongs to a specific instance. Its value is not shared between instances of a class or its subclasses. Let say that each instance has variables with the same name but refers to different values. Can be shared between methods.
3)normal variable(var_name): define in a class body, use to store temporary values because it can’t but access anywhere else but where it is defined. Can’t be shared between methods.
Let’s look at the code below for the difference

3.Class method(self.method_name) vs instance method(method_name)
always ask — what is this method used on? On a group(class) or on an individual (one instance). If it is used on a group, for example, get all the instances, count the total number of instances, it is a class method. If it is used on one individual, for example, what’s the attribute(name, age, etc. ) of the instance, it’s an instance method.
ALWAYS REMEMBER TO PUT SELF. IN FRONT OF THE METHOD NAME WHEN DECLARING A CLASS METHOD!!!!
Relationships
when dealing with relationships, it is always a good idea to draw the connection out.
- One-to-many
One-to-many relationship is the basic relationship form between 2 classes, also the foundation of many-to-many relationship.

A mother (an instance of Mother class) has many children, so she will be able to look into the bunch of children(the Child class) and SELECT all the children that are hers. The retrieve method would be something like:
class Motherdef children
Child.all.select{|child| child.mother == self}
endend
A child only has one mother, so the MOTHER INSTANCE is one of his ATTRIBUTES. Also, all the info about this child should be stored in the Child class. The Child class should look something like this:
class Child@@all = []def self.all
@@all
endattr_reader :mother, :attribute2, ..def initialize mother, attribute2=default value, ...
@mother = mother
@attribute2 = attribute2
attribute_a = attribute_a
.
.
@@all << self
endend
2. Many-to-many
One way model:

In many to many relationships, the principles of has-many and belong to relationships remain the same (as the mother/child example). For example, an aquarium shall be able to look into all the exhibitions and SELECT all its exhibitions, one of the exhibition’s ATTRIBUTE shall be the AQUARIUM INSTANCE.
What is special about the many-to-many relationship is the has-many-thru relationship. When jumping classes, meaning when an aquarium wants to look at its fishes, he will always have to look at its exhibitions list first, and then find out what fishes it has. The code in the Aquarium class would look something like this when it wants to know all the fishes it has
class Aquariumdef fishes
Exhibit.all.select{|exhibit| exhibit.aquarium == self}.map{|exhibit| exhibit.fish}
endend
Since Exhibit class is both a child (of Aquarium class) and a mother (of Fish class), so, it shall have an attribute of an aquarium instance, and a method to get its fishes.
class Exhibit @@all = []def self.all
@@all
endattr_reader :aquarium, :attribute2, ..def initialize aquarium, attribute2=default value, ...
@aquarium = aquarium
@attribute2 = attribute2
attribute_a = attribute_a
.
.
@@all << self
enddef fish
Fish.all.select{|fish| fish.exhibit == self}
endend
Join model:

The Join model is the most complicated one, but nothing new here. It is based on the 3 kinds of relationships. Figure out the mother/child relationship, between 2 classes and who is the middle sharing class, the relationship is all set!
Happy coding!