From the Module
Module#append_features(mod) → mod => When this module is included in another, Ruby calls append_features in this module, passing it the receiving module in mod. Ruby’s default implementation is to add the constants, methods, and module variables of this module to mod if this module has not already been added to mod or one of its ancestors.
Module#prepend_features(mod) → mod => When this module is prepended in another, Ruby calls prepend_features in this module, passing it the receiving module in mod. Ruby’s default implementation is to overlay the constants, methods, and module variables of this module to mod if this module has not already been added to mod or one of its ancestors.
Can anyone help me to understand the below questions:
What more features of Module are defined as append and prepend except those default?
How they differ functionally?
When to use append_features and when prepend_features?
what is the difference between two bold lines as above?
What features of Module are defined as append and prepend?
As specified in the text you quoted:
the constants, methods, and module variables
How they differ functionally?
Both add methods of the mixed-in module to the passed module (class). The difference is in the lookup order of these methods, in case that the target class already has them defined:
include behaves as if the target class inherited mixed-in module:
module FooBar
def say
puts "2 - Module"
end
end
class Foo
include FooBar
def say
puts "1 - Implementing Class"
super
end
end
Foo.new.say # =>
# 1 - Implementing Class
# 2 - Module
prepend makes the methods from the mixed in module "stronger" and executes them first:
module FooBar
def say
puts "2 - Module"
super
end
end
class Foo
prepend FooBar
def say
puts "1 - Implementing Class"
end
end
Foo.new.say # =>
# 2 - Module
# 1 - Implementing Class
The example kindly ripped off from here: http://blog.crowdint.com/2012/11/05/3-killer-features-that-are-coming-on-ruby-2-0.html
When to use append_features and when prepend_features?
Use prepend when you want to keep methods of the target module (class) at the end of the method lookup chain.
Some real-world examples can be found by searching SO for ruby, module and prepend:
Overriding method by another defined in module
When monkey patching a method, can you call the overridden method from the new implementation?
Ruby: Module, Mixins and Blocks confusing?
(Note: I am mentioning only methods, as they are easiest to picture when it comes to inheritance and mixing-in, but the same applies to other features.)
I thought to add it as a comment to a good answer which #Mladen Jablanovic has already made but I couldn't due to my low reputation point.
I've found a more concise, clearer and more descriptive answer on a post here - Ruby modules: Include vs Prepend vs Extend and I post it here just in case someone needs it and could get it with less effort.
Direct quotes:
Though include is the most common way of importing external code into a class, Ruby provides also two other ways to achieve that: extend and prepend. However, they don’t have the same behavior at all, and these differences are often misunderstood by Ruby developers.
To understand how to use them, we must first have a deeper look into how Ruby is resolving methods to execute at runtime, using something called the ancestors chain.
When a Ruby class is created, it holds a list of constant names which are its ancestors. They are all the classes that the class inherits from, and the modules they include. For example, by calling ancestors on the String class, we get the list of its ancestors:
String.ancestors
=> [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]
include is the most used and the simplest way of importing module code. When calling it in a class definition, Ruby will insert the module into the ancestors chain of the class, just after its superclass.
Available since Ruby 2, prepend is a bit less known to Rubyists than its two other friends. It actually works like include, except that instead of inserting the module between the class and its superclass in the chain, it will insert it at the bottom of the chain, even before the class itself.
I would suggest reading the post to get a better understanding as it comes with examples.
Related
I was having trouble understanding an error while unit testing my module, which is a mixin.
Suppose the mixin to be tested is module A:
require 'path/b'
module A
def methodA()
puts methodB.attr1
end
end
And it depends on another mixin B which was defined in a file at path/b.rb
module B
def methodB
return someObject #that has property 'attr1'
end
end
Now, we have a class to unit test module A
require 'path/moduleA'
class TestA
include Path::moduleA
end
describe 'test moduleA.methodA'
it 'does something'
testObject = TestA.new
testObject.methodA()
expect(....)
end
end
I get following error on running the rspec test
NameError:
undefined local variable or method `methodB' for #<TestA:0x00007f77a03db9a8>
I am able to resolve it by one of following ways:
including module B in module A
including module B in class TestA
Questions
I am not clear why include is required to get access to methodB in
module A and class TestA when 'require' was already added in module A.
My intention is to use methods of module B in module A, but not let users of module A access module B methods automatically.
resolution 1 above gives users of A, access to B's methods
resolution 2 forces users of A (user -> the unit test class in this example) to include A's dependency B directly, even though user is only interested in accessing A's methods.
Hence, both resolutions don't achieve what I want. Is there a way to achieve it?
I'm new to Ruby so may be it doesn't support this. I'm from Java background where I would model A and B as two classes, make an instance of B as field of A, then expose A's own public methods to users of A. But since they are mixins, I need to use modules in ruby.
Just to be very explicit: require / require_relative / load and include / extend / prepend have absolutely nothing whatsoever to do with each other.
The former three simply run a Ruby file. That's it. That is all they do. They differ in how and where they search for the file, but after they found the file, they don't do anything else than just execute it.
The latter three add a module to the ancestor chain. include essentially makes the module the superclass, extend is really the same as singleton_class.include (i.e. makes the module the superclass of the singleton class), and prepend inserts the module at the beginning of the ancestor's chain, i.e. actually before the class that it is prepended to.
require just tells ruby to read / load the code inside the ruby file. In this case it will just define the module. However in order for code inside a module to be included inside another module or class, you must include it inside the module or class. So you should just as you mentioned do:
require 'path/b'
module A
include B
def methodA()
puts methodB.attr1
end
end
You should not need to change your test with this since module A already includes module B. However this is not a very good OOP design pattern here. But hopefully you understand why now.
After more googling, I found the answer to my 2nd question using suggestion from:
https://makandracards.com/makandra/977-calling-selected-methods-of-a-module-from-another-module
so basically i did:
require 'path/b'
module A
module B_RequiredMethods
include Path::B
module_function :methodB
end
def methodA
puts B_RequiredMethods.methodB.attr1
end
end
In my case, B_RequiredMethods could be named properly to represent the method of B which would be exposed by it. Ideally, I would make those methods class level methods of B, but it is managed by some other team.
My understanding is that, when a module is included into a class, a copy of the module is made and put between the including class and its superclass.
Let me quote from Ruby Under a Microscope by Pat Shaughnessy. Suppose that you have the following:
module Professor
end
class Mathematician < Person
include Professor
end
When we run the above code, Ruby creates a copy of the RClass structure for the Professor module and uses it as the new superclass for Mathematician. Ruby's C source code refers to this copy of the module as an included class. The superclass of the new copy of Professor is set to the original superclass of Mathematician, which preserves the superclass, or ancestor chain.
Is it possible to get a reference to the included class? For example, I want to get a reference to the Kernel module included in the Object class.
My understanding is that, when a module is included into a class, a
copy of the module is made and put between the including class and its
superclass.
From a Ruby point of view, no copy is made. A reference is added to the ancestors, and that's it.
The behaviour described in your question (extracted from "Ruby under a microscope") is probably specific to CRuby. Internally, a Ruby Module is saved as a modified RClass, and a copy is made when the Module is included. It doesn't seem to be the case in Rubinius for example. I also don't think it's possible to access the copied, internal RClass referencing the included Module from Ruby.
You can check the Ruby behaviour this way :
module M
def copy_or_reference?
puts "copy!"
end
end
class A
include M
end
class B
include M
end
m2 = A.included_modules.first
m2.send(:define_method, :copy_or_reference?) { puts "reference!" }
B.new.copy_or_reference?
#=> reference!
We extract M module from A's ancestors. We redefine the copy_or_reference? method in this ancestor module. If it were a copy of the original M module, M#copy_or_reference?, as called from a B instance, would still return "copy!".
To get the included modules, you could also use:
A.ancestors.grep_v(Class)
in Ruby 2.3+ or
A.ancestors.reject{ |o| o.is_a?(Class) }
in older versions.
If you want more information, you could try to ping #JörgWMittag.
Lets look at this with a sample:
module Bar
end
class Foo
include Bar
end
p Foo.ancestors
p Foo.included_modules
This will print
[Foo, Bar, Object, Kernel, BasicObject]
[Bar, Kernel]
Object and BasicObject are in the ancestor hierarchy because, even without specifying it, Foo extends Object (and Object extends 'BasicObject', at least since Ruby 1.9+ where BasicObject was introduced).
Bar and Kernel are included Modules because Foo includes Bar directly and Object includes Kernel.
But the Module is not copied. It is simply referenced and used when looking up methods.
You can find some more details here: http://ruby-doc.com/docs/ProgrammingRuby/html/tut_modules.html
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).
In Ruby, since you can include multiple mixins but only extend one class, it seems like mixins would be preferred over inheritance.
My question: if you're writing code which must be extended/included to be useful, why would you ever make it a class? Or put another way, why wouldn't you always make it a module?
I can only think of one reason why you'd want a class, and that is if you need to instantiate the class. In the case of ActiveRecord::Base, however, you never instantiate it directly. So shouldn't it have been a module instead?
I just read about this topic in The Well-Grounded Rubyist (great book, by the way). The author does a better job of explaining than I would so I'll quote him:
No single rule or formula always results in the right design. But it’s useful to keep a
couple of considerations in mind when you’re making class-versus-module decisions:
Modules don’t have instances. It follows that entities or things are generally best
modeled in classes, and characteristics or properties of entities or things are
best encapsulated in modules. Correspondingly, as noted in section 4.1.1, class
names tend to be nouns, whereas module names are often adjectives (Stack
versus Stacklike).
A class can have only one superclass, but it can mix in as many modules as it wants. If
you’re using inheritance, give priority to creating a sensible superclass/subclass
relationship. Don’t use up a class’s one and only superclass relationship to
endow the class with what might turn out to be just one of several sets of characteristics.
Summing up these rules in one example, here is what you should not do:
module Vehicle
...
class SelfPropelling
...
class Truck < SelfPropelling
include Vehicle
...
Rather, you should do this:
module SelfPropelling
...
class Vehicle
include SelfPropelling
...
class Truck < Vehicle
...
The second version models the entities and properties much more neatly. Truck
descends from Vehicle (which makes sense), whereas SelfPropelling is a characteristic of vehicles (at least, all those we care about in this model of the world)—a characteristic that is passed on to trucks by virtue of Truck being a descendant, or specialized
form, of Vehicle.
I think mixins are a great idea, but there's another problem here that nobody has mentioned: namespace collisions. Consider:
module A
HELLO = "hi"
def sayhi
puts HELLO
end
end
module B
HELLO = "you stink"
def sayhi
puts HELLO
end
end
class C
include A
include B
end
c = C.new
c.sayhi
Which one wins? In Ruby, it turns out the be the latter, module B, because you included it after module A. Now, it's easy to avoid this problem: make sure all of module A and module B's constants and methods are in unlikely namespaces. The problem is that the compiler doesn't warn you at all when collisions happen.
I argue that this behavior does not scale to large teams of programmers-- you shouldn't assume that the person implementing class C knows about every name in scope. Ruby will even let you override a constant or method of a different type. I'm not sure that could ever be considered correct behavior.
My take: Modules are for sharing behavior, while classes are for modeling relationships between objects. You technically could just make everything an instance of Object and mix in whatever modules you want to get the desired set of behaviors, but that would be a poor, haphazard and rather unreadable design.
The answer to your question is largely contextual. Distilling pubb's observation, the choice is primarily driven by the domain under consideration.
And yes, ActiveRecord should have been included rather than extended by a subclass. Another ORM - datamapper - precisely achieves that!
I like Andy Gaskell's answer very much - just wanted to add that yes, ActiveRecord should not use inheritance, but rather include a module to add the behavior (mostly persistence) to a model/class. ActiveRecord is simply using the wrong paradigm.
For the same reason, I very much like MongoId over MongoMapper, because it leaves the developer the chance to use inheritance as a way of modelling something meaningful in the problem domain.
It's sad that pretty much nobody in the Rails community is using "Ruby inheritance" the way it's supposed to be used - to define class hierarchies, not just to add behavior.
The best way I understand mixins are as virtual classes. Mixins are "virtual classes" that have been injected in a class's or module's ancestor chain.
When we use "include" and pass it a module, it adds the module to the ancestor chain right before the class that we are inheriting from:
class Parent
end
module M
end
class Child < Parent
include M
end
Child.ancestors
=> [Child, M, Parent, Object ...
Every object in Ruby also has a singleton class. Methods added to this singleton class can be directly called on the object and so they act as "class" methods. When we use "extend" on an object and pass the object a module, we are adding the methods of the module to the singleton class of the object:
module M
def m
puts 'm'
end
end
class Test
end
Test.extend M
Test.m
We can access the singleton class with the singleton_class method:
Test.singleton_class.ancestors
=> [#<Class:Test>, M, #<Class:Object>, ...
Ruby provides some hooks for modules when they are being mixed into classes/modules. included is a hook method provided by Ruby which gets called whenever you include a module in some module or class. Just like included, there is an associated extended hook for extend. It will be called when a module is extended by another module or class.
module M
def self.included(target)
puts "included into #{target}"
end
def self.extended(target)
puts "extended into #{target}"
end
end
class MyClass
include M
end
class MyClass2
extend M
end
This creates an interesting pattern that developers could use:
module M
def self.included(target)
target.send(:include, InstanceMethods)
target.extend ClassMethods
target.class_eval do
a_class_method
end
end
module InstanceMethods
def an_instance_method
end
end
module ClassMethods
def a_class_method
puts "a_class_method called"
end
end
end
class MyClass
include M
# a_class_method called
end
As you can see, this single module is adding instance methods, "class" methods, and acting directly on the target class (calling a_class_method() in this case).
ActiveSupport::Concern encapsulates this pattern. Here's the same module rewritten to use ActiveSupport::Concern:
module M
extend ActiveSupport::Concern
included do
a_class_method
end
def an_instance_method
end
module ClassMethods
def a_class_method
puts "a_class_method called"
end
end
end
Right now, I'm thinking about the template design pattern. It just wouldn't feel right with a module.
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