Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class methods in Ruby on Rails 3 — I'm totally lost!

Background here.

In the above link, the following example is given:

class << self
  def by_author(author)
    where(:author_id => author.id)
  end
end

Aside from that syntax being foreign to a beginner like me — I had always thought class methods were defined with def self.my_class_method — where can I find documentation about class methods in Ruby on Rails?

As far as I know, class methods are always called on the class itself (MyClass.my_class_method), but if class methods in Rails are chainable, it seems as though something else must be going on here!

Edit:

I suppose I sort of cheated by making that comment about the syntax for class methods. I'm really asking how Rails makes a class method chainable — I understand how method chaining works, but not how Rails can allow you to chain class methods without actually returning the class object itself after each "link" in the chain.

like image 540
ClosureCowboy Avatar asked Mar 09 '11 03:03

ClosureCowboy


3 Answers

Class methods in Ruby are really just members of the singleton class, and doing class << self involves opening the singleton class directly and adding to it, removing the need to declare it in each method definition.

This article on Ruby singletons does a good job explaining.

As far as class methods being chainable, that isn't something specific to class methods, the second method call is simply called on the object returned from the first. For example:

bar = foo.do_something.do_more

is equivalent to:

tmp = foo.do_something
bar = tmp.do_more

In Rails, this chainability is most often used for building SQL queries (e.g., with where or order, etc.). This is achieved because each of these methods returns an ActiveRecord Relation.

The reason

 foo.scoped.my_foo_class_method

works is because of ActiveRecord::Relation#method_missing doing the following:

elsif @klass.respond_to?(method)
  scoping { @klass.send(method, *args, &block) }

Which checks if the ActiveRecord class responds to the method called, and if so, calls that.

like image 167
Andrew Marshall Avatar answered Sep 26 '22 13:09

Andrew Marshall


Having class << self is also another way to define your methods so that you do not have to call "def self.my_method" or "def MyClass.my_method" for every single method that you are defining as a class method. Instead of calling

  def self.my_method1
  end

  def self.my_method2
  end
class << self
  def my_method1
  end

  def my_method2
  end
end

Cheers!

like image 28
RubyFanatic Avatar answered Sep 25 '22 13:09

RubyFanatic


The following two bits of code are equivalent.

Using self.method:

class Hello
  def self.world
    puts "Hello, World!"
  end
end

Using class << self:

class Hello
  class << self
    def world
      puts "Hello, World!"
    end
  end
end

The only difference is readability, as well as the ease in refactoring. The class << self technique is often used when metaprogramming.

There is another thread that explains this. class << self vs self.method with Ruby: what's better?

like image 42
Justin Baker Avatar answered Sep 24 '22 13:09

Justin Baker