Doubt regarding the ||= ruby operator

Asked

Viewed 553 times

3

Hello I’m still starting in Ruby, and I have a question regarding the following code

Main.Rb

web_design = Livro.new "Ruby", "X", "9428", 56.40, :web_design
android_dev = Livro.new "Java", "Y", "9385", 78.9, :android_dev
game_dev = Livro.new "Unity", "Z", "9420", 67.5, :game_dev

biblioteca = Biblioteca.new

biblioteca.adiciona web_design
biblioteca.adiciona android_dev
biblioteca.adiciona game_dev

for categoria,livros in biblioteca.livros do
    p categoria
    for livro in livros do
        p livro.preco
    end
end

Library.Rb

class Biblioteca

    attr_reader :livros

    def initialize
        @livros = []
    end

    def adiciona(livro)
        @livros[livro.categoria] ||= [] 
        @livros[livro.categoria] << livro
    end

    def livros
        @livros.values.flatten
    end
end

Basically when I try to add books to the library, the compiler returns the following error "Library.Rb:11: in []: no implicit Conversion of Symbol into integer ".

I did some research on the error, and it would be due to the fact that I was treating an array as a hash.

def adiciona(livro)
    @livros[livro.categoria] ||= [] 
    @livros[livro.categoria] << livro
end

In addition to this excerpt above indicate the error, to be quite frank its purpose has not yet become very clear.

Thank you in advance.

  • You are starting @books as an array @livros = []. You should initialize as a hash @livros = {}

1 answer

5


First, let’s understand what ||= means in your code. Basically, and for ease of understanding, you can translate the code to something more didactic like:

def adiciona(livro)
    @livros[livro.categoria] = @livros[livro.categoria] || []
    @livros[livro.categoria] << livro
end

To be EVEN clearer, this code could be translated into something like this as well:

def adiciona(livro)
    @livros[livro.categoria] = [] unless @livros[livro.categoria]
    @livros[livro.categoria] << livro
end

That is, if @books[book.category] be it nil (therefore, it will be evaluated as false), then an empty array will be assigned to the variable. Otherwise, the variable will keep the value it already has. But your code will be cleaner and clear if you just use ||=, agrees? :)

Now talking about your problem. The point is that you are assigning an empty Array to the variable @books and then you’re trying to treat it like a hash. Simply change your constructor code to:

def initialize
    @livros = {}
end
  • Dear thank you, it was much clearer the use of ||=, solved the problem too, was inattention on my part.

  • Oops! Excellent, @wagnermps!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.