Do Ruby 'Require' Statements Go Inside or Outside the Class Definition

Do Ruby 'require' statements go inside or outside the class definition?

Technically, it doesn't really matter. require is just a normal method call, and the scope it's called in doesn't affect how it works. The only difference placement makes is that it will be executed when whatever code it's placed in is evaluated.

Practically speaking, you should put them at top so people can see the file's dependencies at a glance. That's the traditional place for it.

In Ruby, do i require within a class or outside?

It will work either way. require works anywhere, and the FileUtils will be available inside and outside of your class.

By what I have seen on github, it is usually on top - just like most of the other languages, by the way.

Require statements inside methods?

If the dependency has good namespace organization (won't pollute the global namespace) and isn't large (won't slow startup times), I'd say put it at the top of the file. It's where people expect to find require statements. If it has either of those problems, consider putting it in the most limited scope possible.

How does include module works inside vs outside the class

From the other answer:

Outside of any class definition include Foo will add Foo to the ancestors of Object. [...] all of Foo's instance methods are now available everywhere.

By including a module at the top level, you are effectively saying:

Object.include(Human)

# or

class Object
include Human
end

What you are missing is that modules and classes are objects, too.

The methods an object responds to come from its ancestors, e.g.:

1.0.class.ancestors
#=> [Float, Numeric, Comparable, Object, Kernel, BasicObject]

'abc'.class.ancestors
#=> [String, Comparable, Object, Kernel, BasicObject]

or, for your module:

Human.class.ancestors
#=> [Module, Object, Kernel, BasicObject]

When you include Human at the top level, it adds that module to every object's ancestors:

include Human

1.0.class.ancestors
#=> [Float, Numeric, Comparable, Object, Human, Kernel, BasicObject]
# ^^^^^

'abc'.class.ancestors
#=> [String, Comparable, Object, Human, Kernel, BasicObject]
# ^^^^^

Human.class.ancestors
#=> [Module, Object, Human, Kernel, BasicObject]
# ^^^^^

Some examples:

1.0.living   #=> true
'abc'.living #=> true
Float.living #=> true
Human.living #=> true

When do you have to require a module in Ruby?

You never require modules, you require files.

In the above example, if the two fragments that you posted were in different files, e.g. my_first_module.rb and module_tester.rb, then you would have to do

require "my_first_module"

before you could reference MyFirstModule.

(Obviously, if they were in the same file, no require statement would be necessary, and would not make sense anyway, as there would be no file to require.)

What require does is to look for the given Ruby file in the library path, and then load the Ruby file, just as if you had executed it. The file will be loaded at most once during the runtime of your program (which is the difference to the load command, which is otherwise very similar to require).

In the above example, before you can use MyFirstModule, you'll have to require the file that defines it.

Be aware that there is an auto loading mechanism which can require files automatically for you. Also, Rails does require most classes automatically. So don't be confused that in some cases a require statement does not seem to be necessary.

Which context should I code for using require method

Case 2 is better, purely because it's proper etiquette and easier for other programs to find your code's dependencies.

Technically, require does the exact same thing no matter where you call it: it simply runs the code in the file. The only difference between placements is when (if ever) the require is actually called. For example:

def my_method
require "my_extension"
end

In this case, my_extension.rb isn't loaded until my_method is called.

In Ruby or Rails, why is include sometimes inside the class and sometimes outside the class?

Yes, include Foo inside a class adds Foo to that class's ancestors and thus makes all of Foo's instance methods available to instances of those class.

Outside of any class definition include Foo will add Foo to the ancestors of Object. I.e. it is the same as if you did include Foo inside the definition of the Object class. The use doing this is that all of Foo's instance methods are now available everywhere.

Why are global methods allowed to be defined outside of a class in Ruby?

When you define a function in Ruby at the global scope in this way, it technically becomes a private method of the Object class, which is the base class that everything inherits from in Ruby. Everything in Ruby is an object, so it is indeed true that you have defined a method.

def say_goodnight(name)
result = "Goodnight, " + name
return result
end

Object.private_methods.include? :say_goodnight
=> true

Because it is defined as a method with private visibility on Object, it can only be called inside objects of the class on which it's defined or subclasses. So why does it appear to be available globally?

Basically, the Ruby program itself defines an instance of Object called main, which serves as the top-level scope where your method was defined. So if you think of your program as running inside main (which is an Object) its private methods are available for use.

# In irb:
self
=> main
self.class
=> Object
self.private_methods.include? :say_goodnight
=> true

Addendum:
This answer which further explains how main is defined and implemented.

Update for Ruby >= 2.3

Noted in the comment thread, later versions of Ruby would define the method Object#say_goodnight in this example with public visibility rather than private. This behavior appears to have changed between Ruby 2.2.x and 2.3.x, but does not affect method exposure.

Ruby - How to include classes in a Module

Im not sure what the issue is. I understand that it says uninitialized but Im not sure why. It seems it is looking for a constant instead of reading the class?

It is not clear to me what you mean by "reading the class". Yes, Ruby is looking for a constant. Variable names that begin with a capital letter are constants, ergo, HtmlBody is a constant, HeadingTags is a constant, and HtmlBody::HeadingTags is the constant HeadingTags located in a class or module that is referenced by the constant HtmlBody.

How are you supposed to include classes located in separated files inside a module?

You namespace a class inside a module by defining the class inside the module. If you are sure that the module already exists, you can define the class like this:

class HtmlBody::HeadingTags
# …
end

However, if HtmlBody is not defined (or is not a class or module), this will fail.

module HtmlBody
class HeadingTags
# …
end
end

This will guarantee that module HtmlBody will be created if it doesn't exist (and simply re-opened if it already exists).

There is also a slight difference in constant lookup rules between the two, which is however not relevant to your question (but be aware of it).

The is something that Im missing in Ruby and the require/require_relative probably.

Indeed, your question stems from a fundamental misunderstanding of what Kerne#load / Kernel#require / Kernel#require_relative does.

Here is the very complicated, detailed, in-depth explanation of all the incredibly convoluted stuff that those three methods do. Brace yourself! Are you ready? Here we go:

They run the file.

Wait … that's it? Yes, that's it! That's all there is to it. They run the file.

So, what happens when you run a file that looks like this:

class HeadingTags
# …
end

It defines a class named HeadingTags in the top-level namespace, right?

Okay, so what happens when we now do this:

require_relative './html_body/HeadingTags'

Well, we said that require_relative simply runs the file. And we said that running that file defines a class named HeadingTags in the top-level namespace. Therefore, this will obviously define a class named HeadingTags in the top-level namespace.

Now, looking at your code: what happens, when we do this:

module HtmlBody
require_relative './html_body/HeadingTags'
end

Again, we said that require_relative simply runs the file. Nothing more. Nothing less. Just run the file. And what did we say running that file does? It defines a class named HeadingTags in the top-level namespace.

So, what will calling require_relative from within the module definition of HtmlBody do? It will define a class named HeadingTags in the top-level namespace. Because require_relative simply runs the file, and thus the result will be exactly the same as running the file, and the result of running file is that it defines the class in the top-level namespace.

So, how do you actually achieve what you are trying to do? Well, if you want to define a class inside a module, you have to … define the class inside the module!

lib/html_body.rb

require_relative 'html_body/heading_tags'
require_relative 'html_body/anchor_tags'
require_relative 'html_body/img_tags'

module HtmlBody; end

lib/html_body/heading_tags.rb

module HtmlBody
class HeadingTags
# …
end
end

lib/html_body/anchor_tags.rb

module HtmlBody
class AnchorTags
# …
end
end

lib/html_body/img_tags.rb

module HtmlBody
class ImgTags
# …
end
end

main.rb

require_relative 'lib/html_body'

HtmlBody::HeadingTags.new

Why can't ruby classes inside modules have the same scope as regular classes?

I have a module with a class inside,

No, you don't. You have a module definition with a class definition inside, but that does not make the class a nested class. Ruby does not have nested classes.

Ruby is not Beta, Scala, or Newspeak, there are no nested classes in Ruby.

Nesting a module or class definition inside another module or class definition does not create nesting relationship between the two classes / modules. It only makes the constant which references the class / module part of the outer class' / module's namespace.

In other words, there is no difference between

module Foo
class Bar
end
end

and

class Quux
end

module Foo
Bar = Quux
end

Only the constant is nested, but not the object that is referenced by the constant.

but I find that the class inside can't reach any of the methods in the enclosing module without specifying the module path.

That is precisely because there is no "enclosing module". There is a lexically enclosing module definition but that does not create any form of relationship whatsoever between the Foo class and the MyMod module.

Another way to look at it is that the module_function doesn't seem to carry into the class.

I honestly don't understand what you mean by that, what it means for a method to "carry into a class", but Module#module_function is not magic. It does exactly what the documentation says it does: it takes an instance method of the module, copies it as an instance method of the singleton class of the module, and makes the original instance method private.

You can read its specification in the Ruby/Spec, it is fairly simple. Also, the Rubinius source code, both the basic version for booting the Rubinius kernel and the full version are fairly readable.

In the end, Module#module_function really does not do much more than

class Module
def module_function(*meths)
meths.each do |meth|
define_singleton_method(meth, &instance_method(meth).bind(self))
private meth
end

self
end
end

If you run this, you get an error on the "But I can't..." line of:

undefined local variable or method `meaning'

The reason is simple: neither the class Foo nor any of its superclasses has any method of that name, so of course you get an exception.

But if you remove the MyMod bits around the whole file, it has no problem accessing the outer method.

There is no "outer method". Ruby does not have Beta-like nested classes. That is really the fundamental cause of your misunderstanding. You expect Ruby to behave like Beta, but it just doesn't. Ruby takes inspiration from any languages, most notably (in rough order of importance) Smalltalk, Lisp, Perl, and Clu, but Beta is not among them.

This here works for a completely different reason:

def meaning
42
end

class Foo
def initialize
meaning
end
end

Methods that are defined at the top-level are implicitly defined as private instance methods of Object. This is because the default definee at the top-level is ::Object. Since Foo inherits from Object, method lookup will eventually find the meaning method defined in Object.

Is there an easy way to make these accessible without having to give the full path?

Inheritance. For example, Module#append_features, which is called by Module#include, makes the module the superclass of the including class, and thus all instance methods of the module become part of the method lookup ancestry chain.

An aside: if there is no nesting, then what does Module::nesting do? Well, yeah, that is an unfortunately named method. The term "nested class" or "nested module" has a well-defined meaning in OO going all the way back to Beta. But this method is about a completely different kind of nesting:

It refers to the lexical nesting of module definitions, and not to nesting of modules themselves.

For example, these module definitions all define the exact same module, but the definition text has different nesting:

module Foo
module Bar
module Baz
module Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar::Baz, Foo::Bar, Foo]
end
end
end
end

module Foo
module Bar
module Baz::Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar, Foo]
end
end
end

module Foo
module Bar::Baz
module Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar::Baz, Foo]
end
end
end

module Foo::Bar
module Baz
module Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar::Baz, Foo::Bar]
end
end
end

module Foo
module Bar::Baz::Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo]
end
end

module Foo::Bar::Baz
module Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar::Baz]
end
end

module Foo::Bar
module Baz::Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux, Foo::Bar]
end
end

module Foo::Bar::Baz::Qux
p Module.nesting
#=> [Foo::Bar::Baz::Qux]
end

Again, this is purely lexical nesting of the module definition. The module itself is not nested; the module itself is the same in all of these cases. This nesting only affects constant lookup.

Constants are looked up first lexically outwards in enclosing module definitions, then upwards the inheritance chain.

There is another instance where things can be nested: blocks create nested lexical scopes, whereas all other lexical scopes (script, module / class definition, and method definition) don't nest. In other words, blocks and only blocks have access to the local variables (and self) of their enclosing lexical scopes.



Related Topics



Leave a reply



Submit