Friday 10 February 2012

Class and Instance Methods in Ruby


In ruby, classes are also objects, so the methods you define as class methods only exist in the object that defined them (the class) and nowhere else. If you define class_method in a class named Test, class_method will only live into the object Test, which is an instance of a built-in ruby class named Class.

class methods are singleton methods of instances of Class


But in general u will feel that Class methods are methods that are called on a class and instance methods are methods that are called on an instance of a class.

Every instances that you create contain a variable that points to their corresponding class. Say you create a new instance of class Test and that you name this instance T (T = Test.new). T will contain every instance variables/methods that have been defined as such in the class as well as a reference to the object Test, which will contain the variables that need to be shared among every instances of this class (class variables) as well as methods that will be local to this object (class methods). That’s the reason why ruby complain when you write something like T.class_method. It complains because class_method just doesn’t reside in T, it resides in Test.
You have 2 ways for defining a class method.

1) You can use the name of the class directly





    class My #My is now an instance of a built-in class named Class
          
            def My.class_method
               "It's a class method."
            end
       end


2) You can use the self variable, which is always pointing to the current object






  
     class My
       def self.class_method
          "It's a class method."
       end
     end


3  It consists of building a new anonymous class only for the current object (self). To create the anonymous class, we use the << notation.


    class test
            class << self
                def bar
                    puts 'It's a class Method'
                end
           end
       end

4
     class Test;
         end

          def Test.bar
            puts 'It's a class Method'

          end

5 Way to call class method

   class_name.method_name

      like here

                  my.class_method
      or 

                  test.bar


Once you understand that classes are objects, this use of the self variable to define a class method finally makes sense.

Remember what we have to do to add a new instance method in a class :













class Test
  def hello
    "It's an instance method"
    "It'saccessible in every single instance of class Test"
  end
end
T = Test.new

When you look at it, it's exactly the same trick that we previously used to add a new class method. The only difference is that instead of adding a method to an instance of class Class, we added a method to an instance of class Test.

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.T
  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.


other uses of class methods in Rails are validations and associations in ActiveRecord and before/after/around filters in ActionPack. The way this works is something like this (simplified for clarity):

module ActiveRecord
  class Base
    def self.validates_presence_of(...)
      # make sure present
    end
  end
end

class Foo < ActiveRecord::Base
  validates_presence_of :bar
end

When you say validates_presence_of, the class method in AR::Base is what gets called.





So what are some examples uses of instance methods in Rails, to give you a better idea? Ever do a find in a destroy action and then call destroy on the found instance? destroy is an instance method.

class FoosController < ActionController
  def destroy
    foo = Foo.find(params[:id])
    foo.destroy
    redirect_to foos_url
  end
end

So are save and update_attributes, which you have definitely used before if you’ve done any Rails.

foo = Foo.new(:title => 'Bar')
foo.save # is an instance method


No comments:

Post a Comment