Reputation: 4464
I'm trying to understand when to use self.method_name vs. when to use Classname.method_name.
In the example below, why does "before_create" need to reference "User.hash_password" instead of "self.hash_password" or just "hash_password"?
Since we are in the User class already, I thought the before_create method would "know" that "hash_password" is a member of its own class and would not need any special syntax to refer to it.
require 'digest/sha1'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :password
validates_presence_of :name, :password
validates_uniqueness_of :name
def before_create
self.hashed_password = User.hash_password(self.password)
end
def after_create
@password = nil
end
def self.login(name, password)
hashed_password = hash_password(password || "")
self.find(:first, :conditions => ["name = ? and hashed_password = ?", name, hashed_password])
end
def try_to_login
User.login(self.name, self.password)
end
private
def self.hash_password(password)
Digest::SHA1.hexdigest(password)
end
end
Upvotes: 14
Views: 3891
Reputation: 75035
def before_create
self.hashed_password = User.hash_password(self.password)
end
In this example, User.hash_password
calls the hash_password
method on the class User
, whereas self.hashed_password=
calls the hashed_password=
method on this particular instance of User
.
If you replace User.hash_password
with self.hash_password
, Ruby would complain with a NoMethodError
, because no instance method by the name of hash_password
exists in the class User
. You could replace it with self.class.hash_password
, though.
If you replace self.hashed_password=
with simply hashed_password=
, Ruby would create a local variable named hashed_password
, rather than call the instance method hashed_password=
. You need to explicitly add self
if you want to call attribute writers.
The self
in the method definition (def self.hash_password
) makes hash_password
a class method instead of an instance method. In this context, self
refers to the class. In the context of an instance method, self
refers to an instance.
Upvotes: 13
Reputation: 21378
You are asking the difference between a class method and an instance method.
There are a few ways of defining a class method:
class Klass
def Klass.method_name
..
end
end
which is the same as doing:
class Klass
def self.method_name
..
end
end
or the preferred ruby idiom:
class Klass
class << self
def method_name
..
end
end
end
If Klass is already declared you can also do..
def Klass.method_name
..
end
or:
class << Klass
def method_name
..
end
end
or you could even use Module#extend:
Klass.extend(Module.new { def method_name; puts 'ducky'; end })
Much like you would add a singleton method to an object. In fact class methods are singleton methods which operate on the class level.
In rails ActiveRecord for example you have a class method 'find' which you can use on any Model:
Person.find(1)
and instance methods like 'save' which operates on the individual object
person = Person.find(1)
...
person.save
In the current project I am working on I have a model Feed which contains data feeds. Periodically I need to run a method which updates all the feeds so i have an fetch_all method which accomplishes this.
class Feed < ActiveRecord::Base
// class method Feed.fetch_all
def self.fetch_all
Feed.all.each do |feed|
feed.fetch_value
end
end
// instance method
def fetch_value
// grabs updated value and saves
end
end
Upvotes: 13
Reputation: 56448
I have yet to delve into Ruby, but from your description I'd say that hash_password is a static method or is capable of being used in a static manner.
Upvotes: 1