What's the difference between self.generate and Invoice.generate? - ruby

class Invoice
def Invoice.generate(order_id, charge_amount, credited_amount = 0.0)
Invoice.new(:order_id => order_id, :amount => charge_amount, :invoice_type => PURCHASE, :credited_amount => credited_amount)
end
end
Why would you create Invoice.generate inside Invoice class rather than self.generate?

self.generate is easier to work with, whereas Invoice.generate is arguably more explicit. Other than that, there's no difference between the two.
Explanation
You can define a method on any instance using this form
def receiver.method(args)
end
Check this out
class Foo
end
def Foo.bar
"bar"
end
Foo.bar # => "bar"
And yes, I mean any instance. It's absolutely possible that one instance has some method while another doesn't
f = Foo.new
def f.quux
'quux'
end
f2 = Foo.new
f.quux # => "quux"
f2.quux # => # ~> -:20:in `<main>': undefined method `quux' for #<Foo:0x007fe4e904a6c0> (NoMethodError)
A reminder: inside of class definition (but outside of method definitions) self points to that class.
class Foo
# self is Foo
end
So, armed with this knowledge, the difference between self.generate and Invoice.generate should be obvious.

Under normal circumstances, it would practically have no difference from def self.generate.
The only edge case I can think of is if you have a nested class with the same name, then the explicit version would apply only to the nested class.
class A
def self.x
name
end
def A.y
name
end
class A
# nested class A::A
end
def self.p
name
end
def A.q
name
end
end
> A.x # => "A"
> A.y # => "A"
> A.p # => "A"
> A.q # => NoMethodError: undefined method `q' for A:Class
> A::A.q # => "A::A"
As you see, after a nested class with the same name is defined, subsequent explicit class method definitions made with the class name refer to the nested class, but explicit definitions made beforehand refer to the original.
Implicit definitions made with self always refer to the base class.

You have 2 ways for defining a class method.
1) You can use the name of the class directly
class Test #Test is now an instance of a built-in class named Class
def Test.class_method
"I'm a class method."
end
end
2) You can use the self variable, which is always pointing to the current object
class Test
def self.class_method
"I'm a class method."
end
end
Once you understand that classes are objects, this use of the self variable to define a class method finally makes sense.
The value of self
Not too surprinsingly, when you are inside a class method, the value of self refers to the object that holds the class structure (the instance of class Class). This means that :
class Test
def self.class_method
self.x
end
end
is equivalent to :
class Test
def self.class_method
Test.x
end
end
When you are inside an instance method, the value of self still refers to the current object. This time however, the current object is an instance of class Test, not an instance of class Class.
More info. : http://www.jimmycuadra.com/posts/self-in-ruby

Related

Is there to shorten `def self.method_name` and `def method_name` into one method?

So say I have this class:
class This
def a(that)
puts that
end
def self.b(that)
puts that
end
end
This.b("Hello!") # => passes
This.a("Hello!") # => fails
the_class = This.new()
the_class.b("Hello!") # => fails
the_class.a("Hello!") # => passes
Is there a way to shorten both of those methods into one method that is able to be called on a uninitialized object, AND is able to be called on an already initialized one, or will I always have to write a method like that twice?
You can extract the functionality into a module and both extend and include it.
module A
def a(that)
puts that
end
end
class This
include A # defines instance methods
extend A # defines class methods
end
This.a("foo") # => "foo"
This.new.a("foo") # => "foo"
Although I think it's more common to either include or extend and not both. The reason being that instance methods often depend on instance state, whereas class methods don't. If you have an instance This.new and want to call a class method, you can use .class i.e. This.new.class.a
The following bit of code uses some metaprogramming tricks to auto copy over any class methods to instances of that class.
module AutoAddMethods
def singleton_method_added(symbol)
define_method(symbol, method(symbol).to_proc)
end
end
class Foo
extend AutoAddMethods
#bar = 39
def initialize
#bar = 42
end
def test_one # Only added as an instance method.
puts "One #{#bar.inspect}"
end
def self.test_two # Added as both an instance and class method.
puts "Two #{#bar.inspect}"
end
end
i = Foo.new
i.test_one
i.test_two
Foo.test_two
And here is my test run output:
One 42
Two 39
Two 39
The test_two method is callable from both the class and its instances. It runs as if in the class.

What is the difference between `Class` and `class`

