Created
July 20, 2011 06:47
-
-
Save cldwalker/1094474 to your computer and use it in GitHub Desktop.
Prints out a tree of classes and their methods for a rails project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# == Description | |
# Prints out a tree of classes and their methods for a rails project. Can be run from the | |
# root directory of a rails project or with a specified rails directory. By default | |
# this script only looks in the models, controllers and helpers directories for ruby classes but that can be | |
# configured. | |
# | |
# This was useful back in the day when Rails projects were small and I wanted to a quick overview of | |
# the project. | |
##### RDOC file parser ##### | |
#Known to work with rdoc for ruby 1.8.2, 1.8.4 and 1.8.6 | |
require 'rdoc/rdoc.rb' | |
#to avoid issues in rdoc/parsers/parse_rb.rb | |
Options.instance.instance_eval "@tab_width = 8" | |
def index_class(cls,hash) | |
class_name = cls.full_name | |
hash[class_name] = cls.method_list.map {|x| x.name } if ! hash[class_name] | |
#indexes subclasses of a class | |
cls.each_classmodule { |x| index_class(x,hash) } | |
end | |
# Correctly parses methods with explicit classes. | |
# Todo: Doesn't correctly parse global methods ie methods without a class. | |
def rdoc_parse_file(file) | |
class_hash = {} | |
content = File.open(file, "r") {|f| f.read} | |
capital_p = RDoc::ParserFactory.parser_for(RDoc::TopLevel.new(file),file,content,Options.instance,RDoc::Stats.new) | |
capital_p.scan | |
rclasses = RDoc::TopLevel.all_classes_and_modules | |
rclasses.each {|rc| index_class(rc,class_hash) } | |
RDoc::TopLevel::reset | |
class_hash | |
end | |
##### END of RDOC file parser ##### | |
require "yaml" | |
require 'optparse' | |
options = {:nosort=>false,:delete_empty=>false } | |
OptionParser.new do |opt| | |
opt.banner = "Usage: #{File.basename($0)} [OPTIONS] [Directories under app/]" | |
opt.on('-s', '--nosort', 'Displays original order of methods for each class') { |options[:nosort]| } | |
opt.on('-d', '--delete_empty', 'Deletes classes that don\'t have any methods') { |options[:delete_empty]| } | |
opt.on('-r', '--rails_root==DIR',String, 'Specify rails root directory') { |options[:rails_root]| } | |
opt.parse!(ARGV) | |
end | |
rails_root = Dir.pwd | |
if options.has_key?(:rails_root) | |
RAILS_ROOT = options[:rails_root] | |
elsif File.exists?(File.join(rails_root,'config','environment.rb')) | |
RAILS_ROOT = rails_root | |
else | |
raise "No rails root detected. Add a default rails root." | |
end | |
directories = (! ARGV.empty?) ? ARGV : %w{models helpers controllers} | |
# Returns hash of class to methods pairs | |
def parse_methods_from_file(filename) | |
#other parsers could be used here | |
rdoc_parse_file(filename) | |
end | |
def yaml_format(dir_info) | |
dir_info.to_yaml + "\n" | |
end | |
def outline_format(dir_info) | |
body = '' | |
indent = "\t" | |
dir_info.each {|dir,info| | |
body += dir + "\n" | |
body += info.to_yaml.gsub!("\n","\n#{indent}").sub!(/^-+.*?\n/,'') + "\n" | |
} | |
body | |
end | |
dir_info = {} | |
directories.each { |e| | |
full_dir = File.join(RAILS_ROOT,'app',e) | |
unless File.exists?(full_dir) | |
puts "nonexistant directory '#{full_dir}' skipped" | |
next | |
end | |
files = Dir.glob(full_dir +"/**/*") | |
dir_info[e] = files.grep(/\.rb$/).map {|f| parse_methods_from_file(f) }.inject({}) {|t,s| t.update(s) } | |
if options[:delete_empty] | |
dir_info[e].each { |k,s| | |
dir_info[e].delete(k) if dir_info[e][k].empty? | |
} | |
end | |
unless options[:nosort] | |
dir_info[e].each { |k,sub| | |
dir_info[e][k] = sub.sort | |
} | |
end | |
} | |
#could also use yaml_format() | |
puts "\n",outline_format(dir_info) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment