(Ruby,Rails) Context of Self in Modules and Libraries...

(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



Leave a reply



Submit