Ruby: Self
Tags: ruby, oop, firstyearincode, beginners
Published: 2020-08-25 15:33:52

I am a fellow SE student at Flatiron School, and have decided to blog my coding journey. I am a novice programmer with an intense level of curiosity to learn, and always welcome any constructive criticism. Let's say - I am Baby Yoda in training, and incessantly developing my Jedi mindset.

![baby_yoda](https://pmcvariety.files.wordpress.com/2019/11/baby-yoda.jpg?w=681&h=383&crop=1)

The past three weeks, I have immersed myself in Ruby procedural programming concepts from variable and methods to data structures. We proceeded with Object-Oriented Programming (OOP). The whole week, I was struggling to grasp the use of **@**, **@@** and **self**. After countless hours of irb-ing, I am more comfortable now constructing Classes and implementing **@**, **@@** and **self** in Object Relationships. 

Okay, we understand Class is essentially a blueprint or factory. It births instances with shared attributes and behaviors. I will be using _**plant**_ to iterate my thoughts as an extension of my side interest in nurseries.

```
class Plant 
   def name=(name)
      @name = name
   end

   def name
      @name
   end
end 

cactus = Plant.new("Cactus")
cactus.name = "Cactus"
```
This is my preliminary Class scope with basic reader and getter methods. "Cactus" would be an instance of Plant class. 


**What is @ and @@?**
@ is an instance variable, and @@ is a class variable. They are capable of traversing through instance and class methods. I call this an upgraded version of local variable. Let's refine our Plant class.

```
class Plant 
   @@all = []

   def name=(name)
      @name = name
   end

   def name
      @name
   end

   def save 
      @@all << self 
   end 

   def self.all 
      @@all 
   end 

   def self.chatty_plant
      self.all.each do |plant|
         puts "I am #{@name}. Water me please!"
      end 
   end  
end 
```

In my earlier approach to Ruby classes, I would simply refer to @instance_variable and @@class_variable on instance and class methods. They worked, and I passed the test. As I progressed through more complex schemes, this mental modeling approach became less intuitive. What if we rename _@@class_variable_ to _@@something_else_? We would have to rename every single _@@class_variable_. What if I misspelled _@instance_variable_ as _@instance_varyable_? Would Ruby help us to catch this mistake? 


**The rise of self**
I believe this is when we should utilize **self**, and construct our Ruby Classes more intuitively. Referring to @ and @@ is a literal approach, and utilizing **self** allows our object to operate inherently. **Self** refers to main, or itself, in which program functions. In instance method, self refers to the instance itself, and in class method, self refers to the class itself. Let's take a look at our first alternative approach below:

```
   def save 
      @@all << self 
   end 
```
```
   def save 
      self.class.all << self 
   end 
```

We can refactor @@all to **self.class.all**. 
**@@all** == @@all
**Plant.class** == @@all
**self.class.all** == @@all
  
Why are we using **self.class.all** in lieu of @@all?
It is prudent to reify and refactor our instance or class methods as our code gradually becomes more complex. By using **self.class.all**, we avoid possible error syntax when renaming any class variables.

```
   def self.chatty_plant
      self.all.each do |plant|
         puts "I am #{@name}. Water me please!"
      end 
   end  
```
```
   def self.chatty_plant
      all.each do |plant|
         puts "I am #{name}. Water me please!"
      end 
   end  
```

Do we need **self** in _self.all.each do_?
self.chatty_plant is a class method, and self.all is also a class method. We can omit **self** in _self.all.each do_. Ruby understands **self** as an implicit receiver in this class method.

**#{@name}** vs. **#{name}**
If we erroneously typed #{@naame}, Ruby will look for an instance variable @naame which is non-existent. 
```
#=> I am  . Water me please!
```
A better approach in Ruby is to call out an instance method. If we have a typo such as #{naame} instead of #{name}, Ruby will help us to navigate the error. 
```
#=> NameError (undefined local variable or method 'naame'..)
```

This **self** mental modeling allows better design approach as our code gets more complex attributes and behaviors in Ruby implementation. 


```
class Plant 
   @@all = []

   def name=(name)
      @name = name
   end

   def name
      @name
   end

   def save 
      self.class.all << self 
   end 

   def self.all 
      @@all 
   end 

   def self.chatty_plant
      all.each do |plant|
         puts "I am #{name}. Water me please!"
      end 
   end  
end 
``` 

Keep Calm and Code On.

***
<center>[**fentybit**](https://fentybit.me/) | [GitHub](https://github.com/fentybit) | [Twitter](https://twitter.com/fentybit) | [LinkedIn](https://www.linkedin.com/in/fentybit/)</center>