Ruby Attributes VS Instance variables
Tags: ruby, oop, programming, certification
Published: 2024-03-04 02:02:52

I am finally going to **clarify** the confusion among developers about the use of **attributes and instance variables** in Ruby classes. In this article, I will show you the similarities and differences between these two concepts and provide **best practices for using them**.

##First things first SIMILARITIES
* Attributes and instance variables are used to store data **within a class**.
* They can both be accessed and modified **within the class**.

##Now the differences
* Attributes have a **wider scope** than instance variables. 
* Attributes can be accessed and modified **outside the class** using accessors, while instance variables are only accessible within the class.
* Attributes can be defined with **specific data types**, ensuring data integrity. Instance variables, on the other hand, can hold **any data type**.
* Attributes can be initialized **during declaration**, while instance variables **need** to be initialized **within the class**.
* Instance variables consume *more memory* than attributes since they are not bound to a specific data type.

##Best practices
**attr_accessor** is so versatile, that it lets us to store a value anywhere.
```Ruby
class AttributesInstances
  attr_accessor :my_attribute

  def initialize
    @my_attribute = "Hello" # instance variable used to store the value of the attribute
  end

  def show_me
    puts @my_attribute # instance variable used to access the value of the attribute
    puts self.my_attribute # attribute reader used to access the value of the attribute
  end
end

ai = AttributesInstances.new
ai.show_me
#=> Hello
#=> Hello
```
As you can see, it is possible to access the attribute value by the instance variable used to store it during the initialization.

```Ruby
class AttributesInstances
  attr_accessor :my_attribute

  def initialize
    self.my_attribute = "Hello" # attribute writer used to set the value of the attribute
  end

  def show_me
    puts @my_attribute # instance variable used to access the value of the attribute
    puts self.my_attribute # attribute reader used to access the value of the attribute
  end
end

ai = AttributesInstances.new
ai.show_me
#=> Hello
#=> Hello
```
In this case, the value can be stored with `self` which is the attribute writer method.

**attr_reader and attr_writer** It has their special treatment.
```Ruby
class AttributesInstances
  attr_reader :my_attribute_reader

  def initialize
    # self.my_attribute_reader = 'Hello' # RISES NoMethodError: undefined method `my_attribute_reader=' for #<AttributesInstances:0x00007f8f3b8b3e40>
    @my_attribute_reader = 'Hello' # instance variable used to set the value of the attribute
  end

  def show_me
    puts @my_attribute_reader # instance variable used to access the value of the attribute
    puts self.my_attribute_reader # attribute reader used to access the value of the attribute
  end
end

ai = AttributesInstances.new
ai.show_me
#=> Hello
#=> Hello
```
Here, the value can only be stored by an instance variable, when `self` is used, it raises the `undefined method` exception.

I hope this is useful for getting your code cleaner and better organized.

Any comments are fully welcomed.