2

I joined Rails team and maintain the codes. Some of the objects are controlled by Gem virtus, but I really don't understand like below code is doing.

I understand the result that the attribute 'latest_book' can collect latest book from Books but why it can be done? What 'books=(books)' is doing? and Why 'super books' is here?

class GetBooks
  include Virtus.model
  include ActiveModel::Model

  attribute :books, Array[Book]
  attribute :latest_book, Book

  def books=(books)
    self.latest_book = books.sort_by { |book| book['createdate'] }.last
    super books
  end
end

Could you help me?

d.y
  • 105
  • 1
  • 6

1 Answers1

4

def books=(books) is defining a method called books= which takes a single argument books. Yes, that's confusing. It should probably be def books=(value) or def books=(new_books).

And yes, the = is part of the method name. self.books = value is really syntax sugar for self.books=(value). Again, the method is books=.

super books is super(books). super calls the next inherited or included method of the same name; it's calling books= created by attribute :books, Array[Book]. This is a "method override" which allows you to add to the behavior of an existing method.

When books= is called it updates latest_books and then calls its the original method to set the books attribute.

gb = GetBooks.new
gb.books = [old_book, new_book]

p gb.latest_book # new_book
p gb.books       # [old_book, new_book]
Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Thanks a lot! What I wanted to know was this point. "created by attribute :books, Array[Book]." and then understand "method override", in this case, setter override is used. – d.y Jul 06 '20 at 07:58
  • 1
    @d.y you could also use `super` instead of `super books` since it passes the arguments along by default. – Stefan Jul 06 '20 at 16:28