Reputation: 3265
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.
Upvotes: 4
Views: 1988
Reputation: 54902
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)
Upvotes: 7
Reputation: 4561
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.
Upvotes: 2
Reputation: 7366
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>
Upvotes: 1