0

I am experimenting with ruby (2.4.1p111) and with the load method and it does have some strange behavior:

I have two files:

mytest.rb:

class MyClass

  def self.greet(param)
   puts "Got called: #{param}"
  end

  greet 'Called locally'

  load "./testld.rb"
end

and the loaded file:

testld.rb:

greet 'Called by load'

I understood from documentation that the loaded code from testld.rb and the method call right in the MyClass should behave the same. Instead, I am getting:

-bash-4.2$ ruby mytest.rb
Got called: Called locally
/Blacksmith/RB/testld.rb:1:in `<top (required)>': undefined method `greet' 
for main:Object (NoMethodError)
    from mytest.rb:9:in `load'
    from mytest.rb:9:in `<class:MyClass>'
    from mytest.rb:1:in `<main>'

Any idea what I do wrong?

7
  • 1
    Could you point to the documentation that left you with such understanding? That is not how it works. If it was enclosed in MyClass in testld.rb, it will be called as if it was. If it was not, it will not, no matter where you load it. Commented Aug 9, 2017 at 14:23
  • ruby-doc.org/core-2.4.1/Kernel.html#method-i-load I wrongly assumed the loaded code is executed in the context of the MyClass. MyClass.greet does the work as @MatayoshiMariano has pointed out. Commented Aug 9, 2017 at 14:46
  • @Pavel "I wrongly assumed the loaded code is executed in the context of the MyClass." That is not what MatayoshiMariano pointed out. That answer misses the point. Commented Aug 9, 2017 at 14:46
  • 2
    @Pavel you want something like eval File.read('testld.rb') but load doesn't work that way. Commented Aug 9, 2017 at 14:59
  • @Pavel, I couldn't see how you got this interpretation. I agree that Ruby's namespacing is one of it's weaker points, but it's not as terrible as for load to perform a copy-paste. xd Commented Aug 9, 2017 at 14:59

2 Answers 2

2

You need to call MyClass.greet in testld.rb, that is because greet is a class method defined in the class MyClass.

Here is documentation for class methods.

Sign up to request clarification or add additional context in comments.

3 Comments

@Pavel The fact that it works is coincidence. This answer is irrelevant to your actual question.
Is anything mentioned in this answer specific to Ruby 2.4, whose tag MatayoshiMariano added to the suggested edit?
@sawa I do not think that is a coincidince, but my answer may be incomplete, it's missing what load does. I added the ruby-2.4 tag because @Pavel says that he is using ruby 2.4.1p111
1

Wherever you load a file, the loaded file is always evaluated within the main environment. The value of self in the main environment of testld.rb is the main environment of the entire script. Hence, your

greet 'Called by load'

is not equivalent to

MyClass.greet 'Called by load'

as you expected.

4 Comments

What I really wanted to achieve is to have the static method called, the MyClass.greet. I thought that the load works kind of like a C preprocessor, placing the file content into the MyClass and then execute, which was wrong.
You do have defined MyClass.greet. That part, you did correctly. What you did wrong is the way you called it. And here is the explanation to it.
@Pavel Don't think of Ruby as a fancy C. It's Smalltalk in origin which has a different approach to solving problems like this. If you created a module and include it in your class you'll be able to hook in through the included method and everything should work seamlessly.
@Pavel: load, require, and require_relative simply run the file. That's all they do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.