While creating a class, we use the keyword class like:
class Abc
Z = 5
def add
puts "anything here"
end
end
In console, Abc.class # => Class
How does Abc internally become a class? What is the difference between class and Class?
It would be great if anyone could explain how class constants and method are internally called, and if a method is not defined, then how we get the exception "undefined class method". What is the internal logic behind it?
There are three different things here:
class is a keyword, which is used to define or reopen a class
Object#class is a method, which returns the class of a given object
Class is the class which all classes are an instance of (including Class itself)
ndn's answer gives a nice overview of the different things "class" could refer to.
To answer your specific question:
How does Abc internally become a class?
Almost like any other object.
class Abc
end
is equivalent to:
Abc = Class.new do
end
It creates a new instance of Class and assigns it to the constant Abc.
To see what the different "class" things in Ruby mean, check out my other answer.
As for how methods are looked up:
There are multiple places a method can come from:
The class of the object
The parent of the class of the object
Modules, which are included/prepended
The singleton class of the object
The order of lookup is the following:
If it exists, the singleton class
Prepended modules
Methods defined in the class
Included modules
Recursively, the above rules for the parent class
There are a few things that have to be noted here:
If multiple modules are included/prepended, they will be looked up in the reverse order of how they were included/prepended
If a module was already included/prepended in one of the parrents, it won't be included/prepended again
If using these rules the method was not found til the very start of the hierarchy (BasicObject), the ancestor chain is searched again for a different method, called method_missing
BasicObject#method_missing is defined so that it throws a NoMethodError and that is where the error comes from
module M1
def foo
puts 'Defined in M1'
end
end
module M2
def foo
puts 'Defined in M2'
end
end
class C
include M1
prepend M2
def foo
puts 'Defined in C'
end
def method_missing(method_name)
puts 'Method missing' if method_name == :foo
end
end
c = C.new
# singleton method
def c.foo
puts "Defined in c's singleton"
end
puts c.singleton_class.ancestors
# => [#<Class:#<C:0xa2d0f8>>, M2, C, M1, Object, Kernel, BasicObject]
# ^ the singleton class,
# the prepended module,
# the C class itself,
# the included module,
# the rest of the hierarchy
# (Object is the implicit parent of all classes with no explicit parent)
with class Abc you define a class.
Abc.class is returning the Type, and the type of Abc is a Class
another example:
1337.class
=> Fixnum
"hi babe!".class
=> String
12.55.class
=> Float
(1..12).class
=> Range
so as you can see, each "datatype" is a class. in your case Abc is also a Datatype. And for the end of that chain, the class of a class is Class! :-)
Answering second par of the question, undefined class method happens when method you called is not present in such class - classes are just objects in Ruby, and as such they have their own set of methods. Ruby has several ways to define class methods, most common is probably
class Klass
def self.klass_method
...
end
end
the other is
class Klass
# some ordinary instance methods here
class << self
def klass_method
# this is class method
end
end
end
Some Rubyists prefer the latter, as it keeps all class methods in single block, but they are equivalent.

Calling instance method in Class in Ruby

I am very confused about this. In Programming Ruby book, it says,
"receiver checks for the method definition in its own class"
So class object stores all instance methods. Then why can't I call
instance method from within a class?
For example
Class ExampleClass
def example_method
end
example_method
end
I cannot call example_method inside ExampleClass.
However if I define a method in top level like this:
class ExampleClass
def example_method
end
end
def example_method1
end
example_method1
Then I can call top level method example_method1.
Isn't top level also a class? How come it is different than
a calling instance method from within ExampleClass?
The biggest reason that you cannot call that function in the way that you have written it is that it is, as you say, an instance method.
Try defining it in this way:
class ExampleClass
def self.class_method
puts "I'm a class method"
end
class_method
end
I believe you will find that you have a different result. It's not that it's "Top Level", it's whether or not it's in scope for what you're dealing with. Since you're dealing with a class, a class method would be necessary. If you're dealing with an object (an instantiated class) it's a different "scope".
Those "global" methods are an exception. They are defined as private instance methods of Object. Everything inherits from Object, so these methods are "globally" visible.
p self.class # => Object
p self.private_methods.sort # => [:Array, :Complex, ... :using, :warn] # all (?) from Kernel module
def aaaa
end
p self.private_methods.sort # => [:aaaa, :Array, ... :using, :warn]
The receiver checks for the method definition in its own class. The receiver is ExampleClass. The class of ExampleClass is Class. There is no example_method method in the Class class, ergo, you get a NoMethodError.
I'll try to explain it as follows.
class MyClass
def self.my_method
puts "Me, I'm a class method. Note that self = #{self}"
end
def my_method
puts "Me, I'm an instance method. Note that self = #{self}"
end
# I'm about to invoke :my_method on self. Which one will it be?"
# "That depends on what self is now, of course.
puts "self = #{self}"
# OK. It's MyClass. But wait. I'm just defining the set now.
# Do the methods I defined above even exist yet?
# Does the class exist yet? Let's find out.
print "class methods: "
puts self.methods(false)
print "instance methods: "
puts self.instance_methods(false)
# Cool! Let's try invoking my_method
my_method
# It worked. It was the class method because self = MyClass
# Now let's see if we can create an instance of the class before
# we finish defining the class. Surely we can't.
my_instance = new
puts "my_instance = #{my_instance}"
# We can! Now that's very interesting. Can we invoke the
# instance method on that instance?
my_instance.my_method
# Yes!
end
The following is printed while the class is being defined:
self = MyClass
class methods: my_method
instance methods: my_method
Me, I'm a class method. Note that self = MyClass
my_instance = #<MyClass:0x007fd6119125a0>
Me, I'm an instance method. Note that self = #<MyClass:0x007fd6119125a0>
Now let's confirm the methods can be invoked from outside the class. There should be no surprises here:
MyClass.my_method
#-> Me, I'm a class method. Note that self = MyClass
my_instance = MyClass.new
my_instance.my_method
#-> Me, I'm an instance method. Note that self = #<MyClass:0x007fd61181d668>

