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
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 trying to understand concepts of including or inheriting a module inside a class. Whenever I read i get new ways to include or inherit a module inside a class. So just want to know how many ways are there. Here are the examples I am sharing:
Example 1
module TimeExtensions
refine Fixnum do
def minutes; self * 60; end
end
end
class MyApp
using TimeExtensions
def initialize
p 2.minutes
end
end
Example 2
VAL = 'Global'
module Foo
VAL = 'Foo Local'
class Bar
def value1
VAL
end
end
end
class Foo::Bar
def value2
VAL
end
end
Example 3
module Foo
def foo
puts 'heyyyyoooo!'
end
end
class Bar
include Foo
end
Out of the three, only the last one includes a module into the class. That is, it adds the methods from the module to the class.
The first one is called refinement. If instead of refining Fixnum you just added a #minutes method to it, Fixnum will have that method for everyone that uses it, as long as your code is loaded. This might cause conflicts with other implementations of the same method (for example active record's #minutes) and leads to obscure, hard to debug issues. Instead, you can refine the Fixnum class and it will have that method only in the scope where you added the refinement with using.
It has some issues and it's not very widely used. But for the purposes of this question, the differences between including a module and using a refinement are:
including will add methods to the class where you do the inclusion, while refinements make other classes behave differently in the context where they are used
including is semantical (all objects will have the new included methods), while refinements are lexical (after you close the class, if you reopen it again, you won't see the refined methods)
The second one is scoping the class inside the module. This doesn't add methods anywhere. It is just due to the way constants are searched that if the constant (in this case VAL) isn't found in the current class, it is searched further up the tree. It's not that simple actually, if you want more details, you can read here.
The methods in Math can be invoked like a class method:
Math.cos(0)
but also can be include-d like instance method:
include Math
cos(0)
In contrast, the following modules can be invoked in one way but not the other:
module Foo
def bar
end
end
Foo.bar() # NoMethodError for this call
include Foo
bar() # but this call is fine
Singleton method:
module Foo
def self.bar
end
end
Foo.bar() # this call is fine
include Foo
bar() # but not this one
Any idea how to write a module like Math?
There're a few ways to get singleton methods, so I'm going to go over those first. We'll get to the part that lets the include Math work in a minute. So, first, if you're in a module or class body, you can define a singleton method as a method of self, like so:
module Foo
# Define bar as a method on self (the Foo module), thereby making
# it a singleton method.
def self.bar
"baz"
end
end
Alternatively, you can define them as methods on a module or class's singleton class:
module Foo
# Opens the singleton class of self (the Foo module). This makes
# bar a singleton method (see Module#define_singleton_method for
# some more on that).
class <<self
def bar
"baz"
end
end
end
include Math, Having Your Methods, and Eating Them Too
Thirdly, if you want methods as both instance and singleton methods, you can use extend. This allows you to include the module somewhere and call its methods without qualification or at least with differing qualification, depending on where you include the module (sort of -- that's beyond the scope of this, though). You can also extend self or extend using another module (containing instance methods) to add them as singleton methods when in a module or class body. This might sound more complicated than it probably looks:
module Foo
def bar
"baz"
end
# Extending self will add the instance methods of self as
# methods on the object self -- which happens to be a module,
# so you basically get class methods from the instance methods.
extend self
end
This last case allows you to also include the module in another module or class and gain bar as an instance method as well, so what you do depends on what you need. In general, I prefer the first route if I'm just defining a singleton method and it's all I'll need. The second option is more or less equivalent, but also allows you to use alias_method and so on. Qualified access is next to godliness, as far as I'm concerned.
The third option, however, — using extend self — is good for doing what you're asking about with include Math, where you want to be able to both call a function as a singleton method (Math.cos(0)) and include the module to access and call the methods without qualifying them with the module name (cos(0)). If you want that, you can do one of the following:
Define the method twice, both as a singleton method and as an instance method. This is not preferrable.
Define them in another module and both include and extend using that module. This is handy if you want to use the module in multiple places.
extend self. Extending using self is probably the best choice here, since it's simple, reduces duplicate code, and it's sufficient for the purpose of the question.
So there you go, instance methods and singleton methods living side-by-side in harmony, just like Holan and Hamlet.
That's what Module#module_function is for.
Let's say I have a bunch of related functions that have no persistent state, say various operations in a string differencing package. I can either define them in a class or module (using self) and they can be accessed the exact same way:
class Diff
def self.diff ...
def self.patch ...
end
or
module Diff
def self.diff ...
def self.patch ...
end
I can then do Diff.patch(...). Which is 'better' (or 'correct')?
The main reason I need to group them up is namespace issues, common function names are all used elsewhere.
Edit: Changed example from matrix to diff. Matrix is a terrible example as it does have state and everyone started explaining why it's better to write them as methods rather than answer the actual question. :(
In your two examples, you are not actually defining methods in a Class or a Module; you are defining singleton methods on an object which happens to be a Class or a Module, but could be just about any object. Here's an example with a String:
Diff = "Use me to access really cool methods"
def Diff.patch
# ...
end
You can do any of these and that will work, but the best way to group related methods is in a Module as normal instance methods (i.e. without self.):
module Diff
extend self # This makes the instance methods available to the Diff module itself
def diff ... # no self.
def patch ...
end
Now you can:
use this functionality from within any Class (with include Diff) or from any object (with extend Diff)
an example of this use is the extend self line which makes it possible to call Diff.patch.
even use these methods in the global namespace
For example, in irb:
class Foo
include Diff
end
Foo.new.patch # => calls the patch method
Diff.patch # => also calls Diff.patch
include Diff # => now you can call methods directly:
patch # => also calls the patch method
Note: the extend self will "modify" the Diff module object itself but it won't have any effect on inclusions of the module. Same thing happens for a def self.foo, the foo won't be available to any class including it. In short, only instance methods of Diff are imported with an include (or an extend), not the singleton methods. Only subclassing a class will provide inheritance of both instance and singleton methods.
When you actually want the inclusion of a module to provide both instance methods and singleton methods, it's not completely easy. You have to use the self.included hook:
module Foo
def some_instance_method; end
module ClassMethods
def some_singleton_method; end
end
def self.included(base)
base.send :extend, ClassMethods
end
def self.will_not_be_included_in_any_way; end
end
class Bar
include Foo
end
# Bar has now instance methods:
Bar.new.some_instance_method # => nil
# and singleton methods:
Bar.some_singleton_method # => nil
The main difference between modules and classes is that you can not instantiate a module; you can't do obj = MyModule.new. The assumption of your question is that you don't want to instantiate anything, so I recommend just using a module.
Still you should reconsider your approach: rather than using arrays of arrays or whatever you are doing to represent a Matrix, it would be more elegant to make your own class to represent a matrix, or find a good class that someone else has already written.
Ruby Modules are used to specify behaviour, pieces of related functionality.
Ruby Classes are used to specify both state and behaviour, a singular entity.
There is a maxim in software design that says that code is a liability, so use the less code possible. In the case of Ruby, the difference in code lines is cero. So you can use either way (if you don't need to save state)
If you want to be a purist, then use a Module, since you won't be using the State functionality. But I wouldn't say that using a class is wrong.
As a trivia info: In Ruby a Class is a kind of Module.
http://www.ruby-doc.org/core-1.9.3/Class.html
The following also works
Matrix = Object.new
def Matrix.add ...
def Matrix.equals ...
That's because so-called "class methods" are just methods added to a single object, and it doesn't really matter what that object class is.
As a matter of form, the Module is more correct. You can still create instances of the class, even if it has only class methods. You can think of a module here as a static class of C# or Java. Classes also always have the instance related methods (new, allocate, etc.). Use the Module. Class methods usually have something to do with objects (creating them, manipulating them).
I'm new to ruby metaprogramming, and I see people metaprogramming code in different places, like class Object, class Module, module Kernel and "nothing" (ie, out of a class/module definition block).
E.g.: I'm creating a c_attr_accessor method to access class variables, and I'm not sure where I must put the code, since it works in any of those cases.
How to decide what place is more appropriate to put a new global code?
Each of these examples fall into different cases.
If you are writing methods that apply to all objects, then you open the Object class so all objects can access it. If you are writing methods that apply to all modules, then you open Module. Whenever you open a class to add methods, the methods should apply to all instances of the class and nothing else.
Extending the Kernel module is different: people do this to add methods that should be available to every scope, but not really as methods to be explicitly called on an object, by making them private.
When you are outside of any class or module statement, you are in the scope of the main object, and methods you define default to being private methods of Object. This is fine for small or simple programs, but you will eventually want to use proper modules as namespaces to organize your methods.
As a final note on the subject, you always need to be sure that you really want methods you add to built-in classes and modules to be available to everything in your application, including external inclusions because they all share the built-ins.
Now to apply this to answer your question. Because you are defining a method that creates accessors for class variables, you should put it in the class Class as it applies to all classes and nothing else. Finally, you will likely only use it in class definitions (within a class statement), so we should make it private:
class Class
private
def c_attr_accessor(name)
# ...
end
end
class User
c_attr_accessor :class_variable_name
# ...
end
If you don't really need it in every class (maybe just a few), then create a "mixin module" to extend every class that needs this feature:
module ClassVariableAccessor
private
def c_attr_accessor(name)
# ...
end
end
class User
extend ClassVariableAccessor
c_attr_accessor :class_variable_name
# ...
end
Note that you are using Object#extend to add c_attr_accessor only to the object User (remember that classes are objects; you will hear that a lot if you are new to Ruby metaprogramming).
There is another way to implement the last example, which works by explicitly extending its base class through the Module#included(base_class) "hook method" called whenever the module included, and the base class is passed to base_class:
module ClassVariableAccessor
def included(base_class)
base_class.extend ClassMethods
end
module ClassMethods
def c_attr_accessor(name)
# ...
end
end
end
class User
include ClassVariableAccessor
c_attr_accessor :class_variable_name
# ...
end
I recommend this last solution because it is the most general and uses a simple interface that should not need to be updated. I hope this is not too much!
Have you tried looking up where the normal attribute accessors are defined? I'd either define it in the same class/module, or create my own module in which all my new methods go.