You need to add a module that adds an array to the object. This code for some reason does not work, there is no access to the @comments array in the methods

module Library module Commentable attr_accessor :comments def initialize author, title @comments = [] super author, title end end end class Library::Book include Library::Commentable attr_accessor :author, :title def initialize author, title @author = author @title = title end end 

    2 answers 2

    Because it turns out that initialize is first called on Library::Book , which the inherited method (from the Commentable ) does not call ( super is not there).

     Library::Book.ancestors #=> [ # Library::Book, <-- он первый по списку # Library::Commentable, # Object, # Kernel, # BasicObject # ] 

    If you forget about the fact that the “commented on” you for some reason accept the arguments characteristic of the book (because this is a detail of the task, about which you didn’t tell anything), there are two possible outputs:

    1. (in Ruby 2.0 and newer) Replace include with prepend so that the module is ahead of the entire search chain of methods (except after the metaclass, but this is a jungle).
    2. Transfer the super call to Library::Book (and remember that the call to super without arguments and parentheses passes the arguments of the current call).

      I will add my five kopecks. In the module, you can reload the included method, which is executed each time the module is included in another module or class using the include statement. As an argument, the class is passed to the method where the module was mixed in, which allows you to define your own methods:

       module Library module Commentable def self.included(base) base.class_eval do def comments= comments @comments = comments end def comments @comments end end end end end class Library::Book include Library::Commentable attr_accessor :author, :title def initialize author, title @author = author @title = title end end o = Library::Book.new 'Мария Эрих Ремарк', 'Три товарища' o.comments = [] p o.comments 

      However, as already mentioned D-side, a much more elegant task can be solved using the prepend method, which allows you to solve the problem more elegantly.

       module Library module Commentable attr_accessor :comments def initialize author, title @author = author @title = title @comments = [] end end end class Library::Book prepend Library::Commentable attr_accessor :author, :title def initialize author, title @author = author @title = title end end o = Library::Book.new 'Мария Эрих Ремарк', 'Три товарища' p o.comments p o.author 

      In the last example, you overwrite the Library::Book#initialize method with the Library::Commentable#initialize method. It doesn't make any sense here - since the example is very compact, but if you need to change the behavior of a class somewhere on the fly, you can open it and fix it with your module.

       class Library::Book prepend Library::Commentable end 
      • one
        Hmm, no, prepend does not overwrite initialize , it will just be in front of the corresponding method of the class itself, super work just the same way in the opposite direction. Unless, of course, use it. Otherwise, yes, it will look as if the original method is missing. - D-side