how rails delegate method works?

After reading the answer by jvans below and looking at the source code a few more time I get it now :). And in case anyone is still wondering how exactly rails delegates works. All rails is doing is creating a new method with (module_eval) in the file/class that you ran the delegate method from.
So for example:
class A
delegate :hello, :to => :b
end
class B
def hello
p hello
end
end
At the point when delegate is called rails will create a hello method with (*args, &block) in class A (technically in the file that class A is written in) and in that method all rails do is uses the ":to" value(which should be an object or a Class that is already defined within the class A) and assign it to a local variable _, then just calls the method on that object or Class passing in the params.
So in order for delegate to work without raising an exception... with our previous example. An instance of A must already have a instance variable referencing to an instance of class B.
class A
attr_accessor :b
def b
#b ||= B.new
end
delegate :hello, :to => :b
end
class B
def hello
p hello
end
end
This is not a question on "how to use the delegate method in rails", which I already know. I'm wondering how exactly "delegate" delegates methods :D. In Rails 4 source code delegate is defined in the core Ruby Module class, which makes it available as a class method in all rails app.
Actually my first question would be how is Ruby's Module class included? I mean every Ruby class has ancestors of > Object > Kernel > BasicObject and any module in ruby has the same ancestors. So how exactly how does ruby add methods to all ruby class/modules when someone reopens the Module class?
My second question is.. I understand that the delegate method in rails uses module_eval do the actual delegation but I don't really understand how module_eval works.
def delegate(*methods)
options = methods.pop
unless options.is_a?(Hash) && to = options[:to]
raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
end
prefix, allow_nil = options.values_at(:prefix, :allow_nil)
if prefix == true && to =~ /^[^a-z_]/
raise ArgumentError, 'Can only automatically set the delegation prefix when delegating to a method.'
end
method_prefix = \
if prefix
"#{prefix == true ? to : prefix}_"
else
''
end
file, line = caller.first.split(':', 2)
line = line.to_i
to = to.to_s
to = 'self.class' if to == 'class'
methods.each do |method|
# Attribute writer methods only accept one argument. Makes sure []=
# methods still accept two arguments.
definition = (method =~ /[^\]]=$/) ? 'arg' : '*args, &block'
# The following generated methods call the target exactly once, storing
# the returned value in a dummy variable.
#
# Reason is twofold: On one hand doing less calls is in general better.
# On the other hand it could be that the target has side-effects,
# whereas conceptually, from the user point of view, the delegator should
# be doing one call.
if allow_nil
module_eval(<<-EOS, file, line - 3)
def #{method_prefix}#{method}(#{definition}) # def customer_name(*args, &block)
_ = #{to} # _ = client
if !_.nil? || nil.respond_to?(:#{method}) # if !_.nil? || nil.respond_to?(:name)
_.#{method}(#{definition}) # _.name(*args, &block)
end # end
end # end
EOS
else
exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
module_eval(<<-EOS, file, line - 2)
def #{method_prefix}#{method}(#{definition}) # def customer_name(*args, &block)
_ = #{to} # _ = client
_.#{method}(#{definition}) # _.name(*args, &block)
rescue NoMethodError => e # rescue NoMethodError => e
if _.nil? && e.name == :#{method} # if _.nil? && e.name == :name
#{exception} # # add helpful message to the exception
else # else
raise # raise
end # end
end # end
EOS
end
end
end
Ruby isn't reopening the module class here. In ruby the class Module and the class Class are almost identical.
Class.instance_methods - Module.instance_methods #=> [:allocate, :new, :superclass]
The main difference is that you can't 'new' a module.
Module's are ruby's version of multiple inheritance so when you do:
module A
end
module B
end
class C
include A
include B
end
behind the scenes ruby is actually creating something called an anonymous class. so the above is actually equivalent to:
class A
end
class B < A
end
class C < B
end
module_eval here is a little deceptive. Nothing from the code you're looking at is dealing with modules. class_eval and module_eval are the same thing and they just reopen the class that they're called on so if you want to add methods to a class C you can do:
C.class_eval do
def my_new_method
end
end
or
C.module_eval do
def my_new_method
end
end
both of which are equivalent to manually reopening the class and defining the method
class C
end
class C
def my_new_method
end
end
so when they're calling module_eval in the source above, they're just reopening the current class it's being called it and dynamically defining the methods that you're delegating
I think this will answer your question better:
Class.ancestors #=> [Module, Object, PP::ObjectMixin, Kernel, BasicObject]
since everything in ruby is a class, the method lookup chain will go through all of these objects until it finds what it's looking for. By reoping module you add behavior to everything. The ancestor chain here is a little deceptive, since BasicObject.class #=> Class and Module is in Class's lookup hierarchy, even BasicObject inherits behavior from repening module. The advantage of reopening Module here over Class is that you can now call this method from within a module as well as within a class! Very cool, learned something here myself.
After reading the answer by jvans below and looking at the source code a few more time I get it now :). And in case anyone is still wondering how exactly rails delegates works. All rails is doing is creating a new method with (module_eval) in the file/class that you ran the delegate method from.
So for example:
class A
delegate :hello, :to => :b
end
class B
def hello
p hello
end
end
At the point when delegate is called rails will create a hello method with (*args, &block) in class A (technically in the file that class A is written in) and in that method all rails do is uses the ":to" value(which should be an object or a Class that is already defined within the class A) and assign it to a local variable _, then just calls the method on that object or Class passing in the params.
So in order for delegate to work without raising an exception... with our previous example. An instance of A must already have a instance variable referencing to an instance of class B.
class A
attr_accessor :b
def b
#b ||= B.new
end
delegate :hello, :to => :b
end
class B
def hello
p hello
end
end

