Making a module inherit from another module in Ruby
In fact you can define a module inside of another module, and then include it within the outer one.
so ross$ cat >> mods.rb
module ApplicationHelper
module Helper
def time
Time.now.year
end
end
include Helper
end
class Test
include ApplicationHelper
def run
p time
end
self
end.new.run
so ross$ ruby mods.rb
2012
How Can I Inherit a Ruby Module to Create Another Module?
You can just include module WithReviews in module Reviewable.
module WithReviews
def getReviews;end
end
module Reviewable
include WithReviews
def createReview;end
end
Making a module pre-include another (module inheritance) ruby
The answer is present in a duplicate question, though I didn't see it at first:
module XMLBacked
include FileBacked
# other XMLBacked methods here
end
This causes FileBacked
to be injected into the lookup chain before XMLBacked
whenever XMLBacked
it is included.
inheritance from multiple modules?
To help you understand that, ruby provides you with Module#ancestors
:
Object.ancestors # => [Object, Kernel, BasicObject]
This is the order, in which an instance method of Object
will be searched for. So lets test your examples.
First, two modules included:
module M; end
module N; end
class C
include M
include N
end
C.ancestors # => [C, N, M, Object, Kernel, BasicObject]
So the methods will first be searched for in C
. If a method with the given name is not found, it is searched for first in N
and then in M
. In other words - the reverse order of which you included the modules.
Second, module, including a module, included in a class:
module X; end
module Y
include X
end
class K
include Y
end
K.ancestors # => [K, Y, X, Object, Kernel, BasicObject]
So we can see that the same rule applies for including in modules. Just as in the previous example a method will first be searched for in C
and only then in the modules included in C
, here a method will first will be searched for in a module, and only then in the included modules in that module.
The reason for that, other than consistency, is that classes are actually modules in Ruby:
Class.superclass # => Module
There are a lot of rules. For example including the same module twice in the hierarchy, singleton classes, #prepend
, #method_missing
and so on. But you can deduce all of it knowing how to use #ancestors
.
Inheriting from class Module
Module
is indeed a Ruby class. An instance of the class Module
is a Ruby module. To illustrate, these two ways of defining a module are equivalent:
module MyModule
# ...
end
# is equivalent to
MyModule = Module.new do
# ...
end
If an instance of Module
is a Ruby module, that means that an instance of any subclass of Module
is also a Ruby module, including Shrine::Attachment
. This makes sense, because we know that we can include
only modules, so an instance of Shrine::Attachment
has to be a module.
Because of Shrine's plugin system design, this:
class Attachment < Module
@shrine_class = ::Shrine
end
isn't the whole implementation of Shrine::Attachment
; the actual implementation is defined in the Shrine::Plugins::Base::AttachmentMethods
module, which gets included into Shrine::Attachment
.
If we look at the implementation of Shrine::Attachment.new
, we can see that it dynamically defines methods on itself based on the given attribute name. For example, Shrine::Attachment.new(:image)
will generate a module with the following methods defined: #image_attacher
, #image=
, #image
, and #image_url
. These methods will then get added to the model that includes that Shrine::Attachment
instance.
Why didn't I just have a method that creates a new module via Module.new
(like Refile does), instead of creating a whole subclass of Module
? Well, two main reasons:
First, this gives better introspection, because instead of seeing #<Module:0x007f8183d27ab0>
in your model's ancestors list, you now see an actual Shrine::Attachment
instance that points to its definition. You could still manually override #to_s
and #inspect
, but this is better.
Second, since Shrine::Attachment
is now a class, other Shrine plugins can extend it with more behaviour. So remote_url plugin adds the #<attachment>_remote_url
accessor, data_uri plugin adds the #<attachment>_data_uri
accessor etc.
Can a ruby class method inherit from another class?
class Users::PasswordsController < Devise::PasswordsController
...
end
In the above code, Users is the module and PasswordsController is the class inside Users module. Similarly Devise is the module and PasswordsController is the class inside Devise module.
so when you run
Users::PasswordsController.class
#=> Class
Users.class
#=>Module
Related Topics
Rails Routes: Get Without Param :Id
What Are the Steps Needed to Create and Publish a Rubygem of Your Own
How to Read a Gzip File Line by Line
Trying to Set Up Amazon's S3 Bucket: 403 Forbidden Error & Setting Permissions
Parsing Date from Text Using Ruby
Is There a Pry Debug Setup That Works with Ruby 2.0
Bundle Install/Error in Installing Libv8 (3.3.10.4) on Rails (Running on Lion)
Gem Which Cannot Find Gem Despite It Being Installed
Getting the Siblings of a Node with Nokogiri
Rails:Runtimeerror - Can't Modify Frozen Array When Running Rspec in Rails
Ruby Scope of Data After _End_
Split Seeds.Rb into Multiple Sections
Pg_Config, Ruby Pg, Postgresql 9.0 Problem After Upgrade, Centos 5
Clicking Link with JavaScript in Mechanize
How to Make Ruby's Restclient Gem Respect Content_Type on Post