Hard time understanding the differences between "def self.fo

Hi guys,

I’m having a little trouble understanding the differences and knowing
when to use “def foo” and “def self.foo” in my models. I don’t quite
understand them and was hoping someone could explain or give me
examples on how to use the “self.” properly.

For example, I had “def foo” in my model “Account” and in one of my
views I tried doing “<%= Account.foo %>” but it didn’t work, but when
I changed it to “def self.foo” it did. But I don’t know why.

Thanks for the help.

Hey Rob,

The difference is between a Class and an Object. (btw, this is basic
object oriented stuff you’ll find in any reference)

Examples work best;

Dog is a Class, and your dog Fido is an Object (a specific instance
of a Dog).

So Dog.new references the Class method new, which gives you a new dog.

fido = Dog.new

and on fido, you can do specific dog things.

dog.sniff!
dog.eat(food)

etc.

in terms of ruby, you define a Class method as:
def self.new
end

and a object (aka instance) method
def sniff!
end

hope that helps Rob.
(I tried to work in some ‘mongrel’ references, but that started to
look like a subclass of dog that complicated the matter)

cheers,
Jodi

Hi Jodi,

Thanks. So can you tell me if I understand this correctly?

Instance methods are defined without the “self.” and are accessible
to all new class instances (objects)?

Class methods are defined with the “self.” and can be accessed by
themselves using Class.method? and dont require a new class instance?

So like…

class Dog

def self.find_owner (id)
self.find_by_owner(id)
end

def set_new_owner(owner)
self.owner = owner
end

end

so if i just wanted to find a random persons owner, i can just do…

owner = Dog.find_owner(1)
owner = Dog.find_owner(5)

without creating any new objects / class instances… and if I want to
create a new dog and give it a new owner’s name i can do…

fido = Dog.new(:name => “fido”, :owner => “rob”)
fido.set_new_owner=“jerry”
fido.save

Am I on the right track?

Well, almost.
find_owner would be calling find_by_owner on the Dog class.
So, it would return an array of Dog objects, not owner(s).

Your set_new_owner(owner) method is right, but there’s a better way.
fido.owner = “jerry”
fido.save

If you need to override the default accessor, you can do that:
def owner=(new_name)
self.name = new_name.capitalize # always store names capitalized
end

Make sense?

– Wes

Rob -

The find_by_owner Class method Wes mentions is provided to you by
Rails - as well as a bunch of others per finders field (find_by_#
{field_name})

Plus rails gives you accessors (instance methods) for every column in
your database. So fido.owner (fido.size, fido. color) will be
automatically available with the following class definition:

class Dog < ActiveRecord::Base
end

you get a bunch of free instance and class methods - as long as you
follow the rails naming conventions (tablename is ‘dog’, and has a
column id : integer [primary key]).

Rob - I suggest you pickup one of the great rails tutorials. You’ll
get a more complete picture than we can provide - http://
www.pragmaticprogrammer.com/title/rails1/ is a definitely worthwhile.

Jodi

Thanks. I already knew that you can use find_by_fieldname with rails
as well as getting field names automatically with fido.name,
fido.owner, etc… I just used those as examples to see if I
understood the difference between instance methods and class methods…