I am having an issue with namespaces in Rails 3.1. I have a class, let's call it a.
#/app/models/a.rb
class a
#some methods
def self.method_from_a
#does things
end
end
But I also have another class that has the same name in a different namespace.
#/app/models/b/a.rb
class b::a
def method
return a.method_from_a
end
end
When I call b::a.method though I get:
NameError: uninitialized constant b::a::a
I am sure it is a simple solution, I am just missing it.
Prefix a with :::
class b::a
def method
return ::a.method_from_a
end
end
This, (i.e. the scope operator) is also explained here:
Constants defined within a class or module may be accessed unadorned
anywhere within the class or module. Outside the class or module, they
may be accessed using the scope operator, ::'' prefixed by an
expression that returns the appropriate class or module object.
Constants defined outside any class or module may be accessed
unadorned or by using the scope operator::'' with no prefix.
By the way, in Ruby class names should start with an upper case letter.
Related
I've seen this a lot in Ruby (started using Ruby for the first time a couple years ago):
class MyAwesomeClass
another_method
def initialize; end
end
And I can't get my head around what type of method another_method is...
Looking at examples, it's sometimes declared as a class method, but usually you call class methods in your code like this:
AnotherClass.another_method
And most importantly you call your methods regardless if they are from another class, module, or inherited class inside another method of your class you use them. For example:
module SomeModule
def some_method; end
end
class AnotherClass
private
def another_method; end
end
class YetAnotherClass
self.yet_another_method; end
end
class MyAwesomeClass < AnotherClass
include SomeModule
def initialize
some_method # method from my included module
another_method # method inherited from AnotherClass
YetAnotherClass.yet_another_method # class method called directly
end
end
So what are these methods that can be called at the top of a class and NOT called inside of another method as my examples above?
Are you able to just call class methods inside another class (that it inherits from) outside of your method calls?
I can't get my head around what type of method another_method is...
There is only one type of method in Ruby: every method in Ruby is an instance method of some module. There is no other type of method.
We may sometimes talk about "class methods" or "singleton methods", but that is just a convenient way of talking about a particular way to use methods. The methods themselves are no different.
Every method in Ruby is an instance method of some module. The question is simply: which module?
We are sometimes talking about class methods, but class methods don't really exist. Class methods are simply singleton methods of an object that happens to be an instance of the Class class.
There is absolutely no difference between
Foo = ''
def Foo.bar; end
and
class Foo; end
def Foo.bar; end
and
module Foo; end
def Foo.bar; end
We call the first one a "singleton method", the second one a "class method", and the third one a "module function", but there is actually no difference between the three. The only difference is that the first object is an instance of the String class, the second object is an instance of the Class class, and the third object is an instance of the Module class, that's it.
Actually, I must confess something: I lied. I wrote that class methods are simply singleton methods of an object that happens to be an instance of the Class class, but in reality … singleton methods don't exist either.
A singleton method is simply a boring old normal instance method of the singleton class.
There is no difference between
foo = ''
def foo.bar; end
and
foo = ''
class << foo
def bar; end
end
There you have it: singleton methods are actually just instance methods of the singleton class, class methods are actually just instance methods of the singleton class of an object that is an instance of the Class class, module functions are actually just instance methods of the singleton class of an object that is an instance of the Module class.
It's just that "instance method of the singleton class of an object that is an instance of the Class class" is annoying to say and write all the time, so we say "class method" instead, knowing full well that there is no such thing.
Looking at examples, it's sometimes declared as a class method, but usually you call class methods in your code like this:
AnotherClass.another_method
Again, there is no such thing as a class method. There is exactly one kind of method, and they are always called the same way:
receiver.method(args)
If the receiver is self, then you can leave it out, and if you have no arguments, you can leave them out, too.
And most importantly you call your methods regardless if they are from another class, module, or inherited class inside another method of your class you use them.
That is not true.
In fact, in your own example, you are calling two methods outside of a method body: Module#private and Module#include, and you seem to have no trouble with those. Other methods that I am sure you have already called outside of a method body are Module#attr_accessor, Kernel#require, or Kernel#puts. In fact, in simple scripts, there is often not a single method definition body at all.
So what are these methods that can be called at the top of a class and NOT called inside of another method as my examples above?
They are instance methods just like any other instance methods, there is absolutely nothing special about them.
Are you able to just call class methods inside another class (that it inherits from) outside of your method calls?
Since class methods don't exist, and these are simply instance methods just like every other instance method, the method lookup algorithm is of course also just the method lookup algorithm for instance methods:
Start with the private internal hidden __klass__ pointer of the receiver. If you can't find the method there …
Get the private internal hidden __superklass__ pointer and repeat.
And that's it. (Yes, okay, there is a tiny bit more to it: if you come to a point where there is no __superklass__ pointer, then you try again with method_missing and the name of the method as an argument, and if you also cannot find that, then you raise a NoMethodError.)
So, let's try that in your example:
class MyAwesomeClass
another_method
end
Okay, first off: what is the receiver? Well, if no receiver is given, then the receiver is always implicitly self. Now, what is self here?
A ha! That is actually the most important question in Ruby, always. At any point in Ruby, you must always know what self is.
Well, we know that inside of a method body, self is the receiver of the message send. So, we can guess: what would make the most sense for self inside of a class definition. The class itself, of course! Let's test that:
what_is_self = class MyAwesomeClass
self
end
p what_is_self
# MyAwesomeClass
Well, looks like we're right. Okay, we know the receiver of the message send is MyAwesomeClass, so what is the first step in our algorithm? We get the private internal hidden __klass__ pointer.
We cannot actually do that in Ruby (it is a private internal hidden implementation detail of the Ruby implementation). But let me assure you that is pretty much always going to be the singleton class. (There are some objects which cannot have singleton classes, and some Ruby implementations optimize the creation of singleton classes so that they are only created when needed, but for all intents and purposes, we can assume that the __klass__ pointer is always the singleton class.)
We look inside the singleton class, and we find no definition of the method another_method. So, we move to the second step of the algorithm: we get the __superklass__ of the singleton class.
The __superklass__ of the singleton class is usually going to be the class of the object. So, in this case, the object is MyAwesomeClass, which is a class, so the class of MyAwesomeClass and the __superklass__ of the singleton class is going to be Class.
Again, we look inside Class and we don't find another_method. Ergo, we get Class's __superklass__, which is Module. We also don't find another_method here, so we move on to Object, which also doesn't have another_method.
Now, it gets interesting again, because Object's __superklass__ pointer is actually Kernel and not BasicObject as you might have thought. (More precisely, it is an include class which shares its method table with the Kernel module, since Kernel is not a class at all and thus cannot be a superclass.)
Kernel also doesn't have a method named another_method, so we get Kernel's __superklass__ (again, technically we are talking about an include class that proxies Kernel and not Kernel itself), which is BasicObject. Finally, BasicObject does not have a __superklass__.
Which means we start aaaaaaaaaaaall the way back from step #1 again, but this time as-if you had written
class MyAwesomeClass
method_missing(:another_method)
end
We do the whole song-and-dance again, and we also never find a method until we get to the very top, to BasicObject, which has a method_missing that roughly looks like this:
class BasicObject
def method_missing(meth, *args)
raise NoMethodError, "undefined method `#{meth}' for #{inspect}", meth, args, receiver: self
end
end
So, if you want your call to another_method to not fail, it needs to be defined anywhere along the whole chain we just walked up:
In MyAwesomeClass's singleton class
In a module that MyAwesomeClass extends
In Class
In a module that Class includes
Or in a module included by that module
In Module
In a module that Module includes
Or in a module included by that module
In Object
In Kernel
Or another module that Object includes
Or in a module that Kernel includes
In BasicObject
In a module that BasicObject includes
Or in a module included by that module
Or maybe the Ruby implementation you are using has an implementation-specific superclass of BasicObject (e.g. MacRuby has Objective-C's NSObject as the superclass of BasicObject)
To illustrate difference between different type of methods, consider this example:
class Foo
puts 'method called outside of method'
def initialize
puts 'initialize called'
end
def instanse_method
puts 'instance method called'
end
def self.clazz_method
puts 'class method called'
end
end
Foo
foo = Foo.new
foo.instanse_method
Foo.clazz_method
What will be the output?
method called outside of method
initialize called
instance method called
class method called
So what are these methods that can be called at the top of a class and NOT called inside of another method as my examples above?
As you can see, any method can be called before initialize method. It's executed when class is loaded.
Just calling
Foo
would be sufficient enough to output:
method called outside of method
(but notice that it was not called multiple times)
Looking at examples, it's sometimes declared as a class method, but usually you call class methods in your code like this: AnotherClass.another_method
It's like static function in PHP. In my example, it's Foo#clazz_method.
And most importantly you call your methods regardless if they are from another class, module, or inherited class inside another method of your class you use them
Usually, you have to include a file that define another class before using its method. But most frameworks like Ruby on Rails, have already built-in autoloading system, so it looks like it's working magically without explicit require or include. But there are times when RoR does not know where your custom classes are. In this case, you have to require the file explicitly before you use it. Well, usually in the beginning of the file.
It'll be easier to understand by looking at it in action.
# Step 1
# Run this in IRB
class MyClass
def self.another_method
puts "Executed when class is loaded to memory"
end
end
# Step 2
# Now when you run the following in IRB after that, its going to execute the
# class method which was defined in its parent class (MyClass)
class MyAwesomeClass < MyClass
another_method # Executed ONCE when the class is loaded to memory for the first
def initialize; end
end
# Now if you instantiate MyAwesomeClass though, it will not print the same as of
# Step 2 as class method :another_method already has been executed when class
# was loaded
awesome1 = MyAwesomeClass.new
The body of a class will be interpreted and executed sequentially & behaves much like you'd expect it inside an instance method. Try putting a puts "Hello World" in the body of your class definition like so:
class MyClass
# Executes when the class is defined in IRB(Loaded to memory)
puts "Hello World"
end
I am having trouble with some fundamental concepts in Ruby, specifically the interchangeability of a subclass for the superclass.
According to the Ruby documentation on classes, "Class" inherits from "Module".
https://ruby-doc.org/core-2.5.3/Class.html
class MyClassTest end
MyClassTest.is_a? Module # => true
However, when trying to use the module keyword to reopen a class defined with the keyword class, you get a TypeError that the class is not a module.
class MyClassTest end
module MyClassTest end # => TypeError: MyClassTest is not a module
This SO question has some excellent discussion surrounding subclasses vs subtypes, but I think it has lead me to more questions:
Why can't classes be used as modules?
Generally, since Ruby is dynamically typed, I am confused by the existence of TypeErrors.
Specifically, in this case, I am extra confused as to how Ruby inheritance can result in a TypeError where the subclass cannot be substituted for the superclass. In my mind, subclassing is equivalent to subtyping in Ruby since the subclass will inherit the interface (methods and public attributes) of the superclass.
My current guess is that TypeError's are raised by the core Ruby library when certain assertions fail, and these TypeErrors don't necessarily have anything to do with Ruby's dynamic typing system, which is to say that typing is not a first-class concept in Ruby. The linked SO question raises excellent points about the diamond problem with multiple class inheritance, so it makes sense that Ruby would prevent the interchangeable usage of modules and classes when using the module or class keyword. Still, it feels like there are inconsistencies in my understanding of Ruby.
How can a "Class" input result in a TypeError when a "Module" object is expected?
Basic assertions are
Class is a Class (Class.is_a?(Class) #=> true)
Class is a Module (Class.is_a?(Module) #=> true)
An instance of the class Class is a Class (Class.new.is_a?(Class) #=> true)
An instance of the class Class is a Module (Class.new.is_a?(Module) #=> true)
Module is a Class (Module.is_a?(Class) #=> true)
By virtue Module is a Module (Module.is_a?(Module) #=> true)
An instance of the class Module is a Module (Module.new.is_a?(Module) #=> true)
However An instance of the class Module is not a Class (Module.new.is_a?(Class) #=> false)
an instance of the class Class is an instance of Class but not and instance of the class Module (Class.new.instance_of?(Module) #=> false)
module is a declaration for an instance of the class Module just as class is a declaration for an instance of the class Class.
If this were a method it might look like
def module(name,&block)
raise TypeError if defined?(name) && !const_get(name).instance_of?(Module)
obj = defined?(name) ? const_get(name) : const_set(name, Module.new)
obj.instance_eval(&block)
end
TypeError exists to prevent ambiguity.
As in your case by using class MyClassTest you have created an instance of the class Class and that instance is called MyTestClass.
If you were also allowed to use module MyTestClass, in the same global context, then during usage I would be unaware if when calling MyClassTest I would be calling the Class or the Module.
The basic (very basic) difference is a Class can be instantiated (have instances) however a Module cannot.
For instance
Class.new.new #creates an instance of the anonymous class created by Class.new
Module.new.new # results in NoMethodError
I think the first point of confusion is the distinction between usage and definition.
The following code defines a class:
class C; end
If I see the above code, I expect to be able to instantiate C later:
C.new
However, imagine that C was already defined as a module:
# In one file:
module C; end
# Later in a different file:
class C; end # C is actually a module
C.new # fails
Ruby surfaces the problem (conflicting definitions of C) at the point where C is redefined as a class, rather than allowing the program to continue to where C is used.
The benefit of surfacing the problem earlier is generally the earlier an error is identified, the easier it is to find and fix its root cause (in this example, perhaps C is supposed to be a class after all, and thus the real issue is the module C definition).
Your second question is, I think, why a class cannot always be used as a module, for example why the following is prohibited:
class C; end
class A
include C
end
The answer, I think, is the programming language starts with concepts which are then implemented using various constructs. We could describe classes and modules as follows:
A class represents an object which has data and behavior (classic OOP definition).
A module is a collection of behavior.
The include keyword extends a class with a module's behavior. In principle it is possible to take just a class's methods and add them to another class. But this operation doesn't make sense because a class is an object and its behavior together. Taking just the behavior goes against the concept of the class.
There are other programming languages which take different positions on this issue. For example, in JavaScript any function can be taken out of any class and invoked with an instance of any other class. This can be convenient in some situations and difficult to debug in others.
I have a number of questions regarding ruby classes and modules. I have written a number of test files to kind of explore them further that are too long to post here (https://github.com/Senjai/Learning-Ruby/blob/master/class_test.rb and https://github.com/Senjai/Learning-Ruby/blob/master/mixin-instance-var-conflict.rb)
First three questions are about variables.
So far that I understand it, instance variables are prefixed with #, and are unique to each instance of the class. They can only be accessed with accessor methods (like attr_accessor)
Second, class variables, they're prefixed by ##.
How come class variables can't be used with attr_accessor/reader?
What's the difference between class.class_variable and instance.class_variable? If an instance modifies a class variable from within the class (e.g in an instance method) does that affect the static variable in the class definition?
Thirdly,
Why do instance/class variables need to be prefixed with #? What happens when they aren't prefixed at all? Like in the example below:
module Test
State = {}
def state=(value)
State[object_id] = value
end
def state
State[object_id]
end
end
For class methods, I understand that instance methods are defined as normal functions, and class methods have to be prefixed with self. Why can't you use class methods in an instantiated object? Why does self make it so special?
Lastly, for the scope resolution operator, I've only found that it works for constants and class methods, what's the point of having a scope resolution operator in the first place if they can be accessed in dot notation?
RSpec adds a "describe" method do the top-level namespace. However, instead of simply defining the method outside of any classes/modules, they do this:
# code from rspec-core/lib/rspec/core/dsl.rb
module RSpec
module Core
# Adds the `describe` method to the top-level namespace.
module DSL
def describe(*args, &example_group_block)
RSpec::Core::ExampleGroup.describe(*args, &example_group_block).register
end
end
end
end
extend RSpec::Core::DSL
Module.send(:include, RSpec::Core::DSL)
What is the benefit of using this technique as opposed to simply defining describe outside any modules and classes? (From what I can tell, the DSL module isn't used anywhere else in rspec-core.)
I made this change a few months ago so that describe is no longer added to every object in the system. If you defined it at the top level:
def describe(*args)
end
...then every object in the system would have a private describe method. RSpec does not own every object in the system and should not be adding describe willy-nilly to every object. We only want the describe method available in two scopes:
describe MyClass do
end
(at the top-level, off of the main object)
module MyModule
describe MyClass do
end
end
(off of any module, so you nest your describes in a module scope)
Putting it in a module makes it easy to extend onto the main object (to add it to only that object, and not every object) and include it in Module (to add it to all modules).
Actually, if that's all there is in the code, I don't really believe it to be much better — if at all. A common argument is that you can easily check that RSpec is responsible for addinng this method in the global namespace by checking the method owner. Somehow it never felt this was needed, as the location of the method already stores that information.
Defining the method outside of any scope would have be equivalent to defining a private instance method in Object:
class Object
private
def double(arg)
arg * 2
end
end
double(3) # OK
3.double(3) # Error: double is private
self.double(3) # Error: double is private
I think privateness is a useful aspect, because it prevents from making certain method calls that have no meaning, that the code shown in the question lacks.
There's an advantge to defining the method in a module, though, but the RSpec code doesn't seem to make use of it: using module_function, not only do you preserve privateness of the instance method, but you also get a public class method. This means that if you have an instance method of the same name, you will still be able to refer to the one defined by the module, by using the class method version.
A common example of module_function is the Kernel module, which contains most function-like core methods like puts (another one is Math). If you're in a class that redefines puts, you can still use Kernel#puts explicitly if you need:
class LikeAnIO
def puts(string)
#output << string
end
def do_work
puts "foo" # inserts "foo" in #output
Kernel.puts "foo" # inserts "foo" in $stdout
end
end
Just getting my head around Ruby metaprogramming. The mixin/modules always manage to confuse me.
include: mixes in specified module methods as instance methods in the target class
extend: mixes in specified module methods as class methods in the target class
So is the major difference just this or is a bigger dragon lurking?
e.g.
module ReusableModule
def module_method
puts "Module Method: Hi there!"
end
end
class ClassThatIncludes
include ReusableModule
end
class ClassThatExtends
extend ReusableModule
end
puts "Include"
ClassThatIncludes.new.module_method # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method # "Module Method: Hi there!"
extend - adds the specified module's methods and constants to the target's metaclass (i.e. the singleton class)
e.g.
if you call Klazz.extend(Mod), now Klazz has Mod's methods (as class methods)
if you call obj.extend(Mod), now obj has Mod's methods (as instance methods), but no other instance of of obj.class has those methods added.
extend is a public method
include - By default, it mixes in the specified module's methods as instance methods in the target module/class.
e.g.
if you call class Klazz; include Mod; end;, now all instances of Klazz have access to Mod's methods (as instance methods)
include is a private method, because it's intended to be called from within the container class/module.
However, modules very often override include's behavior by monkey-patching the included method. This is very prominent in legacy Rails code. more details from Yehuda Katz.
Further details about include, with its default behavior, assuming you've run the following code
class Klazz
include Mod
end
If Mod is already included in Klazz, or one of its ancestors, the include statement has no effect
It also includes Mod's constants in Klazz, as long as they don't clash
It gives Klazz access to Mod's module variables, e.g. ##foo or ##bar
raises ArgumentError if there are cyclic includes
Attaches the module as the caller's immediate ancestor (i.e. It adds Mod to Klazz.ancestors, but Mod is not added to the chain of Klazz.superclass.superclass.superclass. So, calling super in Klazz#foo will check for Mod#foo before checking to Klazz's real superclass's foo method. See the RubySpec for details.).
Of course, the ruby core documentation is always the best place to go for these things. The RubySpec project was also a fantastic resource, because they documented the functionality precisely.
#include RubySpec rubydoc
#included RubySpec rubydoc
#extend RubySpec rubydoc
#extended RubySpec rubydoc
#extend_object RubySpec rubydoc
#append_features RubySpec rubydoc
What you have said is correct. However, there is more to it than that.
If you have a class Klazz and module Mod, including Mod in Klazz gives instances of Klazz access to Mod's methods. Or you can extend Klazz with Mod giving the class Klazz access to Mod's methods. But you can also extend an arbitrary object with o.extend Mod. In this case the individual object gets Mod's methods even though all other objects with the same class as o do not.
That's correct.
Behind the scenes, include is actually an alias for append_features, which (from the docs):
Ruby's default implementation is to
add the constants, methods, and module
variables of this module to aModule if
this module has not already been added
to aModule or one of its ancestors.
When you include a module into a class, the module methods are imported as instance methods.
However, when you extend a module into a class, the module methods are imported as class methods.
For example, if we have a module Module_test defined as follows:
module Module_test
def func
puts "M - in module"
end
end
Now, for include module. If we define the class A as follows:
class A
include Module_test
end
a = A.new
a.func
The output will be: M - in module.
If we replace the line include Module_test with extend Module_test and run the code again, we receive the following error: undefined method 'func' for #<A:instance_num> (NoMethodError).
Changing the method call a.func to A.func, the output changes to: M - in module.
From the above code execution, it is clear that when we include a module, its methods become instance methods and when we extend a module, its methods become class methods.
All the other answers are good, including the tip to dig through RubySpecs:
https://github.com/rubyspec/rubyspec/blob/master/core/module/include_spec.rb
https://github.com/rubyspec/rubyspec/blob/master/core/module/extend_object_spec.rb
As for use cases:
If you include module ReusableModule in class ClassThatIncludes, the methods, constants, classes, submodules, and other declarations gets referenced.
If you extend class ClassThatExtends with module ReusableModule, then the methods and constants gets copied. Obviously, if you are not careful, you can waste a lot of memory by dynamically duplicating definitions.
If you use ActiveSupport::Concern, the .included() functionality lets you rewrite the including class directly. module ClassMethods inside a Concern gets extended (copied) into the including class.
I would also like to explain the mechanism as it works. If I am not right please correct.
When we use include we are adding a linkage from our class to a module which contains some methods.
class A
include MyMOd
end
a = A.new
a.some_method
Objects don't have methods, only clases and modules do.
So when a receives mesage some_method it begin search method some_method in a's eigen class, then in A class and then in linked to A class modules if there are some (in reverse order, last included wins).
When we use extend we are adding linkage to a module in object's eigen class.
So if we use A.new.extend(MyMod) we are adding linkage to our module to A's instance eigen class or a' class.
And if we use A.extend(MyMod) we are adding linkage to A(object's, classes are also objects) eigenclass A'.
so method lookup path for a is as follows:
a => a' => linked modules to a' class => A.
also there is a prepend method which changes lookup path:
a => a' => prepended modulesto A => A => included module to A
sorry for my bad english.
I came across a very useful article that compares include, extend and prepend methods used inside a class:
include adds module methods as instance methods to the class, whereas extend adds module methods as class methods. The module being included or extended must be defined accordingly