DEV Community

'Seun Somefun
'Seun Somefun

Posted on

ORGANIZING STRUCTURES IN RUBY

In ruby, there are two fundamental concepts for organizing methods: classes and modules.

A class is a blueprint or template for building objects. Classes have properties or attributes that are unique to the class while methods determine actions that can be carried out on the class, especially via manipulating the properties.

For example, we can decide to model a human class. Humans normally have legs, hands, a name, and other properties and they can say their names. Let's quickly wire that up

class Human
    def initialize(no_of_hands, no_of_legs, name)
        @no_of_hands = no_of_hands
        @no_of_legs = no_of_legs
        @name = name
    end

    def name
        "Hi there, my name is #{@name}"
    end

    def name=(new_name)
        @name = new_name
    end
end

lm = Human.new(2, 4, 'lege miami')
puts lm.name  # Hi there, my name is lege miami
lm.name = 'bugs bunny'   
puts lm.name   # Hi there, my name is bugs bunny

Enter fullscreen mode Exit fullscreen mode

From the above code block, we defined a class or blueprint as we mentioned earlier called Human with three instance properties and two instance methods, one being a getter and the other being a setter. The class is further instantiated with the initialized properties and then an action is carried out on the next line which prints the instance name as "lege miami". We further set the instance name to a new name via the setter method and when we log it, we see that the new name changes to "bugs bunny"

Imagine that we had about six instance properties, we would have to create a getter and setter method(if we intend to change them) for each and that will be twelve methods altogether. Thankfully Ruby has a shortcut called attr_accessor which essentially helps you have a getter and setter in one piece. See the refactored code below:

class Human
    attr_accessor :no_of_hands, :no_of_legs, :name
    def initialize(no_of_hands, no_of_legs, name)
        @no_of_hands = no_of_hands
        @no_of_legs = no_of_legs
        @name = "Hi there, my name is #{name}"
    end
end

lm = Human.new(2, 4, 'lege miami')
puts lm.name  # Hi there, my name is lege miami
lm.name = 'bugs bunny'   
puts "Hi there, my name #{lm.name}"   # Hi there, my name is bugs bunny
Enter fullscreen mode Exit fullscreen mode

Now we don't have to define a specific getter and setter method as attr_accessor has taken care of that. There are also attr_reader which creates only the reader and attr_writer which creates only the writer. Methods are public by default but they can also be made private or protected depending on the use case.

Modules in Ruby provide a way to organize code that allows for more flexibility than through a standard class. Including a module in a class allows that class use of the code within the module. The effect of this is similar to a child-class inheriting code from a parent-class.

Modules serve two purposes. First, they act as a namespace, letting you define methods whose names won’t clash with those defined elsewhere. Second, they allow you to share functionality among classes. If a class mixes in a module, that module’s methods become available as if they’d been defined in the class. Multiple classes can mix in the same module, sharing the module’s functionality without using inheritance. You can also mix multiple modules into a single class.

Let's look at how to use a module:

module  RandomHelper
    def capitalize_words(string)
        string.split(' ').map {|word| word.capitalize}.join(' ')
    end
end


class Questioner
include RandomHelper
    def capitalize(string)
        RandomHelper::capitalize_words(string)
    end
end

question = Questioner.new
puts question.capitalize_words('is software engineering rewarding?')  # Is Software Engineering Rewarding?
Enter fullscreen mode Exit fullscreen mode

Here we have defined a module RandomHelper because we are lazy with naming(you should not be in real life) and put in it a method capitalize_words which turns the first letter of every word in the sentence passed into it into a capital letter and then we include it in a class so it can be used. This class Questioner(because naming is hard) is then instantiated before the instance calls the method in the module.

These organizing structures are largely used in Ruby on Rails with different flavors.

For further reading and possibilities;

medium article

ruby lang docs

Top comments (0)