Not understanding Classes, Modules, and the class << self method - ruby-on-rails

I have the following code:
class MyClass
module MyModule
class << self
attr_accessor :first_name
def myfunction
MyModule.first_name = "Nathan"
end
end
end
end
When I call the method myfunction like so, it works fine:
> me = MyClass::MyModule.myfunction
=> "Nathan"
> me
=> "Nathan"
But if I removed the class << self and add a self. prefix to myfunction, it doesn't work.
For example:
class MyClass
module MyModule
attr_accessor :first_name
def self.myfunction
MyModule.first_name = "Nathan"
end
end
end
> me = MyClass::MyModule.myfunction
NoMethodError: undefined method `first_name=' for MyClass::MyModule:Module
I'm trying to understand the class << self method. I thought it was a way add the self. prefix to the all the methods inside of it, but if that was true, why doesn't it work if I remove it and prefix each method with self. manually?
Thanks in advance for your help.

This is because your attr_accessor :first_name is also wrapped by the class << self.
To do it the way you suggest, you can use mattr_accessor like so:
require 'active_support'
class MyClass
module MyModule
mattr_accessor :first_name
def self.myfunction
MyModule.first_name = "Nathan"
end
end
end

To better understand how you can achieve what you want, take a look at the following example:
module PrintingModule
def self.included(object)
object.extend(ClassMethods)
end
module ClassMethods
def class_method_of_class
puts "I am class #{self.name}"
end
end
def instance_method_of_class
puts "My name is: #{#name}"
end
class << self
def static_module_method
puts "Printer version 1.0"
end
end
end
class SomeObject
include PrintingModule
def initialize(name)
#name = name
end
end
object = SomeObject.new("Something")
object.instance_method_of_class
SomeObject.class_method_of_class
PrintingModule.static_module_method
I hope it's more clear now, note that this is just one of possible way (there are others)
UPDATE:
I'll try to be more specific. When you define instance/singleton methods on module, what you are really doing is that you are defining instance methods of class which will include that module and on the other hand, class methods defined on module will become class methods of that module. The second think to know is that attr_accessor creates instance method for getter and setter of the given parameter.
Now to answer one part of your question, in the first example you are creating 3 class methods on module's class. In the second one, you are creating 1 class method where you are trying to access another class method (setter), but your getters and setters are defined as instance methods = they will become instance of method of class which will include your module, you cannot get to them this way = you have no access to your getters and setters.
As for explanation of self, well I'm not that skilled, but as far as I know, when you use "class << self" you are opening eigenclass (each object has it's own anynonymous one) of the object (note that Class, modules or instances of classes are of course objects too) where you are defining instance methods. Class method of object in Ruby = instance method of the eigenclass of the object. So you can do this for example:
text = "something"
class << text
def say_hi
puts "Hi!"
end
end
text.say_hi
When you create instance of class (String in that example), that instance gets it's own unique anonymous class which is subclass of that Class. In the example, you have defined instance method on the eigenclass of the anonymous subclass of String class. So you can use method "say_hi" on the text object but not on the String class. So "class << self" is opening those eigenclasses.
On the other hand, "self" alone just represents an object in the current context, which means the same in some scenarios (for example yours). As for self.included method, it is just a callback method which gets called when the module is included in the class with a parameter representing the object (here class SomeObject).
I hope that I have answered at least part of your question.
More information here:
Difference between 'self.method_name' and 'class << self' in Ruby

Related

What is the 'self' keyword doing exactly in this Class method?

class Restaurant
attr_accessor :average_rating, :city
def initialize(city, name)
#city = city
#name = name
#number_of_ratings = 0
#sum_of_ratings = 0
end
def rate(new_rate)
#number_of_ratings += 1
#sum_of_ratings += new_rate
#average_rating = #sum_of_ratings.to_f / #number_of_ratings
end
def self.filter_by_city(restaurants, city)
restaurants.select { |restaurant| restaurant.city == city }
end
end
The above code is part of a challenge and I kept failing the tests for the #filter_by_city method. I checked the solution and the only difference was the self. prior to the method name. I've tried to understand what self does exactly but it's difficult to understand without context. In this particular class method, what exactly is self doing? I know what the body of the method is doing i.e. the filtering of the restaurants by city, but how does it run exactly?
self is the class Restaurant. def self.method is how you implement a method on the class itself rather than an instance of the class. Restaurant.filter_by_city(...) rather than Restaurant.new.filter_by_city(...).
self changes in Ruby depending on context. Within a method, self is the object the method was called on.
Within the class Restaurant block, and outside of any method, self is the Restaurant object which is a Class object. Everything is an object in Ruby. Everything.
You can also do this by declaring a block where the class is the instance.
class << self
def filter_by_city(restaurants, city)
restaurants.select { |restaurant| restaurant.city == city }
end
end
Normally you'd use this syntax if you have a lot of class methods.
See Self in Ruby: A Comprehensive Overview for more.
When defining a method in ruby you can optionally explicitly define that method's receiver using def <receiver>.<method> syntax instead of plain def <method>
object = Object.new
def object.foo
:foo
end
object.foo #=> foo
The receiver must either be a singular reference OR an expression (but it must be enclosed by brackets):
a = [Object.new, Object.new]
def (a.first).foo
:foo
end
def (a[1]).bar
:bar
end
a[0].foo #=> :foo
a.last.bar #=> :bar
a.first.bar #=> undefined method
When receiver is defined, the method is defined directly on the receiver's singleton class, ignoring the context in which the method is defined:
class A
o = Obejct.new
def o.foo
end
end
A.new.foo #=> undefined method
Even though method foo was defined in class A body, it is not available to its instances because of the explicit receiver
self is a ruby keyword returning the current "context". Inside the methods, self is (usually) a receiver of the call, and inside the module self returns that module. So:
module Wrapper
module SomeModule
puts self.name
end
end
will print Wrapper::SomeModule.
This means that:
class A
def self.foo
end
end
Is exactly the same as:
class A
def A.foo
end
end
So, the method is defined directly on A and can only be called directly on the class as A.foo, rather than on its instances.

ruby monkey patching on the fly

Is there a way to implement monkey patching while an object is being instantiated?
When I call:
a = Foo.new
Prior to the instance being instantiated, I would like to extend the Foo class based on information which I will read from a data store. As such, each time I call Foo.new, the extension(s) that will be added to that instance of the class would change dynamically.
tl;dr: Adding methods to an instance is possible.
Answer: Adding methods to an instance is not possible. Instances in Ruby don't have methods. But each instance can have a singleton class, where one can add methods, which will then be only available on the single instance that this singleton class is made for.
class Foo
end
foo = Foo.new
def foo.bark
puts "Woof"
end
foo.bark
class << foo
def chew
puts "Crunch"
end
end
foo.chew
foo.define_singleton_method(:mark) do
puts "Widdle"
end
foo.mark
are just some of the ways to define a singleton method for an object.
module Happy
def cheer
puts "Wag"
end
end
foo.extend(Happy)
foo.cheer
This takes another approach, it will insert the module between the singleton class and the real class in the inheritance chain. This way, too, the module is available to the instance, but not on the whole class.
Sure you can!
method_name_only_known_at_runtime = 'hello'
string_only_known_at_runtime = 'Hello World!'
test = Object.new
test.define_singleton_method(method_name_only_known_at_runtime) do
puts(string_only_known_at_runtime)
end
test.hello
#> Hello World!
Prior to the instance being instantiated, I would like to extend
Given a class Foo which does something within its initialize method:
class Foo
attr_accessor :name
def initialize(name)
self.name = name
end
end
And a module FooExtension which wants to alter that behavior:
module FooExtension
def name=(value)
#name = value.reverse.upcase
end
end
You could patch it via prepend:
module FooPatcher
def initialize(*)
extend(FooExtension) if $do_extend # replace with actual logic
super
end
end
Foo.prepend(FooPatcher)
Or you could extend even before calling initialize by providing your own new class method:
class Foo
def self.new(*args)
obj = allocate
obj.extend(FooExtension) if $do_extend # replace with actual logic
obj.send(:initialize, *args)
obj
end
end
Both variants produce the same result:
$do_extend = false
Foo.new('hello')
#=> #<Foo:0x00007ff66582b640 #name="hello">
$do_extend = true
Foo.new('hello')
#=> #<Foo:0x00007ff66582b280 #name="OLLEH">

No method error for class variable defined with attr_accessor

I want to define methods dynamically using an array of strings.
Here is a simple piece of code that should achieve that.
class SomeClass
attr_accessor :my_array
def initialize(user, record)
#my_array=[]
end
my_array.each do |element|
alias_method "#{element}?".to_sym, :awesome_method
end
def awesome_method
puts 'awesome'
end
end
When I instantiate this class in the console, I get the following error
NoMethodError (undefined method `each' for nil:NilClass)
What is wrong with this code and how to make it work. any help highly appreciated :)
Edit 1:
What I ultimately want to achieve is to inherit from SomeClass and override my_array in the child class to dynamically define methods with its attributes like so
class OtherClass < SomeClass
my_array = %w[method1 method2 method3]
# Some mechanism to over write my_array.
end
And then use self.inherited to dynamically define methods in child class.
Is there a good way to achieve this?
In your code, you use an instance variable (#my_array) and an attr_accessor over it, and then try to access my_array from class level (that is, from the body of the class definition, outside of any methods). But instance variables only exist at instance level, so it is not available in the class scope.
One solution (the natural one, and the one which you would probably use in other languages) is to use a class variable: ##my_array. But class variables in ruby are a little problematic, so the best solution would be to make use of class instance variables, like that:
class SomeClass
class << self
attr_accessor :my_array
end
#my_array=[]
def initialize(user, record)
end
#my_array.each do |element|
alias_method "#{element}?".to_sym, :awesome_method
end
def awesome_method
puts 'awesome'
end
end
The syntax is a little tricky, so, if you look that up and it still doesn't makes sense, try just reading about scopes and using a regular class variable with ##.
Edit:
Ok, so, after your edit, it became more clear what you are trying to accomplish. A full working example is like follows:
class SomeClass
class << self
attr_accessor :my_array
end
#my_array=[]
def awesome_method
puts 'awesome'
end
def self.build!
#my_array.each do |element|
self.define_method("#{element}?".to_sym){ awesome_method }
end
end
end
class ChildClass < SomeClass
#my_array = %w[test little_test]
self.build!
end
child_instance = ChildClass.new
child_instance.test?
>> awesome
child_instance.little_test?
>> awesome
So, I've made some tweaks on SomeClass:
It does not need an initialize method
I tried to use the inherited hook for this problem. It won't ever work, because this hook is called as soon as "ChildClass < SomeClass" is written, and this must be before you can define something like #my_array = %w[test little_test]. So, I have added a self.build! method that must be called in the child instances so that they build their methods from my_array. This is inevitable, but I think it is also good, because it makes more explicit in the subclasses that you are doing something interesting there.
I think you want "define_method", not "alias_method".
awesome_method in passed in a block, which is ruby's way of doing functional programming.
With that done, ChildClass inherits from SomeClass, and it's instances have the dynamically created methods 'test?' and 'little_test?'.
You need to change my_array to class level accessible, in my case class constant.
class SomeClass
DYNAMIC_METHOD_NAMES = %w(method_a method_b method_C).freeze
def initialize(user, record)
end
DYNAMIC_METHOD_NAMES.each do |element|
alias_method "#{element}?".to_sym, :awesome_method
end
def awesome_method
puts 'awesome'
end
end

If self points to the klass object in ruby, why is it used as assignment in ActiveRecord?

Note: This was the best title I could think of that wouldn't make this question seem like a dup. Please feel free to edit if it does not capture the point of the question
So I've been reading Advanced Rails and I had a question that wasn't fully answered by these posts:
When to use `self.foo` instead of `foo` in Ruby methods
In Ruby. How do I refer to the class from within class << self definition?
Why use "self" to access ActiveRecord/Rails model properties?
In my understanding, within a class definition, self refers to the object referenced by the pointer klass, so for the example of an eigenclass:
class A
class << self
def to.s
"Woot"
end
end
end
is the exact same as:
class << A
def to.s
"Woot"
end
end
This is because as you open up the class, ruby is creating a Class:A (virtual) class and assigning A's klass pointer to it. To my understanding this means that within the context of this class definition self == A
My question is (assuming my understanding as I've described it above is accurate) why then in an ActiveRecord::Base subclass in Rails does the use of self seem to be merely a disambiguation of the instance and not the class itself?
For example, if I have a class: A < ActiveRecord::Base with an attribute name, I cannot call A.name = "blah" outside the class definition. However, I CAN use ( and indeed MUST use ) self in assignment within the class definition like so: self.name = "blah".
If the use of self in Ruby refers to the Class object and not the instance, why does this work in ActiveRecord and how does Rails make the distinction?
Everything is a method
Anything you do with an object is a method. When you have a class like this:
class A
attr_accessor :foo
end
obj = A.new
obj.foo = 3
obj.foo #=> 3
It might feel weird, but you didn't make any assignment here. obj.foo = 3 is only a synthatic sugar for obj.send(:foo=, 3) so in fact, it executes foo= method. obj.foo is a method as well, it simply returns a value. This is because all the instance variables are private, and there is no other way to interact with them than inside the method. attr_accessor :foo is just a shortcut for:
def foo=(value)
#foo = value
end
def foo
#foo
end
Now, when ruby see any identifier like foo, it needs to find out what it is. Firstly it assumes it is a local variable, and if not, it tries to execute it as method on current self (see below). This means that:
class A
attr_accessor :foo
def bar
foo = 'bar'
end
end
a = A.new
a.bar #=> 'bar'
a.foo #=> nil
What happened? Interpretor first uses foo as an instance variable, it is not defined. But there is an assignment next to it, so it defines a new instance variable and make an assignment. If we want to use our setter we need to tell interpreter that it is not an instance varible:
class A
attr_accessor :foo
def bar
self.foo = 'bar'
end
end
a = A.new
a.bar #=> 'bar'
a.foo #=> 'bar'
I lied. Everything is an object
about self
self in ruby is very similar to this in javascript - it means different things in different context, and it can be easily changed at any point (obviously, not recommended).
First thing you need to know is that in Ruby every class is an object, namely it is an instance of class Class. When you do
class A
it is (almost, method below uses block and has access to external scope) equivalent to:
A = Class.new
self within a context of a class is always a class itself.
class A
self #=> A
def self.bar #=> this is class method
self #=> A
end
def foo #=> this is instance method
# We are no longer in context of class, but in context of the instance, hence
self #=> instance of A
end
end
Now, for any mutable object you can defined a singleton class. This is sort of weird concept - it is an extra subclass of the original class which only has a single instance. Since all the methods come from the class, this allows you to define extra methods on a particular instance of the method without affecting other object. In most of the cases, instance class is not needed and it is created when you access it for the first time. There are couple of ways to open it:
object.singleton_class do
self #=> instance class
end
class << object
self #=> instance class
end
Any method you defined within instance class is accessible only on that particular instance, hence this:
class A
self #=> A
class << A
# we are now in the instance class of A (which is an instance of Class class)
def foo
# So this is an instance method, however our instance is a class A
self #=> A
end
end

what does "class << self" mean in Rails? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
class << self idiom in Ruby
Can someone please explain class << self to me?
I would like to know what does class << self statement mean in a model class? And how does the statement inside it differ from those outside from it. For example:
class Post < ActiveRecord::Base
class << self
def search(q)
# search from DB
end
end
def search2(qq)
# search from DB
end
end
What does class << self mean?
What are the differences between method search(q) and search2(qq) ?
That is the same as
class Post < ActiveRecord::Base
def self.search(q)
# Class Level Method
# search from DB
end
def search2(qq)
# Instance Level Method
# search from DB
end
end
Class methods work on the class (e.g. Post), instance methods works on instances of that class (e.g. Post.new)
Some people like the class << self; code; end; way because it keeps all class level methods in a nice block and in one place.
Others like to prefix each method with self. to explicitly know that is a class method not an instance method. It's a matter of style and how you code. If you put all class methods in a block like class << self, and this block is long enough, the class << self line might be out of your editor view making it difficult to know that you are in the class instance block.
On the other hand, prefixing each method with self. and intermixing those with instance methods is also a bad idea, how do you know all the class methods while reading your code.
Pick an idiom which you prefer for your own code base but if you work on an open source project or you collaborate on someone else's code, use their code formatting rule.
It creates class methods as opposed to instance methods. It's the same as doing def self.search(q). Those two methods would be called like:
Post.search(q)
Post.new.search(qq)
search2 is an instance-method while search is a class-method. The class << self syntax enables you to group class methods below. There are three ways of defining class methods in Ruby:
class MyClass
def self.method
# do sth.
end
def MyClass.method2
# do sth.
end
class << self
def method3
# do sth.
end
def another_class_method
# do sth.
end
end
end
Class-methods are called on a class, not on an instance. It is personal preference which of the three idioms you want to use. I prefer def self.method for no particular reason.

Resources