0

I have a Ruby module in a file called my_module.rb:

module My_module
    def my_module_method
       puts 'inside my method'
    end
end

In a file my_class.rb in the same folder, I have a class contained within the module.

module My_module
   class My_class
        def my_object_method
          My_module.my_module_method
        end
   end
end

My_module::My_class.new.my_object_method => 'undefined method 'my_module_method''

I was not expecting this error. I assumed that Ruby would run into the line 'My_module.my_module_method' and search for a module called 'My_module' and a method within it called 'my_module_method.' This is what Java does, for example. However, Ruby does not do this. In order to get my_object_method to work, I have to write in my_class.rb:

require 'my_module.rb'

Why doesn't Ruby search for My_module when I call my_object_method? It seems obvious what it should search for and therefore redundant to require the programmer to explicitly write 'yes, Ruby, please allow me to make calls to module-wide methods.' What am I missing?

nickackerman42
  • 415
  • 4
  • 14
  • *"Why doesn't Ruby search for My_module when I call my_class_method? ... What am I missing?"* -- Ruby already knows about `My_module` when it reads `my_class.rb`. But the method `my_module_method` is not defined in this file. Somebody has to tell it in which file is this method defined. And that somebody is the programmer, as Ruby doesn't enforce any rule regarding any relationship between a class or a module name and the name of the file that stores it. What you ask is, basically, why Ruby cannot read your mind and magically know to read the `my_module.rb` file without you telling it so. – axiac Aug 17 '17 at 22:41
  • Ruby would not have to 'read my mind' to know where to look for my_module_method. It could simply look in $LOAD_PATH, like other languages do. The question is: why is Ruby designed to not look, when languages like Java are? What is the advantage of not looking? – nickackerman42 Aug 18 '17 at 13:59

2 Answers2

1

Ruby doesn't automatically load files. If you need a code from some file, you have to load it (by calling require) explicitly.

Thus, when you run "ruby my_class.rb" it loads only this file and you have to define dependencies between files by yourself.

Tema Bolshakov
  • 1,128
  • 8
  • 14
  • Thanks! This explains why I cannot call the method. But can you explain why Ruby doesn't autoload files when other languages do? What's the rationale behind the design choice? – nickackerman42 Aug 18 '17 at 13:57
  • 1
    Ruby is interpreting language. Thus, you can write literally anything in a .rb file. You can run web server, delete files, call external service, you name it. So, ruby was designed to be able to selectively load only required code. But you can always use autoloading if you need https://ruby-doc.org/core-2.1.0/Module.html#method-i-autoload – Tema Bolshakov Aug 18 '17 at 15:15
0

You seem to have a misunderstanding of how to define a class method. In order to make your method call work, you could define it as def self.my_method_name.

In both classes and modules, methods work the same when you define them as class methods using self. or alternatively the class << self syntax. However instance methods (methods without the self.) work differently in these 2 cases. In classes, as you seem to understand, they're accessible once you instantiate the class using .new. In modules, they're only accessible if you include or extend.

See also:

difference between class method , instance method , instance variable , class variable?

http://www.rortuts.com/ruby/ruby-include-vs-extend/

Oh any by the way. Ruby doesn't enforce any convention where you have 1 file per class (named identically). You need to manually require files wherever you need them. Although there are some frameworks such as Rails which auto-require files, and enforce naming conventions.

max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • my mistake -- in my code the method was a class method, but I modified it here to simplify things and forgot to change the name. I fixed it. – nickackerman42 Aug 18 '17 at 13:50