(Ruby,Rails) Context of SELF in modules and libraries...?
In a module:
When you see self
in an instance method, it refers to the instance of the class in which the module is included.
When you see self
outside of an instance method, it refers to the module.
module Foo
def a
puts "a: I am a #{self.class.name}"
end
def Foo.b
puts "b: I am a #{self.class.name}"
end
def self.c
puts "c: I am a #{self.class.name}"
end
end
class Bar
include Foo
def try_it
a
Foo.b # Bar.b undefined
Foo.c # Bar.c undefined
end
end
Bar.new.try_it
#>> a: I am a Bar
#>> b: I am a Module
#>> c: I am a Module
Can someone please explain class self to me?
In Ruby, class << foo
opens up the singleton class of the object referenced by foo
. In Ruby, every object has a singleton class associated with it which only has a single instance. This singleton class holds object-specific behavior, i.e. singleton methods.
So, class << self
opens up the singleton class of self
. What exactly self
is, depends on the context you are in, of course. In a module or class definition body, it is the module or class itself, for example.
If all you are using the singleton class for, is defining singleton methods, there is actually a shortcut for that: def foo.bar
.
Here's an example of how to use singleton methods to provide some "procedures" which don't really have any association with a particular instance:
class << (Util = Object.new)
def do_something(n)
# ...
end
end
Util.do_something(n)
To use self. or not.. in Rails
def self.method_name
end
defines a class method.
def method_name
end
defines an instance method.
This is a pretty good post on it.
Difference between a class and a module
The first answer is good and gives some structural answers, but another approach is to think about what you're doing. Modules are about providing methods that you can use across multiple classes - think about them as "libraries" (as you would see in a Rails app). Classes are about objects; modules are about functions.
For example, authentication and authorization systems are good examples of modules. Authentication systems work across multiple app-level classes (users are authenticated, sessions manage authentication, lots of other classes will act differently based on the auth state), so authentication systems act as shared APIs.
You might also use a module when you have shared methods across multiple apps (again, the library model is good here).
ActiveRecord::Migration prepend context and method
ActiveRecord::Migration.method_missing
(on class level) calls nearest_delegate
that seems to be an instance of ActiveRecord::Migration
> ActiveRecord::Migration.nearest_delegate
=> #<ActiveRecord::Migration:0x0000561889aa1930 @connection=nil, @name="ActiveRecord::Migration", @version=nil>
When you call ActiveRecord::Migration.prepend MyLibrary::Mutators
you prepend instance methods of ActiveRecord::Migration
with MyLibrary::Mutators
. so do_something
is defined on an migration instance.
When you call:
class Test < ActiveRecord::Migration[5.2]
do_something
# ...
end
Test.method_missing
is called, it calls #do_something
on nearest_delegate
that appears to be ActiveRecord::Migration
instance.
If you want to have do_something
really defined on migration class level, you need to properly prepend class methods. It is described precisely in answers to this question.
Long story short, you should call .prepend
in migration singleton class, not on migration class:
ActiveSupport.on_load(:active_record) do
ActiveRecord::Migration.singleton_class.prepend MyLibrary::Mutators
end
How do you list the currently available objects in the current scope in ruby?
ObjectSpace.each_object could be what you are looking for.
To get a list of included modules you could use Module.included_modules.
You can also check if an object responds to a method on a case-by-case basis using object.respond_to?.
Where should I place my own module within rails application?
Rails < 5
Before Rails 5, the place to put reusable code such as this is in the lib
directory. However you do not need to require
anything as lib
is already in the load path and it's contents will be loaded during initialization.
If you need to extend an existing class, you define your module first and then include it by sending it as a message to the class you wish to extend, e.g.
module MyExtensions
def self.included base
base.instance_eval do
def my_new_method
…
end
end
end
end
ActiveRecord::Base.send :include, MyExtensions
What are the practical differences between a module method and a class method in Ruby?
tl;dr: There are no class methods and module methods in Ruby, only instance methods. Considering that they are both just instance methods, and thus the same thing, there cannot possibly be any difference.
There is no such thing as a "class method" or a "module method" in Ruby. Ruby has exactly one kind of method: instance methods.
We sometimes use the word "class method" or "module method" out of convenience when talking about a certain pattern of using instance methods, but there is no such concept in Ruby. "Class methods" and "module methods" are really just singleton methods of an object which just happens to be an instance of the Module
class or the Class
class. There is absolutely no difference whatsoever between a singleton method of an object which happens to be an instance of Class
, Module
, String
, Array
, Hash
, Object
, Foo
, Bar
, Whatever
, or Garbledigookidoo
.
Oh. Did I mention? Singleton methods don't exist, either. Again, it is a word we use for certain kinds of usages of methods, but they are really just regular boring old instance methods of the singleton class of an object.
However, "instance method of the singleton class of foo
" and "instance method of the singleton class of Foo
, where Foo
is an instance of Class
" are really long, and so we shorten them to "singleton method of foo
" and "class method of Foo
" out of convenience, knowing full well that those are fictions that don't actually exist in the language.
Unlike Java, which has three different kinds of methods (instance methods, static methods, and constructors (which are kinda-sorta like methods)), Ruby has exactly one kind of method: instance methods. No class methods, no module methods, no global methods, no top-level methods, no static methods, no constructors. It does, however, have three kinds of classes: regular classes, singleton classes, and include classes (the latter being classes that get synthesized and injected into the inheritance hierarchy when you call include
or prepend
). These classes differ mainly in whether methods like Object#class
, Class#superclass
, and Class#ancestors
display them or suppress them. Singleton classes are suppressed by all of them, include classes by the first two, but shown by ancestors
.
class self idiom in Ruby
First, the class << foo
syntax opens up foo
's singleton class (eigenclass). This allows you to specialise the behaviour of methods called on that specific object.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Now, to answer the question: class << self
opens up self
's singleton class, so that methods can be redefined for the current self
object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module ("static") methods:
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
This can also be written as a shorthand:
class String
def self.value_of obj
obj.to_s
end
end
Or even shorter:
def String.value_of obj
obj.to_s
end
When inside a function definition, self
refers to the object the function is being called with. In this case, class << self
opens the singleton class for that object; one use of that is to implement a poor man's state machine:
class StateMachineExample
def process obj
process_hook obj
end
private
def process_state_1 obj
# ...
class << self
alias process_hook process_state_2
end
end
def process_state_2 obj
# ...
class << self
alias process_hook process_state_1
end
end
# Set up initial state
alias process_hook process_state_1
end
So, in the example above, each instance of StateMachineExample
has process_hook
aliased to process_state_1
, but note how in the latter, it can redefine process_hook
(for self
only, not affecting other StateMachineExample
instances) to process_state_2
. So, each time a caller calls the process
method (which calls the redefinable process_hook
), the behaviour changes depending on what state it's in.
Related Topics
How to Create a Full Audit Log in Rails for Every Table
Modify Ruby Hash in Place( Rails Strong Params)
Case-Insensitive Array#Include
Eager Loading: the Right Way to Do Things
Install Bundler Gem Using Ansible
How to Remove a Substring After a Certain Character in a String Using Ruby
Ruby Koan: Constants Become Symbols
Ror + Unable to Install Tiny_Tds
-%>' (Minus Sign) at the End of a Erb Sequence
Ruby/Rails: Convert Int to Time or Get Time from Integer
Which Algorithm Does Ruby's Sort Method Use
How to Set an Option as Selected Using Selenium Webdriver (Selenium 2.0) Client in Ruby
Rake Assets:Precompile Attempting to Connect to Database