Expected to define. When calling class inside a module
I had the same problem. It comes from the fact that you try to load /lib/blog/core/search/base.rb directly in application.rb with /lib/**/
Error I had:
Expected /[...]/myapp/lib/durative/base.rb to define Base (LoadError)
Directory structure:
lib/
--durative/
--base.rb
base.rb:
module Durative
class Base
def initialize(config)
@config = {}
end
#...
end
end
application.rb:
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Here are the changes I made to make it work
Directory structure:
lib/
--durative.rb **(added)**
--durative/
--base.rb
durative.rb:
require 'durative/base'
base.rb (no change)
application.rb (changed):
config.autoload_paths += Dir["#{config.root}/lib/"]
Tell us if it worked for you too.
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.
Is it possible to call a Module function from inside a class that is also in that module
In order to invoke M::helper
you need to define it as def self.helper; end
For the sake of comparison, take a look at helper and helper2 in the following modified snippet
module M
class C < Struct.new(:param)
include M # include module to get helper2 mixed in
def work
M::helper(param)
helper2(param)
end
end
def self.helper(param)
puts "hello #{param}"
end
def helper2(param)
puts "Mixed in hello #{param}"
end
end
c = M::C.new("world")
c.work
Testing a ruby module class method not working
Reading the reference in this article which explains include, extend, and prepend and I found out that extends
works with the Singleton class already so the self
is unnecesary.
I made a small test with this code, which removes the self
in the definition
module SomeModule
module Account
def account_info
raise NotImplementedError
end
end
end
class MockClass
extend SomeModule::Account
end
MockClass.account_info
And that raises NotImplementedError
When to use nested classes and classes nested in modules?
Other OOP languages have inner classes which cannot be instantiated without being bound to an upper level class. For instance, in Java,
class Car {
class Wheel { }
}
only methods in the Car
class can create Wheel
s.
Ruby doesn’t have that behaviour.
In Ruby,
class Car
class Wheel
end
end
differs from
class Car
end
class Wheel
end
only in the name of the class Wheel
vs. Car::Wheel
. This difference in name can make explicit to programmers that the Car::Wheel
class can only represent a car wheel, as opposed to a general wheel. Nesting class definitions in Ruby is a matter of preference, but it serves a purpose in the sense that it more strongly enforces a contract between the two classes and in doing so conveys more information about them and their uses.
But to the Ruby interpreter, it’s only a difference in name.
As for your second observation, classes nested inside of modules are generally used to namespace the classes. For instance:
module ActiveRecord
class Base
end
end
differs from
module ActionMailer
class Base
end
end
Although this is not the only use of classes nested inside of modules, it is generally the most common.
In Ruby, in a method defined in class self, why can't a constant defined on the superclass be access without self?
You have encountered a common Ruby gotcha - constant lookup.
The most important concept in constant lookup is Module.nesting
(unlike in method lookup, where the primary starting point is self
). This method gives you the current module nesting which is directly used by the Ruby interpreter when resolving the constant token. The only way to modify the nesting is to use keywords class
and module
and it only includes modules and classes for which you used that keyword:
class A
Module.nesting #=> [A]
class B
Module.nesting #=> [A::B, A]
end
end
class A::B
Module.nesting #=> [A::B] sic! no A
end
In meta programming, a module or class can be defined dynamically using Class.new
or Module.new
- this does not affect nesting and is an extremely common cause of bugs (ah, also worth mentioning - constants are defined on the first module of Module.nesting):
module A
B = Class.new do
VALUE = 1
end
C = Class.new do
VALUE = 2
end
end
A::B::VALUE #=> uninitialized constant A::B::VALUE
A::VALUE #=> 2
The above code will generate two warnings: one for double initialization of constant A::VALUE and a second for reassigning the constant.
If it looks like "I'd never do that" - this also applies to all the constants defined within RSpec.describe
(which internally calls Class.new), so if you define a constant within your rspec tests, they are most certainly global (unless you explicitly stated the module it is to be defined in with self::
)
Now let's get back to your code:
class SubExample < SuperExample
puts Module.nesting.inspect #=> [SubExample]
class << self
puts Module.nesting.inspect #=> [#<Class:SubExample>, SubExample]
end
end
When resolving the constant, the interpreter first iterates over all the modules in Module.nesting
and searches this constant within that module. So if nesting is [A::B, A]
and we're looking for the constant with token C
, the interpreter will look for A::B::C
first and then A::C
.
However, in your example, that will fail in both cases :). Then the interpreter starts searching ancestors of the first (and only first) module in Module.nesting. SubrExample.singleton_class.ancestors
gives you:
[
#<Class:SubExample>,
#<Class:SuperExample>,
#<Class:Object>,
#<Class:BasicObject>,
Class,
Module,
Object,
Kernel,
BasicObject
]
As you can see - there is no SuperExample
module, only its singleton class - which is why constant lookup within class << self
fails (print_constant_fails
).
The ancestors of Subclass
are:
[
SubExample,
SuperExample,
Object,
Kernel,
BasicObject
]
We have SuperExample
there, so the interpreter will manage to find SuperExample::A_CONSTANT
within this nesting.
We're left with print_constant_works_2
. This is an instance method on a singleton class, so self
within this method is just SubExample
. So, we're looking for SubExample::A_CONSTANT
- constant lookup firstly searches on SubExample
and, when that fails, on all its ancestors, including SuperExample
.
Ruby: Is it possible to define a class method in a module?
module Common
def foo
puts 'foo'
end
end
class A
extend Common
end
class B
extend Common
end
class C
extend Common
end
A.foo
Or, you can extend the classes afterwards:
class A
end
class B
end
class C
end
[A, B, C].each do |klass|
klass.extend Common
end
Related Topics
How to Get the Target of a Symlink
Repairing Postgresql After Upgrade to Osx Mavericks
Ruby - Determine If a Number Is a Prime
Aws Elastic Beanstalk - How to Upgrade Existing Environment from Ruby 2.1 to Ruby 2.2
How Mix in Routes in Sinatra for a Better Structure
How to Use "Puts" to the Console Without a Line Break in Ruby on Rails
Embedding JSON Data into Yaml File
Finding the Session Id in Rails 3
What Is '$:.Unshift File.Dirname(_File_)' Doing
What Does Post.All.Map(&:Id) Mean
Iterating Between Two Datetimes, with a One Hour Step
Uninitialized Constant Rake::Dsl in Ruby Gem
Rails: Opposite of Hash#To_Param
The Encoding That Notepad++ Just Calls "Ansi", Does Anyone Know What to Call It for Ruby