jakewendt-rdoc_rails 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +94 -0
- data/lib/jakewendt-rdoc_rails.rb +1 -0
- data/lib/rdoc_rails.rb +8 -0
- data/lib/rdoc_rails/rake.rb +21 -0
- data/lib/rdoc_rails/rdoc/ar_association.rb +103 -0
- data/lib/rdoc_rails/rdoc/context.rb +19 -0
- data/lib/rdoc_rails/rdoc/generator/railsfish.rb +27 -0
- data/lib/rdoc_rails/rdoc/generator/template/railsfish/classpage.rhtml +308 -0
- data/lib/rdoc_rails/rdoc/parser/rails.rb +387 -0
- data/lib/rdoc_rails/rdoc/token_stream.rb +9 -0
- data/lib/tasks/rdoc_rails.rake +19 -0
- data/test/app/models/blog.rb +4 -0
- data/test/app/models/comment.rb +12 -0
- data/test/app/models/post.rb +6 -0
- data/test/app/models/user.rb +13 -0
- data/test/rdoc_rails_test.rb +15 -0
- data/test/tasks/testing.rb +9 -0
- data/test/test_helper.rb +86 -0
- metadata +118 -0
data/README.rdoc
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
= RDoc::Rails
|
2
|
+
|
3
|
+
This package adds Rails-specific information to RDoc generated docs on Rails
|
4
|
+
projects. It could be particularly useful for people wanting to document Rails
|
5
|
+
applications for internal use within a team of developers. It includes
|
6
|
+
<tt>RDoc::Parser::Rails</tt> based on <tt>RDoc::Parser::Ruby</tt> as well as
|
7
|
+
<tt>RDoc::Generator::Railsfish</tt> based on <tt>RDoc::Generator::Darkfish</tt>
|
8
|
+
|
9
|
+
== Installation
|
10
|
+
Currently, this is written as a Rails plugin, although I will look into
|
11
|
+
packaging it as a gem as well. It works with RDoc version 2.4.3, the most
|
12
|
+
current version as of August, 2009. I have tested it only with Rails 2.0, but I
|
13
|
+
would expect it to work for projects written in earlier and later versions of
|
14
|
+
Rails as well.
|
15
|
+
|
16
|
+
To install as a Rails plugin, try some variation on one of the following:
|
17
|
+
ruby script/plugin install git://github.com/chinasaur/rdoc_rails.git
|
18
|
+
ruby script/plugin install http://github.com/chinasaur/rdoc_rails.git
|
19
|
+
ruby script/plugin install http://github.com/chinasaur/rdoc_rails.git/
|
20
|
+
|
21
|
+
You may then need/want to rename the directory
|
22
|
+
<tt>vendor/plugins/rdoc_rails.git/</tt> to just +rdoc_rails+
|
23
|
+
|
24
|
+
After that, you should be good to go. The standard
|
25
|
+
> rake doc:app
|
26
|
+
or
|
27
|
+
> rake doc:reapp
|
28
|
+
should now run the Rails customized version of RDoc.
|
29
|
+
|
30
|
+
== Features
|
31
|
+
Right now there are just two basic features above and beyond the standard Ruby
|
32
|
+
RDoc:
|
33
|
+
|
34
|
+
1. Documentation for ActiveRecord associations on Models
|
35
|
+
2. Documentation for methods delegated to other models through the +delegate+ method.
|
36
|
+
|
37
|
+
But the infrastructure is all there to make it straightforward to parse
|
38
|
+
additional features in Rails code and generate documentation based on those
|
39
|
+
parsings.
|
40
|
+
|
41
|
+
== Suggested Features
|
42
|
+
|
43
|
+
* named_scope parsing
|
44
|
+
* validate_* parsing
|
45
|
+
* before_* parsing
|
46
|
+
* after_* parsing
|
47
|
+
* attr_protected parsing
|
48
|
+
* attr_accessible parsing
|
49
|
+
* custom user grouping and parsing (probably more core rdoc)
|
50
|
+
|
51
|
+
== Tests
|
52
|
+
|
53
|
+
* Tests are in development
|
54
|
+
* Both tests for Comment model's belongs_to associations fail
|
55
|
+
* one is polymorphic
|
56
|
+
* the other has a redefined class_name and counter_cache => true
|
57
|
+
* tests run, but I don't parse the output yet
|
58
|
+
|
59
|
+
|
60
|
+
== Contributing
|
61
|
+
I will try to document things better to make it easy for others to contribute
|
62
|
+
additional documentation features. For now, get in touch if you have any
|
63
|
+
questions and fork away.
|
64
|
+
|
65
|
+
== License http://i.creativecommons.org/l/by/3.0/us/80x15.png
|
66
|
+
Rdoc::Rails is released under a {Creative Commons Attribution 3.0 United States
|
67
|
+
License}[http://creativecommons.org/licenses/by/3.0/us/]. Please credit me
|
68
|
+
somewhere in your project's documentation if you are using this.
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
== Dev by Jake
|
75
|
+
|
76
|
+
Gemified with Jeweler
|
77
|
+
|
78
|
+
rake version:bump:patch
|
79
|
+
rake version:bump:minor
|
80
|
+
rake version:bump:major
|
81
|
+
|
82
|
+
rake gemspec
|
83
|
+
|
84
|
+
rake install
|
85
|
+
|
86
|
+
rake release
|
87
|
+
|
88
|
+
|
89
|
+
This seems to be incompatible with the latest rdoc 3.4.
|
90
|
+
Attempting to remedy.
|
91
|
+
Still not working.
|
92
|
+
|
93
|
+
|
94
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rdoc_rails'
|
data/lib/rdoc_rails.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'rdoc_rails/rake'
|
4
|
+
require 'rdoc_rails/rdoc/context'
|
5
|
+
require 'rdoc_rails/rdoc/token_stream'
|
6
|
+
require 'rdoc_rails/rdoc/ar_association'
|
7
|
+
require 'rdoc_rails/rdoc/parser/rails'
|
8
|
+
require 'rdoc_rails/rdoc/generator/railsfish'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rake
|
2
|
+
def self.remove_task(task_name)
|
3
|
+
Rake.application.instance_variable_get(:@tasks).delete(task_name.to_s) || raise('No such task!')
|
4
|
+
end
|
5
|
+
|
6
|
+
class RDocTask
|
7
|
+
def self.remove_task(task='rdoc', opts={})
|
8
|
+
Rake.remove_task(Rake::Task[task].prerequisites[0])
|
9
|
+
Rake.remove_task(task)
|
10
|
+
|
11
|
+
task = task.to_s.split(':')
|
12
|
+
name = task[-1]
|
13
|
+
path = task[0..-2] * ':'
|
14
|
+
rerdoc = opts[:rerdoc] || "re#{name}"
|
15
|
+
clobber = opts[:clobber_rdoc] || "clobber_#{name}"
|
16
|
+
|
17
|
+
Rake.remove_task("#{path}:#{rerdoc}")
|
18
|
+
Rake.remove_task("#{path}:#{clobber}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
require 'cgi'
|
5
|
+
class CGI
|
6
|
+
def self.escapeHTML_with_nil_check(string)
|
7
|
+
string = '' if string.nil?
|
8
|
+
escapeHTML_without_nil_check(string)
|
9
|
+
end
|
10
|
+
class << self
|
11
|
+
alias_method_chain :escapeHTML, :nil_check
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class RDoc::ArAssociation < RDoc::Context
|
16
|
+
include RDoc::TokenStream
|
17
|
+
attr_accessor :atype
|
18
|
+
attr_accessor :name
|
19
|
+
attr_writer :opts
|
20
|
+
|
21
|
+
def initialize(init={})
|
22
|
+
super()
|
23
|
+
init.each{ |k,v| send("#{k}=", v) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def opts
|
27
|
+
@opts || {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def class_name
|
31
|
+
class_name = opts[:class_name]
|
32
|
+
class_name ||= ActiveSupport::Inflector.classify(name) if ['has_many', 'has_and_belongs_to_many'].include?(atype.to_s)
|
33
|
+
class_name ||= name.camelize
|
34
|
+
class_name
|
35
|
+
end
|
36
|
+
|
37
|
+
def path
|
38
|
+
parent.path
|
39
|
+
end
|
40
|
+
|
41
|
+
# Pulled from RDoc::Generator::Markup
|
42
|
+
# Would be nice if this were moved into a module so it could be includable
|
43
|
+
# without copy/paste.
|
44
|
+
def add_line_numbers(src)
|
45
|
+
if src =~ /\A.*, line (\d+)/ then
|
46
|
+
first = $1.to_i - 1
|
47
|
+
last = first + src.count("\n")
|
48
|
+
size = last.to_s.length
|
49
|
+
|
50
|
+
line = first
|
51
|
+
src.gsub!(/^/) do
|
52
|
+
res = if line == first
|
53
|
+
" " * (size + 2)
|
54
|
+
else
|
55
|
+
"%#{size}d: " % line
|
56
|
+
end
|
57
|
+
|
58
|
+
line += 1
|
59
|
+
res
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Pulled from RDoc::Generator::Markup
|
65
|
+
# Would be nice if this were moved into a module so it could be includable
|
66
|
+
# without copy/paste.
|
67
|
+
def markup_code
|
68
|
+
return '' unless @token_stream
|
69
|
+
|
70
|
+
src = ""
|
71
|
+
|
72
|
+
@token_stream.each do |t|
|
73
|
+
next unless t
|
74
|
+
# style = STYLE_MAP[t.class]
|
75
|
+
style = case t
|
76
|
+
when RDoc::RubyToken::TkCONSTANT then "ruby-constant"
|
77
|
+
when RDoc::RubyToken::TkKW then "ruby-keyword kw"
|
78
|
+
when RDoc::RubyToken::TkIVAR then "ruby-ivar"
|
79
|
+
when RDoc::RubyToken::TkOp then "ruby-operator"
|
80
|
+
when RDoc::RubyToken::TkId then "ruby-identifier"
|
81
|
+
when RDoc::RubyToken::TkNode then "ruby-node"
|
82
|
+
when RDoc::RubyToken::TkCOMMENT then "ruby-comment cmt"
|
83
|
+
when RDoc::RubyToken::TkREGEXP then "ruby-regexp re"
|
84
|
+
when RDoc::RubyToken::TkSTRING then "ruby-value str"
|
85
|
+
when RDoc::RubyToken::TkVal then "ruby-value"
|
86
|
+
else nil
|
87
|
+
end
|
88
|
+
|
89
|
+
text = CGI.escapeHTML(t.text)
|
90
|
+
|
91
|
+
if style
|
92
|
+
src << "<span class=\"#{style}\">#{text}</span>"
|
93
|
+
else
|
94
|
+
src << text
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# add_line_numbers src if RDoc::RDoc.current.options.include_line_numbers
|
99
|
+
# change for rdoc > 2.4.3
|
100
|
+
|
101
|
+
src
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rdoc/context'
|
2
|
+
class RDoc::Context
|
3
|
+
attr_accessor :ar_associations
|
4
|
+
|
5
|
+
# Overriding to initialize ar_associations
|
6
|
+
def initialize_methods_etc
|
7
|
+
@method_list = []
|
8
|
+
@attributes = []
|
9
|
+
@aliases = []
|
10
|
+
@requires = []
|
11
|
+
@includes = []
|
12
|
+
@constants = []
|
13
|
+
@ar_associations = []
|
14
|
+
|
15
|
+
# This Hash maps a method name to a list of unmatched aliases (aliases of
|
16
|
+
# a method not yet encountered).
|
17
|
+
@unmatched_alias_lists = {}
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rdoc/generator/darkfish'
|
2
|
+
class RDoc::Generator::Railsfish < RDoc::Generator::Darkfish
|
3
|
+
RDoc::RDoc.add_generator(self)
|
4
|
+
VERSION = '0.1.0'
|
5
|
+
|
6
|
+
# Override template path to use standard darkfish template for most pages
|
7
|
+
def initialize(opts)
|
8
|
+
opts.instance_variable_set(:@template, 'darkfish') if opts.template == 'railsfish'
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
# Overriding to allow setting templatefile to my Rails customized version.
|
13
|
+
def generate_class_files
|
14
|
+
debug_msg "Generating class documentation in #@outputdir"
|
15
|
+
templatefile = Pathname.new(File.dirname(__FILE__) + '/template/railsfish/classpage.rhtml')
|
16
|
+
|
17
|
+
@classes.each do |klass|
|
18
|
+
debug_msg " working on %s (%s)" % [ klass.full_name, klass.path ]
|
19
|
+
outfile = @outputdir + klass.path
|
20
|
+
rel_prefix = @outputdir.relative_path_from( outfile.dirname )
|
21
|
+
svninfo = self.get_svninfo( klass )
|
22
|
+
|
23
|
+
debug_msg " rendering #{outfile}"
|
24
|
+
self.render_template( templatefile, binding(), outfile )
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,308 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
3
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta content="text/html; charset=<%= @options.charset %>" http-equiv="Content-Type" />
|
7
|
+
|
8
|
+
<title><%= klass.type.capitalize %>: <%= klass.full_name %></title>
|
9
|
+
|
10
|
+
<link rel="stylesheet" href="<%= rel_prefix %>/rdoc.css" type="text/css" media="screen" />
|
11
|
+
|
12
|
+
<script src="<%= rel_prefix %>/js/jquery.js" type="text/javascript" charset="utf-8"></script>
|
13
|
+
<script src="<%= rel_prefix %>/js/thickbox-compressed.js" type="text/javascript" charset="utf-8"></script>
|
14
|
+
<script src="<%= rel_prefix %>/js/quicksearch.js" type="text/javascript" charset="utf-8"></script>
|
15
|
+
<script src="<%= rel_prefix %>/js/darkfish.js" type="text/javascript" charset="utf-8"></script>
|
16
|
+
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body class="<%= klass.type %>">
|
20
|
+
|
21
|
+
<div id="metadata">
|
22
|
+
<div id="file-metadata">
|
23
|
+
<div id="file-list-section" class="section">
|
24
|
+
<h3 class="section-header">In Files</h3>
|
25
|
+
<div class="section-body">
|
26
|
+
<ul>
|
27
|
+
<% klass.in_files.each do |tl| %>
|
28
|
+
<li><a href="<%= rel_prefix %>/<%= h tl.path %>?TB_iframe=true&height=550&width=785"
|
29
|
+
class="thickbox" title="<%= h tl.absolute_name %>"><%= h tl.absolute_name %></a></li>
|
30
|
+
<% end %>
|
31
|
+
</ul>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<% if !svninfo.empty? %>
|
36
|
+
<div id="file-svninfo-section" class="section">
|
37
|
+
<h3 class="section-header">Subversion Info</h3>
|
38
|
+
<div class="section-body">
|
39
|
+
<dl class="svninfo">
|
40
|
+
<dt>Rev</dt>
|
41
|
+
<dd><%= svninfo[:rev] %></dd>
|
42
|
+
|
43
|
+
<dt>Last Checked In</dt>
|
44
|
+
<dd><%= svninfo[:commitdate].strftime('%Y-%m-%d %H:%M:%S') %>
|
45
|
+
(<%= svninfo[:commitdelta] %> ago)</dd>
|
46
|
+
|
47
|
+
<dt>Checked in by</dt>
|
48
|
+
<dd><%= svninfo[:committer] %></dd>
|
49
|
+
</dl>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
<% end %>
|
53
|
+
</div>
|
54
|
+
|
55
|
+
<div id="class-metadata">
|
56
|
+
|
57
|
+
<!-- Parent Class -->
|
58
|
+
<% if klass.type == 'class' %>
|
59
|
+
<div id="parent-class-section" class="section">
|
60
|
+
<h3 class="section-header">Parent</h3>
|
61
|
+
<% unless String === klass.superclass %>
|
62
|
+
<p class="link"><a href="<%= klass.aref_to klass.superclass.path %>"><%= klass.superclass.full_name %></a></p>
|
63
|
+
<% else %>
|
64
|
+
<p class="link"><%= klass.superclass %></p>
|
65
|
+
<% end %>
|
66
|
+
</div>
|
67
|
+
<% end %>
|
68
|
+
|
69
|
+
<!-- Namespace Contents -->
|
70
|
+
<% unless klass.classes_and_modules.empty? %>
|
71
|
+
<div id="namespace-list-section" class="section">
|
72
|
+
<h3 class="section-header">Namespace</h3>
|
73
|
+
<ul class="link-list">
|
74
|
+
<% (klass.modules.sort + klass.classes.sort).each do |mod| %>
|
75
|
+
<li><span class="type"><%= mod.type.upcase %></span> <a href="<%= klass.aref_to mod.path %>"><%= mod.full_name %></a></li>
|
76
|
+
<% end %>
|
77
|
+
</ul>
|
78
|
+
</div>
|
79
|
+
<% end %>
|
80
|
+
|
81
|
+
<!-- Method Quickref -->
|
82
|
+
<% unless klass.method_list.empty? %>
|
83
|
+
<div id="method-list-section" class="section">
|
84
|
+
<h3 class="section-header">Methods</h3>
|
85
|
+
<ul class="link-list">
|
86
|
+
<% klass.each_method do |meth| %>
|
87
|
+
<li><a href="#<%= meth.aref %>"><%= meth.singleton ? '::' : '#' %><%= meth.name %></a></li>
|
88
|
+
<% end %>
|
89
|
+
</ul>
|
90
|
+
</div>
|
91
|
+
<% end %>
|
92
|
+
|
93
|
+
<!-- Included Modules -->
|
94
|
+
<% unless klass.includes.empty? %>
|
95
|
+
<div id="includes-section" class="section">
|
96
|
+
<h3 class="section-header">Included Modules</h3>
|
97
|
+
<ul class="link-list">
|
98
|
+
<% klass.each_include do |inc| %>
|
99
|
+
<% unless String === inc.module %>
|
100
|
+
<li><a class="include" href="<%= klass.aref_to inc.module.path %>"><%= inc.module.full_name %></a></li>
|
101
|
+
<% else %>
|
102
|
+
<li><span class="include"><%= inc.name %></span></li>
|
103
|
+
<% end %>
|
104
|
+
<% end %>
|
105
|
+
</ul>
|
106
|
+
</div>
|
107
|
+
<% end %>
|
108
|
+
</div>
|
109
|
+
|
110
|
+
<div id="project-metadata">
|
111
|
+
<% simple_files = @files.select {|tl| tl.parser == RDoc::Parser::Simple } %>
|
112
|
+
<% unless simple_files.empty? then %>
|
113
|
+
<div id="fileindex-section" class="section project-section">
|
114
|
+
<h3 class="section-header">Files</h3>
|
115
|
+
<ul>
|
116
|
+
<% simple_files.each do |file| %>
|
117
|
+
<li class="file"><a href="<%= rel_prefix %>/<%= file.path %>"><%= h file.base_name %></a></li>
|
118
|
+
<% end %>
|
119
|
+
</ul>
|
120
|
+
</div>
|
121
|
+
<% end %>
|
122
|
+
|
123
|
+
<div id="classindex-section" class="section project-section">
|
124
|
+
<h3 class="section-header">Class Index
|
125
|
+
<span class="search-toggle">
|
126
|
+
<img src="<%= rel_prefix %>/images/find.png"
|
127
|
+
height="16" width="16" alt="[+]"
|
128
|
+
title="show/hide quicksearch" />
|
129
|
+
</span>
|
130
|
+
</h3>
|
131
|
+
<form action="#" method="get" accept-charset="utf-8" class="initially-hidden">
|
132
|
+
<fieldset>
|
133
|
+
<legend>Quicksearch</legend>
|
134
|
+
<input type="text" name="quicksearch" value="" class="quicksearch-field" />
|
135
|
+
</fieldset>
|
136
|
+
</form>
|
137
|
+
|
138
|
+
<ul class="link-list">
|
139
|
+
<% @modsort.each do |index_klass| %>
|
140
|
+
<li><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.full_name %></a></li>
|
141
|
+
<% end %>
|
142
|
+
</ul>
|
143
|
+
<div id="no-class-search-results" style="display: none;">No matching classes.</div>
|
144
|
+
</div>
|
145
|
+
|
146
|
+
<% if $DEBUG_RDOC %>
|
147
|
+
<div id="debugging-toggle"><img src="<%= rel_prefix %>/images/bug.png"
|
148
|
+
alt="toggle debugging" height="16" width="16" /></div>
|
149
|
+
<% end %>
|
150
|
+
</div>
|
151
|
+
</div>
|
152
|
+
|
153
|
+
<div id="documentation">
|
154
|
+
<h1 class="<%= klass.type %>"><%= klass.full_name %></h1>
|
155
|
+
|
156
|
+
<div id="description"><%= klass.description %></div>
|
157
|
+
|
158
|
+
<!-- Constants -->
|
159
|
+
<% unless klass.constants.empty? %>
|
160
|
+
<div id="constants-list" class="section">
|
161
|
+
<h3 class="section-header">Constants</h3>
|
162
|
+
<dl>
|
163
|
+
<% klass.each_constant do |const| %>
|
164
|
+
<dt><a name="<%= const.name %>"><%= const.name %></a></dt>
|
165
|
+
<% if const.comment %>
|
166
|
+
<dd class="description"><%= const.description.strip %></dd>
|
167
|
+
<% else %>
|
168
|
+
<dd class="description missing-docs">(Not documented)</dd>
|
169
|
+
<% end %>
|
170
|
+
<% end %>
|
171
|
+
</dl>
|
172
|
+
</div>
|
173
|
+
<% end %>
|
174
|
+
|
175
|
+
<!-- Attributes -->
|
176
|
+
<% unless klass.attributes.empty? %>
|
177
|
+
<div id="attribute-method-details" class="method-section section">
|
178
|
+
<h3 class="section-header">Attributes</h3>
|
179
|
+
|
180
|
+
<% klass.each_attribute do |attrib| %>
|
181
|
+
<div id="<%= attrib.html_name %>-attribute-method" class="method-detail">
|
182
|
+
<a name="<%= h attrib.name %>"></a>
|
183
|
+
<% if attrib.rw =~ /w/i %>
|
184
|
+
<a name="<%= h attrib.name %>="></a>
|
185
|
+
<% end %>
|
186
|
+
<div class="method-heading attribute-method-heading">
|
187
|
+
<span class="method-name"><%= h attrib.name %></span>
|
188
|
+
<span class="attribute-access-type">[<%= attrib.rw %>]</span>
|
189
|
+
</div>
|
190
|
+
|
191
|
+
<div class="method-description">
|
192
|
+
<% if attrib.comment %>
|
193
|
+
<%= attrib.description.strip %>
|
194
|
+
<% else %>
|
195
|
+
<p class="missing-docs">(Not documented)</p>
|
196
|
+
<% end %>
|
197
|
+
</div>
|
198
|
+
</div>
|
199
|
+
<% end %>
|
200
|
+
</div>
|
201
|
+
<% end %>
|
202
|
+
|
203
|
+
<!-- ActiveRecord Associations -->
|
204
|
+
<% unless klass.ar_associations.empty? %>
|
205
|
+
<div id="ara-method-details" class="method-section section">
|
206
|
+
<h3 class="section-header">ActiveRecord Associations</h3>
|
207
|
+
<% klass.ar_associations.each do |ara| %>
|
208
|
+
<div id="<%= ara.name %>-ara-method" class="method-detail">
|
209
|
+
<div class="method-heading ara-method-heading">
|
210
|
+
<span class="method-name">
|
211
|
+
<%= %Q|#{ara.atype} #{h ara.name} (<a href="#{ara.class_name}.html"><tt>#{ara.class_name}</tt></a>)| %>
|
212
|
+
</span>
|
213
|
+
<% if ara.token_stream %>
|
214
|
+
<span class="method-click-advice">click to toggle source</span>
|
215
|
+
<% end %>
|
216
|
+
</div>
|
217
|
+
|
218
|
+
<div class="method-description">
|
219
|
+
<% if ara.comment %>
|
220
|
+
<%= ara.description.strip %>
|
221
|
+
<% end %>
|
222
|
+
|
223
|
+
<% if ara.token_stream %>
|
224
|
+
<div class="method-source-code" id="<%= ara.name %>-source">
|
225
|
+
<pre>
|
226
|
+
<%= ara.markup_code %>
|
227
|
+
</pre>
|
228
|
+
</div>
|
229
|
+
<% end %>
|
230
|
+
</div>
|
231
|
+
</div>
|
232
|
+
<% end %>
|
233
|
+
</div>
|
234
|
+
<% end %>
|
235
|
+
|
236
|
+
<!-- Methods -->
|
237
|
+
<% klass.methods_by_type.each do |type, visibilities|
|
238
|
+
next if visibilities.empty?
|
239
|
+
visibilities.each do |visibility, methods|
|
240
|
+
next if methods.empty? %>
|
241
|
+
<div id="<%= visibility %>-<%= type %>-method-details" class="method-section section">
|
242
|
+
<h3 class="section-header"><%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</h3>
|
243
|
+
|
244
|
+
<% methods.each do |method| %>
|
245
|
+
<div id="<%= method.html_name %>-method" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>">
|
246
|
+
<a name="<%= h method.aref %>"></a>
|
247
|
+
|
248
|
+
<div class="method-heading">
|
249
|
+
<% if method.call_seq %>
|
250
|
+
<span class="method-callseq"><%= method.call_seq.strip.gsub(/->/, '→').gsub( /^\w.*?\./m, '') %></span>
|
251
|
+
<span class="method-click-advice">click to toggle source</span>
|
252
|
+
<% else %>
|
253
|
+
<span class="method-name"><%= h method.name %></span>
|
254
|
+
<span class="method-args"><%= method.params %></span>
|
255
|
+
<span class="method-click-advice">click to toggle source</span>
|
256
|
+
<% end %>
|
257
|
+
</div>
|
258
|
+
|
259
|
+
<div class="method-description">
|
260
|
+
<% if method.comment %>
|
261
|
+
<%= method.description.strip %>
|
262
|
+
<% else %>
|
263
|
+
<p class="missing-docs">(Not documented)</p>
|
264
|
+
<% end %>
|
265
|
+
|
266
|
+
<% if method.token_stream %>
|
267
|
+
<div class="method-source-code" id="<%= method.html_name %>-source">
|
268
|
+
<pre>
|
269
|
+
<%= method.markup_code %>
|
270
|
+
</pre>
|
271
|
+
</div>
|
272
|
+
<% end %>
|
273
|
+
</div>
|
274
|
+
|
275
|
+
<% unless method.aliases.empty? %>
|
276
|
+
<div class="aliases">
|
277
|
+
Also aliased as: <%= method.aliases.map do |aka|
|
278
|
+
%{<a href="#{ klass.aref_to aka.path}">#{h aka.name}</a>}
|
279
|
+
end.join(", ") %>
|
280
|
+
</div>
|
281
|
+
<% end %>
|
282
|
+
</div>
|
283
|
+
|
284
|
+
<% end %>
|
285
|
+
</div>
|
286
|
+
<% end %>
|
287
|
+
<% end %>
|
288
|
+
|
289
|
+
<div id="rdoc-debugging-section-dump" class="debugging-section">
|
290
|
+
<% if $DEBUG_RDOC
|
291
|
+
require 'pp' %>
|
292
|
+
<pre><%= h PP.pp(klass, _erbout) %></pre>
|
293
|
+
<% else %>
|
294
|
+
<p>Disabled; run with --debug to generate this.</p>
|
295
|
+
<% end %>
|
296
|
+
</div>
|
297
|
+
|
298
|
+
</div>
|
299
|
+
|
300
|
+
<div id="validator-badges">
|
301
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
302
|
+
<p><small>Generated with the Railsfish Rdoc Generator
|
303
|
+
<%= RDoc::Generator::Railsfish::VERSION %></small>.</p>
|
304
|
+
</div>
|
305
|
+
|
306
|
+
</body>
|
307
|
+
</html>
|
308
|
+
|
@@ -0,0 +1,387 @@
|
|
1
|
+
require 'rdoc/parser/ruby'
|
2
|
+
class RDoc::Parser::Rails < RDoc::Parser::Ruby
|
3
|
+
include RDoc::RubyToken
|
4
|
+
parse_files_matching(/\.rbw?$/)
|
5
|
+
|
6
|
+
def parse_rails_meta(container, single, tk, comment)
|
7
|
+
return unless container.document_children
|
8
|
+
restore_init_token(tk)
|
9
|
+
# Start listening to get_tk and saving read tokens into @token_stream, parse
|
10
|
+
# symbol args
|
11
|
+
add_token_listener self
|
12
|
+
args = parse_symbol_arg # This gets any symbol or string args
|
13
|
+
opts = (parse_final_hash if token_stream[-1].is_a?(TkCOMMA)) || {}
|
14
|
+
remove_token_listener self
|
15
|
+
|
16
|
+
send("parse_#{tk.name}", container, single, tk, comment, args, opts)
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_rails_debug(container, single, tk, comment, args, opts)
|
20
|
+
puts tk.name
|
21
|
+
puts args.inspect
|
22
|
+
puts opts.inspect if opts
|
23
|
+
puts ""
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_rails_pending(container, single, tk, comment, args, opts); end
|
27
|
+
alias parse_validates_uniqueness_of parse_rails_pending
|
28
|
+
|
29
|
+
def parse_ar_association(container, single, tk, comment, args, opts)
|
30
|
+
ara = RDoc::ArAssociation.new(
|
31
|
+
:atype => tk.name,
|
32
|
+
:name => args[0],
|
33
|
+
:opts => opts,
|
34
|
+
:comment => comment
|
35
|
+
)
|
36
|
+
|
37
|
+
ara.start_collecting_tokens
|
38
|
+
ara.add_tokens [position_comment(tk), NEWLINE_TOKEN]
|
39
|
+
ara.add_tokens token_stream
|
40
|
+
|
41
|
+
ara.parent = container
|
42
|
+
container.ar_associations << ara
|
43
|
+
end
|
44
|
+
alias parse_belongs_to parse_ar_association
|
45
|
+
alias parse_has_one parse_ar_association
|
46
|
+
alias parse_has_many parse_ar_association
|
47
|
+
alias parse_has_and_belongs_to_many parse_ar_association
|
48
|
+
|
49
|
+
# Take the args, opts, and tokens collected by parse_rails_meta and generate
|
50
|
+
# method documentation for delegated methods.
|
51
|
+
def parse_delegate(container, single, tk, comment, args, opts)
|
52
|
+
add_token_listener self
|
53
|
+
skip_to_eol
|
54
|
+
remove_token_listener self
|
55
|
+
|
56
|
+
args.each do |arg|
|
57
|
+
d_meth = RDoc::AnyMethod.new('', arg)
|
58
|
+
@stats.add_method d_meth
|
59
|
+
container.add_method d_meth
|
60
|
+
|
61
|
+
d_meth.start_collecting_tokens
|
62
|
+
d_meth.add_tokens [position_comment(tk), NEWLINE_TOKEN]
|
63
|
+
d_meth.add_tokens token_stream
|
64
|
+
|
65
|
+
d_meth.params = "(?) - delegated to #{opts[:to].inspect}" if opts[:to]
|
66
|
+
d_meth.params ||= '(?) - delegated method...'
|
67
|
+
|
68
|
+
d_meth.comment = comment
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def skip_to_eol
|
73
|
+
tk = get_tk until tk.is_a?(TkNL)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Parse tokens assumed to represent a final hash argument, thus will parse
|
77
|
+
# either a {} enclosed hash or a naked final hash.
|
78
|
+
#
|
79
|
+
# The purpose of this is mainly to be able to generate documentation for Rails
|
80
|
+
# meta calls, which generally have symbols/strings for keys and values, so
|
81
|
+
# that is what I've prioritized being able to parse. Shouldn't be difficult to
|
82
|
+
# add parsing of numeric keys/values. Parsing array/hash keys/values would be
|
83
|
+
# more difficult and isn't in the scope of what I currently plan to do. If
|
84
|
+
# this hits something it doesn't know how to parse, it rewinds all its tokens
|
85
|
+
# and quits.
|
86
|
+
#
|
87
|
+
# The best way to set up a call to parse_final_hash is as is done in
|
88
|
+
# parse_rails_meta, where we first call parse_symbol_arg. This is good setup
|
89
|
+
# because parse_symbol_arg will rewind to the comma before the final hash if
|
90
|
+
# it detects a hash in parsing other args.
|
91
|
+
def parse_final_hash
|
92
|
+
buffer = TokenStream.new
|
93
|
+
add_token_listener(buffer)
|
94
|
+
skip_tkspace(true)
|
95
|
+
|
96
|
+
case tk = get_tk
|
97
|
+
when TkLBRACE then bracketed = true
|
98
|
+
when TkSYMBOL, TkSTRING then bracketed = false
|
99
|
+
else
|
100
|
+
unget_tk(tk) until buffer.token_stream.empty?
|
101
|
+
remove_token_listener(buffer)
|
102
|
+
return
|
103
|
+
end
|
104
|
+
|
105
|
+
last_tk = tk
|
106
|
+
while tk = get_tk do
|
107
|
+
case tk
|
108
|
+
when TkSEMICOLON then break
|
109
|
+
when TkNL
|
110
|
+
unget_tk(tk) and break unless last_tk and TkCOMMA === last_tk
|
111
|
+
when TkSPACE, TkCOMMENT
|
112
|
+
when TkSYMBOL, TkSTRING, TkCOMMA, TkASSIGN, TkGT, TkASSOC then last_tk = tk # Will probably want to expand this to include numerics, possibly others; let's cross that bridge when we come to it.
|
113
|
+
else
|
114
|
+
break if bracketed and tk.is_a?(TkRBRACE)
|
115
|
+
unget_tk(tk) and break if !bracketed and tk.is_a?(TkDO)
|
116
|
+
|
117
|
+
unget_tk(tk) until buffer.token_stream.empty?
|
118
|
+
remove_token_listener(buffer)
|
119
|
+
return
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
remove_token_listener(buffer)
|
124
|
+
read = buffer.token_stream.collect{|tk|tk.text}.join
|
125
|
+
read = "{#{read}\n}" if !bracketed # We need the \n in case #{read} ends with a comment
|
126
|
+
eval(read) rescue nil
|
127
|
+
end
|
128
|
+
|
129
|
+
# Largely copied from super, but rewinds if it hits a =>, indicating the last
|
130
|
+
# symbol/string read should have been part of the final hash arg. Rewinds to
|
131
|
+
# the comma before the final hash, which provides a good check after we return
|
132
|
+
# of whether there are still more arguments to parse.
|
133
|
+
def parse_symbol_arg(no=nil)
|
134
|
+
buffer = TokenStream.new
|
135
|
+
add_token_listener(buffer)
|
136
|
+
|
137
|
+
args = []
|
138
|
+
skip_tkspace_comment
|
139
|
+
case tk = get_tk
|
140
|
+
when TkLPAREN
|
141
|
+
loop do
|
142
|
+
skip_tkspace_comment
|
143
|
+
if tk = parse_symbol_in_arg
|
144
|
+
args.push tk
|
145
|
+
break if no and args.size >= no
|
146
|
+
end
|
147
|
+
|
148
|
+
skip_tkspace_comment
|
149
|
+
case tk2 = get_tk
|
150
|
+
when TkRPAREN
|
151
|
+
break
|
152
|
+
when TkCOMMA
|
153
|
+
when TkASSOC, TkASSIGN, TkGT
|
154
|
+
# Oops, we started slurping the final Hash!
|
155
|
+
# So rewind back past the symbol or string that came before the =>
|
156
|
+
unget_tk(buffer.token_stream[-1]) until buffer.token_stream[-1].is_a?(TkCOMMA) or buffer.token_stream.empty?
|
157
|
+
args.pop
|
158
|
+
break
|
159
|
+
when TkLBRACE
|
160
|
+
# We hit the beginning of a hash or block, so rewind to the comma
|
161
|
+
unget_tk(buffer.token_stream[-1]) until buffer.token_stream[-1].is_a?(TkCOMMA) or buffer.token_stream.empty?
|
162
|
+
break
|
163
|
+
else
|
164
|
+
warn("unexpected token: '#{tk2.inspect}'") if $DEBUG_RDOC
|
165
|
+
break
|
166
|
+
end
|
167
|
+
end
|
168
|
+
else
|
169
|
+
unget_tk tk
|
170
|
+
if tk = parse_symbol_in_arg
|
171
|
+
args.push tk
|
172
|
+
return args if no and args.size >= no
|
173
|
+
end
|
174
|
+
|
175
|
+
loop do
|
176
|
+
skip_tkspace(false)
|
177
|
+
|
178
|
+
tk1 = get_tk
|
179
|
+
if TkCOMMA === tk1
|
180
|
+
elsif TkASSOC === tk1 or TkASSIGN === tk1 or TkGT === tk1
|
181
|
+
# Oops, we started slurping the final Hash!
|
182
|
+
# So rewind back past the symbol or string that came before the =>
|
183
|
+
unget_tk(buffer.token_stream[-1]) until buffer.token_stream[-1].is_a?(TkCOMMA) or buffer.token_stream.empty?
|
184
|
+
args.pop
|
185
|
+
break
|
186
|
+
elsif TkLBRACE === tk1
|
187
|
+
# We hit the beginning of a hash or block, so rewind to the comma
|
188
|
+
unget_tk(buffer.token_stream[-1]) until buffer.token_stream[-1].is_a?(TkCOMMA) or buffer.token_stream.empty?
|
189
|
+
break
|
190
|
+
else
|
191
|
+
unget_tk tk1
|
192
|
+
break
|
193
|
+
end
|
194
|
+
|
195
|
+
skip_tkspace_comment
|
196
|
+
if tk = parse_symbol_in_arg
|
197
|
+
args.push tk
|
198
|
+
break if no and args.size >= no
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
remove_token_listener buffer
|
204
|
+
args
|
205
|
+
end
|
206
|
+
|
207
|
+
# Comment line required to help generator put line numbers on included source code.
|
208
|
+
def position_comment(tk)
|
209
|
+
TkCOMMENT.new(tk.line_no, 1, "# File #{@top_level.absolute_name}, line #{tk.line_no}")
|
210
|
+
end
|
211
|
+
|
212
|
+
# Clear @token_stream and then put back the indentation and initial token;
|
213
|
+
# basically assumes tk is the first non-whitespace token on the line.
|
214
|
+
def restore_init_token(tk)
|
215
|
+
start_collecting_tokens
|
216
|
+
# indent = TkSPACE.new(1, 1)
|
217
|
+
# change for rdoc > 2.4.3
|
218
|
+
indent = TkSPACE.new(nil,1, 1)
|
219
|
+
indent.set_text(' ' * tk.char_no)
|
220
|
+
add_tokens([indent, tk])
|
221
|
+
end
|
222
|
+
|
223
|
+
# The identifiers that should be processed as rails meta-calls
|
224
|
+
RAILS_IDENTIFIERS = [
|
225
|
+
'belongs_to',
|
226
|
+
'has_one',
|
227
|
+
'has_many',
|
228
|
+
'has_and_belongs_to_many',
|
229
|
+
'delegate',
|
230
|
+
'validates_uniqueness_of'
|
231
|
+
]
|
232
|
+
|
233
|
+
# Copied from super, with a minor tweak to the TkIDENTIFIER parsing portion.
|
234
|
+
def parse_statements(container, single = NORMAL, current_method = nil, comment = '')
|
235
|
+
nest = 1
|
236
|
+
save_visibility = container.visibility
|
237
|
+
|
238
|
+
non_comment_seen = true
|
239
|
+
|
240
|
+
while tk = get_tk do
|
241
|
+
keep_comment = false
|
242
|
+
|
243
|
+
non_comment_seen = true unless TkCOMMENT === tk
|
244
|
+
|
245
|
+
case tk
|
246
|
+
when TkNL then
|
247
|
+
skip_tkspace true # Skip blanks and newlines
|
248
|
+
tk = get_tk
|
249
|
+
|
250
|
+
if TkCOMMENT === tk then
|
251
|
+
if non_comment_seen then
|
252
|
+
# Look for RDoc in a comment about to be thrown away
|
253
|
+
parse_comment container, tk, comment unless comment.empty?
|
254
|
+
|
255
|
+
comment = ''
|
256
|
+
non_comment_seen = false
|
257
|
+
end
|
258
|
+
|
259
|
+
while TkCOMMENT === tk do
|
260
|
+
comment << tk.text << "\n"
|
261
|
+
tk = get_tk # this is the newline
|
262
|
+
skip_tkspace(false) # leading spaces
|
263
|
+
tk = get_tk
|
264
|
+
end
|
265
|
+
|
266
|
+
unless comment.empty? then
|
267
|
+
look_for_directives_in container, comment
|
268
|
+
|
269
|
+
if container.done_documenting then
|
270
|
+
container.ongoing_visibility = save_visibility
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
keep_comment = true
|
275
|
+
else
|
276
|
+
non_comment_seen = true
|
277
|
+
end
|
278
|
+
|
279
|
+
unget_tk tk
|
280
|
+
keep_comment = true
|
281
|
+
|
282
|
+
when TkCLASS then
|
283
|
+
if container.document_children then
|
284
|
+
parse_class container, single, tk, comment
|
285
|
+
else
|
286
|
+
nest += 1
|
287
|
+
end
|
288
|
+
|
289
|
+
when TkMODULE then
|
290
|
+
if container.document_children then
|
291
|
+
parse_module container, single, tk, comment
|
292
|
+
else
|
293
|
+
nest += 1
|
294
|
+
end
|
295
|
+
|
296
|
+
when TkDEF then
|
297
|
+
if container.document_self then
|
298
|
+
parse_method container, single, tk, comment
|
299
|
+
else
|
300
|
+
nest += 1
|
301
|
+
end
|
302
|
+
|
303
|
+
when TkCONSTANT then
|
304
|
+
if container.document_self then
|
305
|
+
# parse_constant container, single, tk, comment
|
306
|
+
# change for rdoc > 2.4.3
|
307
|
+
parse_constant container, tk, comment
|
308
|
+
end
|
309
|
+
|
310
|
+
when TkALIAS then
|
311
|
+
if container.document_self then
|
312
|
+
parse_alias container, single, tk, comment
|
313
|
+
end
|
314
|
+
|
315
|
+
when TkYIELD then
|
316
|
+
if current_method.nil? then
|
317
|
+
warn "Warning: yield outside of method" if container.document_self
|
318
|
+
else
|
319
|
+
parse_yield container, single, tk, current_method
|
320
|
+
end
|
321
|
+
|
322
|
+
# Until and While can have a 'do', which shouldn't increase the nesting.
|
323
|
+
# We can't solve the general case, but we can handle most occurrences by
|
324
|
+
# ignoring a do at the end of a line.
|
325
|
+
when TkUNTIL, TkWHILE then
|
326
|
+
nest += 1
|
327
|
+
skip_optional_do_after_expression
|
328
|
+
|
329
|
+
# 'for' is trickier
|
330
|
+
when TkFOR then
|
331
|
+
nest += 1
|
332
|
+
skip_for_variable
|
333
|
+
skip_optional_do_after_expression
|
334
|
+
|
335
|
+
when TkCASE, TkDO, TkIF, TkUNLESS, TkBEGIN then
|
336
|
+
nest += 1
|
337
|
+
|
338
|
+
when TkIDENTIFIER then
|
339
|
+
if nest == 1 and current_method.nil? then
|
340
|
+
case tk.name
|
341
|
+
when 'private', 'protected', 'public', 'private_class_method',
|
342
|
+
'public_class_method', 'module_function' then
|
343
|
+
parse_visibility container, single, tk
|
344
|
+
keep_comment = true
|
345
|
+
when 'attr' then
|
346
|
+
parse_attr container, single, tk, comment
|
347
|
+
when /^attr_(reader|writer|accessor)$/ then
|
348
|
+
parse_attr_accessor container, single, tk, comment
|
349
|
+
when 'alias_method' then
|
350
|
+
if container.document_self then
|
351
|
+
parse_alias container, single, tk, comment
|
352
|
+
end
|
353
|
+
when *RAILS_IDENTIFIERS then parse_rails_meta container, single, tk, comment
|
354
|
+
else
|
355
|
+
if container.document_self and comment =~ /\A#\#$/ then
|
356
|
+
parse_meta_method container, single, tk, comment
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
case tk.name
|
362
|
+
when "require" then
|
363
|
+
parse_require container, comment
|
364
|
+
when "include" then
|
365
|
+
parse_include container, comment
|
366
|
+
end
|
367
|
+
|
368
|
+
when TkEND then
|
369
|
+
nest -= 1
|
370
|
+
if nest == 0 then
|
371
|
+
read_documentation_modifiers container, RDoc::CLASS_MODIFIERS
|
372
|
+
container.ongoing_visibility = save_visibility
|
373
|
+
return
|
374
|
+
end
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
comment = '' unless keep_comment
|
379
|
+
|
380
|
+
begin
|
381
|
+
get_tkread
|
382
|
+
skip_tkspace(false)
|
383
|
+
end while peek_tk == TkNL
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../rdoc_rails')
|
2
|
+
|
3
|
+
Rake::RDocTask.remove_task('doc:app')
|
4
|
+
|
5
|
+
namespace :doc do
|
6
|
+
desc "Generate documentation for the application. Set custom template with TEMPLATE=/path/to/rdoc/template.rb Set custom format with FORMAT=format_name"
|
7
|
+
Rake::RDocTask.new('app') { |rdoc|
|
8
|
+
ENV['format'] ||= 'railsfish'
|
9
|
+
rdoc.rdoc_dir = 'doc/app'
|
10
|
+
rdoc.template = ENV['template'] if ENV['template']
|
11
|
+
rdoc.title = "Rails Application Documentation"
|
12
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
13
|
+
rdoc.options << '--charset' << 'utf-8'
|
14
|
+
rdoc.options << '--format' << ENV['format']
|
15
|
+
rdoc.rdoc_files.include('doc/README_FOR_APP')
|
16
|
+
rdoc.rdoc_files.include('app/**/*.rb')
|
17
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
18
|
+
}
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Comment < ActiveRecord::Base
|
2
|
+
# This will parse incorrectly, ignoring the definition
|
3
|
+
# of :class_name => "User"
|
4
|
+
belongs_to :commenter,
|
5
|
+
:class_name => "User",
|
6
|
+
:counter_cache => true
|
7
|
+
|
8
|
+
# This has no idea who or what commentable is.
|
9
|
+
belongs_to :commentable,
|
10
|
+
:polymorphic => true,
|
11
|
+
:counter_cache => true
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class RDocRailsTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
# test "should say hello" do
|
7
|
+
# puts 'hello'
|
8
|
+
# end
|
9
|
+
|
10
|
+
test "should do something" do
|
11
|
+
FileUtils.remove_dir("test/rdoc") if File.exists?("test/rdoc")
|
12
|
+
Rake::Task[:rdoc_test].invoke
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'rdoc'
|
2
|
+
require 'rdoc/rdoc'
|
3
|
+
#require 'rake'
|
4
|
+
#require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require File.dirname(__FILE__) + '/../../lib/rdoc_rails'
|
7
|
+
|
8
|
+
# Load Rails rakefile extensions
|
9
|
+
Dir["#{File.dirname(__FILE__)}/*.rake"].each { |ext| load ext }
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/test_case'
|
5
|
+
require 'active_record'
|
6
|
+
|
7
|
+
require 'tasks/testing'
|
8
|
+
$: << File.expand_path(File.dirname(__FILE__) + "/../lib/" )
|
9
|
+
require 'rdoc_rails'
|
10
|
+
|
11
|
+
$: << File.expand_path(File.dirname(__FILE__) + "/app/models/" )
|
12
|
+
%w( user blog post comment ).each{|m| require m }
|
13
|
+
|
14
|
+
#ActiveRecord::Base.establish_connection(
|
15
|
+
# :adapter => "sqlite3",
|
16
|
+
# :database => ":memory:")
|
17
|
+
#
|
18
|
+
#def setup_db
|
19
|
+
# ActiveRecord::Schema.define(:version => 1) do
|
20
|
+
# create_table :users do |t|
|
21
|
+
# end
|
22
|
+
# create_table :blogs do |t|
|
23
|
+
# t.references :user
|
24
|
+
# end
|
25
|
+
# create_table :posts do |t|
|
26
|
+
# t.references :blog
|
27
|
+
# t.references :user
|
28
|
+
# end
|
29
|
+
# create_table :comments do |t|
|
30
|
+
# t.references :commenter
|
31
|
+
# t.references :commentable, :polymorphic => true
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#end
|
35
|
+
#
|
36
|
+
#def teardown_db
|
37
|
+
# ActiveRecord::Base.connection.tables.each do |table|
|
38
|
+
# ActiveRecord::Base.connection.drop_table(table)
|
39
|
+
# end
|
40
|
+
#end
|
41
|
+
|
42
|
+
|
43
|
+
class ActiveSupport::TestCase
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
Rake::Task.class_eval do
|
49
|
+
|
50
|
+
# For some reason, a blank prerequisite is added
|
51
|
+
# which causes
|
52
|
+
# RuntimeError: Don't know how to build task ''
|
53
|
+
# so I make sure that they are gone
|
54
|
+
def invoke_prerequisites_with_compressing(
|
55
|
+
task_args, invocation_chain)
|
56
|
+
@prerequisites.delete_if{|a|a.blank?} # || a =~ /\A\s*\z/ }
|
57
|
+
invoke_prerequisites_without_compressing(
|
58
|
+
task_args, invocation_chain
|
59
|
+
)
|
60
|
+
end
|
61
|
+
alias_method_chain :invoke_prerequisites, :compressing
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
RDoc::Generator::Railsfish.class_eval do
|
67
|
+
def generate_class_files
|
68
|
+
debug_msg "Generating class documentation in #@outputdir"
|
69
|
+
|
70
|
+
# The pathname ends up being incorrect by "../."
|
71
|
+
# That's all it takes and since there is not apparent
|
72
|
+
# variable, I just override the method for testing.
|
73
|
+
|
74
|
+
templatefile = Pathname.new("../../lib/rdoc_rails/rdoc/generator/template/railsfish/classpage.rhtml")
|
75
|
+
|
76
|
+
@classes.each do |klass|
|
77
|
+
debug_msg " working on %s (%s)" % [ klass.full_name, klass.path ]
|
78
|
+
outfile = @outputdir + klass.path
|
79
|
+
rel_prefix = @outputdir.relative_path_from( outfile.dirname )
|
80
|
+
svninfo = self.get_svninfo( klass )
|
81
|
+
debug_msg " rendering #{outfile}"
|
82
|
+
self.render_template( templatefile, binding(), outfile )
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jakewendt-rdoc_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Chinasaur
|
14
|
+
- George 'Jake' Wendt
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2011-02-08 00:00:00 -08:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: rails
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 7
|
31
|
+
segments:
|
32
|
+
- 2
|
33
|
+
version: "2"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rdoc
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 7
|
45
|
+
segments:
|
46
|
+
- 2
|
47
|
+
version: "2"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
description: longer description of your gem
|
51
|
+
email: github@jakewendt.com
|
52
|
+
executables: []
|
53
|
+
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files:
|
57
|
+
- README.rdoc
|
58
|
+
files:
|
59
|
+
- lib/jakewendt-rdoc_rails.rb
|
60
|
+
- lib/rdoc_rails.rb
|
61
|
+
- lib/rdoc_rails/rake.rb
|
62
|
+
- lib/rdoc_rails/rdoc/ar_association.rb
|
63
|
+
- lib/rdoc_rails/rdoc/context.rb
|
64
|
+
- lib/rdoc_rails/rdoc/generator/railsfish.rb
|
65
|
+
- lib/rdoc_rails/rdoc/generator/template/railsfish/classpage.rhtml
|
66
|
+
- lib/rdoc_rails/rdoc/parser/rails.rb
|
67
|
+
- lib/rdoc_rails/rdoc/token_stream.rb
|
68
|
+
- lib/tasks/rdoc_rails.rake
|
69
|
+
- README.rdoc
|
70
|
+
- test/app/models/blog.rb
|
71
|
+
- test/app/models/comment.rb
|
72
|
+
- test/app/models/post.rb
|
73
|
+
- test/app/models/user.rb
|
74
|
+
- test/rdoc_rails_test.rb
|
75
|
+
- test/tasks/testing.rb
|
76
|
+
- test/test_helper.rb
|
77
|
+
has_rdoc: true
|
78
|
+
homepage: http://github.com/jakewendt/rdoc_rails
|
79
|
+
licenses: []
|
80
|
+
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
requirements: []
|
105
|
+
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.5.0
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: one-line summary of your gem
|
111
|
+
test_files:
|
112
|
+
- test/app/models/blog.rb
|
113
|
+
- test/app/models/comment.rb
|
114
|
+
- test/app/models/post.rb
|
115
|
+
- test/app/models/user.rb
|
116
|
+
- test/rdoc_rails_test.rb
|
117
|
+
- test/tasks/testing.rb
|
118
|
+
- test/test_helper.rb
|