Ruby and class variables in inherit class

class A
def set(v)
##v = v
end
def put
puts ##v
end
end
class B < A
end
class C < A
end
B.new.set 'b'
B.new.put # => b
C.new.set 'c'
C.new.put # => c
B.new.put # => c
Why? And how should I write this to have 'b' in last B.new.put?
Here is a nice article on the subject - Class and Instance Variables In Ruby.
Basically, what you can do is:
class A
class << self
attr_accessor :class_var
end
def set_class_var(value)
self.class.class_var = value
end
def get_class_var
self.class.class_var
end
end
class B < A; end
A.class_var = 'a'
B.class_var = 'b'
puts A.class_var # => a
puts B.class_var # => b
A.new.set_class_var 'aa'
B.new.set_class_var 'bb'
puts A.new.get_class_var # => aa
puts B.new.get_class_var # => bb
To understand it you should think about A as an instance of Class class (and that's how it is in Ruby). But every object in Ruby has its own singleton class that stores object-specific stuff like methods defined on object itself:
a = A.new
def a.foo
puts 'foo'
end
In that case foo is method defined only for a object and not for every instance of A class. And another way to define method in object's singleton class is like that:
class << a # open a's singleton class
def bar # define method that will be available only on 'a' object
puts 'bar'
end
end
In the first code snippet we use that approach to define class_var attribute accessor in the context of singleton class of our A class (it's a bit tricky, so you need to think about it). As the result class itself has class_var variable as well as its descendant class B. The difference is that every one of them has its own class_var variable that do not interfere.
Another option is to pull out class_inheritable_accessor code from Rails and include its behavior in your classes. See here for a good discussion and the guts of the code.
Perhaps you don't really want a class variable, though.
Assigning a value to a class variable (an ## variable) sets it for EVERY instance of the class. It even "sets" it for instances that "aren't created yet." So, consider this...
B.new.set 'b' # OK, that set ##v for that particular instance of B
B.new.put # Hey, you just created *another* new instance of B!
How can ##v have a value in that one? The second object's value of ##v would be unset, except for the fact that ##v is a class variable, so it has the same value for every instance of the class.

Resources