简体   繁体   中英

Ruby on Rails instance vs class methods

I have studied major difference between Ruby class ,instance method and the major difference I found is we don't need to create instance of that class we can directly call that method on class name directly.

class Notifier 

def reminder_to_unconfirmed_user(user)
    headers['X-SMTPAPI'] = '{"category": "confirmation_reminder"}'
    @user = user
    mail(:to => @user["email"], :subject => "confirmation instructions reminder")
  end

end

So,here I defined instance method reminder_to_unconfirmed_user in my Notifier class to send email to unconfirmed users, and when I run Notifier.reminder_to_unconfirmed_user(User.last) it get called provided it's a instance method not a class method.

To define a class method, use the self keyword in the method's definition (or the class' name):

class Notifier
  def self.this_is_a_class_method
  end

  def Notifier.this_a_class_method_too
  end

  def this_is_an_instance_method
  end
end

In your case, reminder_to_unconfirmed_user should be defined as a class method:

class Notifier 

  def self.reminder_to_unconfirmed_user(user)
    # ...
  end

end

Then you can use it like this:

Notifier.reminder_to_unconfirmed_user(User.last)

I had the same question the OP did and after digging around I finally figured it out! The other answers just addressed when to use instance vs class methods in Ruby however Rails does some sneaky stuff behind the scences. The question wasn't when to use class vs instance methods but instead how come Rails allows you to call an instance method as if it's a class method as shown by his mailer example above. It's due to: AbstractController::Base and can be seen here: AbstractController::Base

Basically, in all controllers (whether they be your mailer or a standard controller), all defined methods are intercepted by "method_missing" and then returns an instance of that class! The defined methods are then also converted to public instance methods. Thus, because you never instantiate these classes (for example you never do Mailer.new.some_method) Rails automagically calls method_missing and returns an instance of that Mailer which then takes advantage of all the methods defined within that class.

In your case it must be :

class Notifier 

  def self.reminder_to_unconfirmed_user(user)
    headers['X-SMTPAPI'] = '{"category": "confirmation_reminder"}'
    @user = user
    mail(:to => @user["email"], :subject => "confirmation instructions reminder")
  end

end

As their name suggests:

Instance methods on a model should be used for logic/operations that relate to a specific instance of a model (the one on which the method is called.)

Class methods are for things which don't operate on an individual instance of a model or for cases where you don't have the instance available to you. Like in some cases you do want to apply changes on few group of objects. If you want to update all users on a specific condition, Then you should go for class method.

They do have different way of calling :

class Test
  def self.hi
    puts 'class method'
  end

  def hello
    puts 'instance method'
  end
end

Foo.hi # => "class method"
Foo.hello # => NoMethodError: undefined method ‘hello’ for Test:Class

Foo.new.hello # => instance method
Foo.new.hi # => NoMethodError: undefined method ‘hi’ for #<Test:0x1e871>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM