[Q]: How can I find the filename where a class is defined?

G

George Moschovitis

Hello everyone,

I would like to find the filename where a given class is defined.
One simple solution is the following:

class MyClass
SOURCE_FILENAME = __FILE__
....
end

then the filename is:

MyClass::SOURCE_FILENAME

This is inelegant though, is there a better solution?
Thanks in advance,
George
 
P

Pit Capitain

Hi George!
I would like to find the filename where a given class is defined.

Since a class can be spread over multiple files, you have to define which one(s)
you want to get.
class MyClass
SOURCE_FILENAME = __FILE__
...
end

This is inelegant though, is there a better solution?

I cannot think of something simpler / better / more elegant...

Regards,
Pit
 
G

George Moschovitis

Since a class can be spread over multiple files, you have to define
which
one(s) you want to get.

My class is defined in one file only. I dont want a general solution. I
want a solution for classes defined in a single file. Any other ideas?
-g.
 
M

Michael Neumann

George said:
My class is defined in one file only. I dont want a general solution. I
want a solution for classes defined in a single file. Any other ideas?

Yes, that's what I needed last night, too (and some month ago where I
considered Wee+templating).

class Object
class << self
attr_accessor :classdef_in_file

alias __old_inherited inherited
def inherited(klass)
klass.classdef_in_file = caller.last.split(":").first
__old_inherited(klass)
end
end
end


# in file test.rb

class MyClass; end
p MyClass.classdef_in_file # => test.rb


Regards,

Michael
 
A

Alexander Kellett

My class is defined in one file only. I dont want a general solution. I
want a solution for classes defined in a single file. Any other ideas

t.rb
class Class
def inherited t
puts "class #{t} created at #{caller.first}"
end
end
require 'g.rb'

g.rb:
class Blah
end

->

class Blah created at ./g.rb:1
 
G

George Moschovitis

Yes, that's what I needed last night, too (and some month ago where I
...
class MyClass; end
p MyClass.classdef_in_file # => test.rb

Thank you very much!
considered Wee+templating).

I want this for a similar reason (new version of controller/action
reloading in Nitro)

-g.
 
R

Robert Klemme

George Moschovitis said:
My class is defined in one file only. I dont want a general solution. I
want a solution for classes defined in a single file. Any other ideas?
-g.

Maybe you can cook something up with set_trace_func. So you can set the
trace funtion at the beginning of your script and fill some global mapping
from class to file name.

robert
 
P

Pit Capitain

Michael said:
class Object
class << self
attr_accessor :classdef_in_file

alias __old_inherited inherited
def inherited(klass)
klass.classdef_in_file = caller.last.split(":").first
__old_inherited(klass)
end
end
end

This is a nice idea!

Note that it doesn't work on Windows, though, cause there you have filenames
with colons ("C:/xxx"). You could change the line
klass.classdef_in_file = caller.last.split(":").first
to

klass.classdef_in_file = caller.last.sub(/:\d+$/, "")


BTW: now I can finally get rid of all those ugly

if $0 == __FILE__
end

Code :)

Thanks for the reminder,
Pit
 
S

Sea&Gull

Michael said:
Yes, that's what I needed last night, too (and some month ago where I
considered Wee+templating).

class Object
class << self
attr_accessor :classdef_in_file

alias __old_inherited inherited
def inherited(klass)
klass.classdef_in_file = caller.last.split(":").first
__old_inherited(klass)
end
end
end

Don't you forget

private :inherited

?

:)

Also I would like to ask why you used "class Object" but not "class Class"?
There are some reasons I haven't seen?
 
Z

Zach Dennis

I dont' know what kind of performance you are looking for, but if you
know the file:

classes = {}
File.open( "file.rb" ) do |file|
file.each_line do |line|
next unless line =~ /\s*class\s*(\w+)/
classes[ $1 ] = file.lineno
end
end

puts "I found the class MyClass in file file.rb at line
#{classes['MyClass']}"

This will build a hash of your class to lineno found in the source
"file.rb". the "file.rb" could also be replaced with just saying
__FILE__ if you are wanting to parse the currently loaded file.

This could easily be expanded to suit any need, but granted it reparses
your source files and thus is slower and less efficient,

Zach
 
Z

Zach Dennis

Zach said:
I dont' know what kind of performance you are looking for, but if you
know the file:

classes = {}
File.open( "file.rb" ) do |file|
file.each_line do |line|
next unless line =~ /\s*class\s*(\w+)/
classes[ $1 ] = file.lineno
end
end

If you need it to gooo real fast, we can write a c extension =) and add
more functions so we don't get charged with being wasteful... The usage
could be similar to:

RubySourceParser::find_method_decl( "mymethod" )
=>[[Class1,"file.rb", lineno=1044], [Class2, "file2.rb", lineno=56]]

RubySourceParser::find_method_decl( "Class1", "mymethod" ) => ...etc...

RubySourceParser::find_class_decl( "Class1" ) => ["file1.rb",lineno=10]

RubySourceParser::find_module_decl( "...etc..." )

Perhaps this is overkill, but I am on a ruby high right now, after I
wrote a mini-library to handle NetworkDrives in Windows. It is a small
very simple thing, but it makes me sooo happy. Happying Rubying!

Zach
 

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

No members online now.

Forum statistics

Threads
474,444
Messages
2,571,709
Members
48,796
Latest member
Greg L.
Top