ORGANIZING STRUCTURES IN RUBY
Published: 2023-10-30 01:02:48

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

```
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
```
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?
```
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](https://medium.com/@lucaspenzeymoog/uses-for-modules-in-ruby-mixins-and-namespaces-efab56575d84)

[ruby lang docs](https://www.ruby-lang.org/en/documentation/faq/8/#:~:text=What%20is%20the%20difference%20between%20a%20class%20and%20a%20module,instance%20state%20(instance%20variables).)