This is best explained with an example:
file1.rb:
def foo
puts 123
end
file2.rb:
class A
require 'file1'
end
A.new.foo
will give an error "': private method 'foo' called".
I can get around this by doing A.new.send("foo") but is there a way to make the imported methods public?
Edit: To clarify, I am not confusing include and require. Also, the reason why I cannot use normal inclusion (as many have rightly pointed out) is that this is part of a meta-programming setup. I need to allow the user to add functionality at run-time; eg he can say "run-this-app --include file1.rb" and the app will behave differently based on the code he wrote in file1.rb. Sorry should have explained clearer.
Edit: After reading Jorg's answer I realized my code does not behave exactly as intended, and he answers my (misguided) question perfectly. I am trying to do something more akin to str=(entire file1.rb as string); A.class_exec(str).
Global procedures in Ruby aren't really global procedures. They are methods, like everything else. In particular, when you define what looks like a global procedure, you are actually defining a private instance method of
Object. Since every piece of code in Ruby is evaluated in the context of an object, this allows you to use those methods as if they were global procedures, sinceselfis the default receiver, andselfis an object whose class inherits fromObject.So, this:
is actually equivalent to
Now you have a "global procedure" called
foo, which you can call just like this:The reason why you can call it like this, is that this call is actually equivalent to
and
selfis an object that includesObjectin its ancestry chain, thus it inherits the privatefoomethod.[Note: to be precise, private methods cannot be called with an explicit receiver, even if that explicit receiver is
self. So, to be really pedantic, it is actually equivalent toself.send(:foo)and notself.foo.]The
A.new.fooin yourfile2.rbis a red herring: you could just as well tryObject.new.fooor[].fooor42.fooand get the same result.By the way:
putsandrequireare themselves examples of such "global procedures", which are actually private methods onObject(or more precisely, they are private methods onKernelwhich is mixed intoObject).On a sidenote: it is really bad style to put calls to
requireinside a class definition, because it makes it look like therequired code is somehow scoped or namespaced inside the class, which is of course false.requiresimply runs the code in the file, nothing more.So, while
is perfectly valid code, it is also very confusing. It is much better to use the following, semantically equivalent, code:
That way it is perfectly clear to the reader of the code that
file1.rbis in no way scoped or namespaced insideA.Also, it is generally preferred to leave off the file extension, i.e. to use
require 'file1'instead ofrequire 'file1.rb'. This allows you to replace the Ruby file with, for example, native code (for MRI, YARV, Rubinius, MacRuby or JRuby), JVM byte code in a.jaror.classfile (for JRuby), CIL byte code in.dllfile (for IronRuby) and so on, without having to change any of yourrequirecalls.One last comment: the idiomatic way to circumvent access protection is to use
send, notinstance_eval, i.e. useA.new.send(:foo)instead ofA.new.instance_eval {foo}.