Calling class method from instance method

Y

Yu-shan Fung

Pretty dumb question -- how do I call a class method from inside an
instance method (of the same class)?

The use case I have is that in an activerecord model class, I would like
to define an instance method which calls find_by_sql.

I have tried and found that this works:
self.class.find_by_sql


But this seems pretty verbose for something so obvious.

Thanks!
 
S

Stefano Crocco

Pretty dumb question -- how do I call a class method from inside an
instance method (of the same class)?

The use case I have is that in an activerecord model class, I would like
to define an instance method which calls find_by_sql.

I have tried and found that this works:
self.class.find_by_sql


But this seems pretty verbose for something so obvious.

Thanks!

You can replace self.class with the name of the class. For example:

class C

def C.x
end

def y
self.class.x
C.x
end

end

There's a difference, however. If you derive a class from C and override C.x
from D:

class D < C
def self.x
end
end

using self.class.x from C#y will use the version of x defined in the
instance's class (that is, C.x if called by an instance of C and D.x if called
by an instance of D). Using C.x will, obviously, always call C.x. Here's some
code which demonstrates this:

class C
def self.x
puts "x of C"
end

def y
self.class.x
end

def z
C.x
end
end

class D < C
def self.x
puts "x of D"
end
end

puts "Calling y on an instance of C"
C.new.y
puts "Calling y on an instance of D"
D.new.y
puts "Calling z on an instance of D"
D.new.z

I hope this helps

Stefano
 
D

David A. Black

Hi --

Pretty dumb question -- how do I call a class method from inside an
instance method (of the same class)?

The use case I have is that in an activerecord model class, I would like
to define an instance method which calls find_by_sql.

I have tried and found that this works:
self.class.find_by_sql


But this seems pretty verbose for something so obvious.

You need the 'self.' part because class is a keyword. It's a bit
verbose but something's got to give :)


David

--
Rails training from David A. Black and Ruby Power and Light:
ADVANCING WITH RAILS April 14-17 New York City
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
See http://www.rubypal.com for details and updates!
 
M

marco antonio f.

Is it possible to do the opposite? call a instance method from a class
method?
 
R

Ryan Davis

Is it possible to do the opposite? call a instance method from a class=20=

When you have an instance "call a class method" you're really having the =
instance ask the class (an instance of Class) to call it's method.

When you want to have a class call an "instance method", which instance =
would call it?
 
A

Anurag Priyam

Is it possible to do the opposite? call a instance method from a class

Create an instance and call the instance method; very weird usage
though. Why would you need it?

class Foo
def self.hello
Foo.new.hello
end

def hello
puts "Hello World"
end
end

You can basically call any method from anywhere if you have the right receiver.
 
M

marco antonio f.

Ryan Davis ,
"When you want to have a class call an "instance method", which instance
would call it?"

Good point! Makes sense.

Anurag Priyam, this is pretty wierd... but works.

You see, there's stuff that need to be donne in both cases, in instances
and in classes. For example:

class SomeClass
def self.method
if file_exists?
#do stuff
end
#something need to be donne here, and I need to check if the file
exists
#I dont want to define a nother class method exactly the same as the
already declared instance method.
end

def file_exists?
#there are instance methods depending on this one
File.exists?("some_file_name.txt")
end
end

How do you deal with this kind of thing?
 
J

John Feminella

First, write your class method so that it accepts an instance:

=3D=3D=3D=3D begin snippet =3D=3D=3D=3D
class ExtendedFile
attr_accessor :filename

def self.process(file)
if file.exists?
# do some work
end
end

def exists?
self.exists? self.filename
end
end
=3D=3D=3D=3D end snippet =3D=3D=3D=3D

Of course, once you can do that, then you can refactor the class
method into an instance method. Delete the method's argument and
replace it with a reference to `self`:

=3D=3D=3D=3D begin snippet =3D=3D=3D=3D
class ExtendedFile
attr_accessor :filename

def process # now it's an instance method
if self.exists? # reference self instead of the argument
# do some work
end
end

def exists?
self.exists? self.filename
end
end
=3D=3D=3D=3D end snippet =3D=3D=3D=3D

~ jf
 
A

Anurag Priyam

You see, there's stuff that need to be donne in both cases, in instances
and in classes. For example:

class SomeClass
=A0def self.method
=A0 =A0if file_exists?
=A0 =A0 =A0#do stuff
=A0 =A0end
=A0 =A0#something need to be donne here, and I need to check if the file
exists
=A0 =A0#I dont want to define a nother class method exactly the same as t= he
already declared instance method.
=A0end

Since file_exists? is an instance method, it is very likely to return
true/false based on the state of the instance (see below). Calling
file_exists in self.method does not make sense unless its
responsibility is to act on an instance of your class - like a
factory, or processing an instance passed to it as a parameter.

def self.method(object)
if object.file_exists?
# do something on that object
object.statistics
end
end

or,

def self.create(*args)
object =3D SomeClass.new(*args)
return object if object.file_exists?
end
=A0def file_exists?
=A0 =A0#there are instance methods depending on this one
=A0 =A0File.exists?("some_file_name.txt")
=A0end

Umm, is the file name hard coded, or does it depend on the state of
the instance, like:

def file_exists?
File.exists?(@file)
end

If it is hard coded, or depends on a constant, you might as well
define a class method:

class SomeClass
CONFIG =3D "~/.foo.rc"

def self.config_exists?
File.exists?(CONFIG)
end

def init
raise "Config file not found" unless SomeClass.config_exists?
...
end
end
How do you deal with this kind of thing?

Depends on the context.

--=20
Anurag Priyam
http://about.me/yeban/
 
M

marco antonio f.

Thanks for the replies.

Turned out it was a matter of code organization. The methods I needed to
call, I put in another class, and called from its instances.

regards
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top