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

前端 未结 3 1232
死守一世寂寞
死守一世寂寞 2021-02-10 12:40

Background here.

In the above link, the following example is given:

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


        
相关标签:
3条回答
  • 2021-02-10 13:13

    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?

    0 讨论(0)
  • 2021-02-10 13:23

    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.

    0 讨论(0)
  • 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!

    0 讨论(0)
提交回复
热议问题