Ruby Self & Attr, as a Python Dev
Tags: ruby, codenewbie, python
Published: 2021-01-06 18:34:10

*This is a continuation of Picking up Ruby Fast, as a Python Dev. Again, expect examples with pets and minimal math*

---

## What is `self`

`self` is a method called on the class itself. It can be done in a couple of different ways. The first is similar to Python. The second with the `<<` is new to me.

In these examples, I'm just gonna add 1 to a count of how many dog or cat instances we've created.

### `self.`

words

```ruby
class Dog
    @@num_dogs = 0

    def initialize
        @@num_dogs += 1
    end

    def self.num_monkeys
        @@num_dogs
    end
end

# to get the num of dogs
self.num_dogs
```

### `class << self`

In this example, the `class << self` is saying that everything before the `end` is a class method and is not for the instances.

```ruby
class Cat
    @@num_cats = 0

    def initialize
        @@num_cats += 1
    end

    class << self
        def num_cats
            @@num_cats
        end
    end
end

# to get the num of cats
Cat.num_cats
```

## `attr`

We can use the following to easily read, write, and grab attributes of a class: `attr_reader`, `attr_writer`, and `attr_accessor`. They all automatically create methods that do things to keep us from having to write so many methods.

Giving a symbol to `attr_reader` automatically makes a method by the name of the symbol that will read the instance variable by the same name.

`attr_writer` will automatically create a method ending with an `=` with will then write/set the symbol's instance variable to the value given.

`attr_accessor` is the best of both worlds and it automatically creates methods to read and write. Again, it uses the name of the symbol given.

The example below shows a `Kitty` class with these different `attr` things.


```ruby
class Kitty
    attr_accessor :name  # creates method to read/get & write/set the instance variable
    attr_reader :lives_remaining  # creates method to read/get the instance variable

    def initialize name
        @name = name
        @lives_remaining = 9
    end
end

# irb and output
irb(main):003:0> cat_1 = Kitty.new('Mouse')
=> #<Kitty:0x00007fa04e956f50 @name="Mouse", @lives_remaining=9>
```


---
## More New Stuff that I Never Saw in Python

Every time I see something new-to-me in Ruby I wonder if it's because I never came across it in Python or because Ruby just has all sort of cool stuff that Python doesn't have.

### `method_name=`
Turns out method names can not only end with question marks, but they can also end with equal signs.

Ending a method with an `=`, Ruby reads it as "this method is going to change the value of something"

In this example, we have a `Cat` class. We're going to create a new cat. Then, we are going to rename that cat.

```ruby
class Cat
    def initialize name
        @name = name
    end
    
    def name= new_name
        @name = new_name
    end
end

# output
irb(main):005:0> cat_one = Cat.new 'Blocks' 
irb(main):012:0> cat_one
=> #<Cat:0x00007ff6948b19a0 @name="Blocks">
irb(main):013:0> cat_one.name = "Socks"
=> "Socks"
irb(main):014:0> cat_one
=> #<Cat:0x00007ff6948b19a0 @name="Socks">
```


---
## Reminder To Self (haha, get it :D)
1. Use `irb` in terminal to get IRB. I keep getting this mixed up because Python uses `python` to get REPL.

---
If you missed the first post in this series, I've heard it's a good read and there's cats.
{% post https://dev.to/vickilanger/python-to-ruby-1hc2 %}