annotator 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -4
- data/lib/annotator.rb +6 -180
- data/lib/annotator/attributes.rb +92 -0
- data/lib/annotator/initial_description.rb +23 -0
- data/lib/annotator/initial_description/base.rb +21 -0
- data/lib/annotator/initial_description/belongs_to.rb +29 -0
- data/lib/annotator/initial_description/devise.rb +39 -0
- data/lib/annotator/initial_description/paperclip.rb +26 -0
- data/lib/annotator/initial_description/rails.rb +23 -0
- data/lib/annotator/model.rb +57 -0
- data/lib/annotator/version.rb +1 -1
- data/test/annotator_test.rb +18 -8
- data/test/assets/boo_annotated.rb +4 -1
- data/test/assets/foo_require_first.rb +11 -0
- data/test/assets/moo_hoo_annotated.rb +13 -0
- data/test/dummy/app/models/boo.rb +1 -0
- data/test/dummy/app/models/moo/hoo.rb +6 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20120527025142_create_boos.rb +2 -0
- data/test/dummy/db/schema.rb +18 -1
- data/test/dummy/log/development.log +97 -0
- data/test/support/test_app.rb +19 -0
- data/test/test_helper.rb +5 -9
- metadata +19 -3
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -62,15 +62,14 @@ Of course similar thing happens when you remove column or change it's type.
|
|
62
62
|
* for some fields like title above you can just skip description including dash sometimes name is just obvious enough
|
63
63
|
* multiline comments are ok
|
64
64
|
* generating initial descriptions it understands things like
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
* belongs_to association columns
|
66
|
+
* devise columns
|
67
|
+
* paperclip colums
|
68
68
|
|
69
69
|
Contributions are very much welcome.
|
70
70
|
|
71
71
|
== Todos
|
72
72
|
|
73
|
-
* it could be written a bit cleaner
|
74
73
|
* since name does not have "model" in it, we could possibly use "rake routes" to annotate controller actions, not sure if it's worth it
|
75
74
|
|
76
75
|
== Authors
|
data/lib/annotator.rb
CHANGED
@@ -1,189 +1,15 @@
|
|
1
1
|
require 'annotator/railtie'
|
2
|
+
require 'annotator/model'
|
3
|
+
require 'annotator/attributes'
|
4
|
+
require 'annotator/initial_description'
|
2
5
|
|
3
6
|
module Annotator
|
4
|
-
def self.run
|
5
|
-
models = Dir.glob("#{Rails.root}/app/models/*.rb").map do |filename|
|
6
|
-
klass = filename.split('/').last.split(/\.rb$/).first.camelize.constantize
|
7
|
-
[filename, klass]
|
8
|
-
end.sort_by {|x| x.last.to_s}
|
9
|
-
|
10
|
-
|
11
|
-
models.each do |filename, model|
|
12
|
-
next unless model.ancestors.include? ActiveRecord::Base
|
13
|
-
begin
|
14
|
-
file = File.read(filename)
|
15
|
-
lines = file.split("\n")
|
16
|
-
out = ''
|
17
|
-
ia = false # inside attributes block
|
18
|
-
after_block = false # we are already after comments block
|
19
|
-
changed = false
|
20
|
-
skip_file = false
|
21
|
-
attrs_arr = []
|
22
|
-
lines.each do |line|
|
23
|
-
break if skip_file
|
24
|
-
out << "#{line}\n" && next if after_block
|
25
|
-
|
26
|
-
if ia && !line.match(/^# \*/) && !line.match(/^# \S/)
|
27
|
-
out << stringify_attrs_arr(update_attrs_arr(attrs_arr, model))
|
28
|
-
ia = false
|
29
|
-
changed = true
|
30
|
-
end
|
31
|
-
|
32
|
-
# check if we are still in the comments part of the file
|
33
|
-
unless line.strip.empty? || line.match(/^\s*#/)
|
34
|
-
after_block = true
|
35
|
-
unless changed
|
36
|
-
out << "# Attributes:\n"
|
37
|
-
out << stringify_attrs_arr(update_attrs_arr(attrs_arr, model))
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
if ia
|
42
|
-
if line.match(/^# \*/)
|
43
|
-
m = line.match(/^# \* (\w+) \[(.*?)\]( \- )?(.*)/)
|
44
|
-
if m
|
45
|
-
attrs_arr << [m[1], m[2], m[4]].map(&:strip)
|
46
|
-
else
|
47
|
-
puts "!! Unrecognized line format on attributes list in #{model}:"
|
48
|
-
puts line
|
49
|
-
end
|
50
|
-
else
|
51
|
-
attrs_arr[-1][2] << " #{line[4..-1]}"
|
52
|
-
end
|
53
|
-
else
|
54
|
-
out << "#{line}\n"
|
55
|
-
end
|
56
|
-
|
57
|
-
ia = true if line.match(/^# Attributes:/i)
|
58
|
-
skip_file = true if line.match(/^# Attributes\(nodoc\):/i)
|
59
|
-
end
|
60
|
-
|
61
|
-
File.open(filename,'w') { |f| f.write(out) } if out.strip != file.strip && !skip_file
|
62
|
-
|
63
|
-
rescue Exception => e
|
64
|
-
puts "FAILURE while trying to update model #{model}:\n #{e}"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
protected
|
72
|
-
|
73
|
-
def self.update_attrs_arr(arr, model)
|
74
|
-
arr = arr.dup
|
75
|
-
model.columns.each do |column|
|
76
|
-
attrs_str = column_attrs(column)
|
77
|
-
if row = arr.find {|x| x[0] == column.name}
|
78
|
-
if row[1] != attrs_str
|
79
|
-
puts " M #{model}##{column.name} [#{row[1]} -> #{attrs_str}]"
|
80
|
-
row[1] = attrs_str
|
81
|
-
end
|
82
|
-
else
|
83
|
-
puts " A #{model}##{column.name} [#{attrs_str}]"
|
84
|
-
desc = initial_description model, column
|
85
|
-
arr << [column.name, attrs_str, desc]
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# find columns that no more exist in db
|
90
|
-
orphans = arr.map(&:first) - model.columns.map(&:name)
|
91
|
-
unless orphans.empty?
|
92
|
-
orphans.each do |orphan|
|
93
|
-
puts " D #{model}#{orphan}"
|
94
|
-
arr = arr.select {|x| x[0] != orphan}
|
95
|
-
end
|
96
|
-
end
|
97
|
-
arr
|
98
|
-
end
|
99
7
|
|
100
|
-
def self.
|
101
|
-
|
102
|
-
|
103
|
-
when 'created_at' then return 'creation time'
|
104
|
-
when 'updated_at' then return 'last update time'
|
105
|
-
end
|
106
|
-
|
107
|
-
# TODO stop writing like it's functional lang and make class for Description ;)
|
108
|
-
|
109
|
-
# Belongs to association
|
110
|
-
model.reflect_on_all_associations.each do |reflect|
|
111
|
-
if reflect.foreign_key == column.name && reflect.macro == :belongs_to
|
112
|
-
return "belongs to #{reflect.klass}"
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# Devise column names
|
117
|
-
if model.respond_to? :devise_modules
|
118
|
-
devise_columns = {
|
119
|
-
:reset_password_token => "Devise Recoverable module",
|
120
|
-
:reset_password_sent_at => "Devise Recoverable module",
|
121
|
-
:remember_created_at => "Devise Rememberable module",
|
122
|
-
:sign_in_count => "Devise Trackable module",
|
123
|
-
:current_sign_in_at => "Devise Trackable module",
|
124
|
-
:last_sign_in_at => "Devise Trackable module",
|
125
|
-
:current_sign_in_ip => "Devise Trackable module",
|
126
|
-
:last_sign_in_ip => "Devise Trackable module",
|
127
|
-
:password_salt => "Devise Encriptable module",
|
128
|
-
:confirmation_token => "Devise Confirmable module",
|
129
|
-
:confirmed_at => "Devise Confirmable module",
|
130
|
-
:confiramtion_sent_at => "Devise Confirmable module",
|
131
|
-
:unconfirmed_email => "Devise Confirmable module",
|
132
|
-
:failed_attempts => "Devise Lockable module",
|
133
|
-
:unlock_token => "Devise Locakble module",
|
134
|
-
:locked_at => "Devise Lockable module",
|
135
|
-
:authentication_token => "Devise Token authenticable module"
|
136
|
-
}
|
137
|
-
guess = devise_columns[column.name.to_sym]
|
138
|
-
return guess if guess
|
139
|
-
end
|
140
|
-
|
141
|
-
# Paperclip column names
|
142
|
-
if model.respond_to? :attachments_definitions
|
143
|
-
model.attachments_definitions.keys.each do |att|
|
144
|
-
cols = ["#{att}_file_name", "#{att}_content_type", "#{att}_file_size", "#{att}_updated_at"]
|
145
|
-
return "Paperclip for #{att}" if cols.include? column.name
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
# let's not add "document me" note for these obvious ones:
|
150
|
-
return '' if %w{email name title body}.include? column.name
|
151
|
-
|
152
|
-
return 'TODO: document me'
|
153
|
-
end
|
154
|
-
|
155
|
-
def self.column_attrs(c)
|
156
|
-
ret = c.type.to_s
|
157
|
-
ret << ", primary" if c.primary
|
158
|
-
ret << ", default=#{c.default}" if c.default
|
159
|
-
ret << ", not null" unless c.null
|
160
|
-
ret << ", limit=#{c.limit}" if c.limit && (c.limit != 255 && c.type != :string)
|
161
|
-
ret
|
162
|
-
end
|
163
|
-
|
164
|
-
def self.stringify_attrs_arr(arr)
|
165
|
-
ret = ''
|
166
|
-
arr.sort_by{|x| x[0] == 'id' ? '_' : x[0]}.each do |name, attrs, desc|
|
167
|
-
# split into lines that don't exceed 80 chars
|
168
|
-
desc = " - #{desc}" unless desc.empty?
|
169
|
-
line = "# * #{name} [#{attrs}]#{desc}"
|
170
|
-
lt = wrap_text(line, opts[:max_chars_per_line]-3).split("\n")
|
171
|
-
line = ([lt[0]] + lt[1..-1].map{|x| "# #{x}"}).join("\n")
|
172
|
-
ret << "#{line}\n"
|
8
|
+
def self.run
|
9
|
+
Dir.glob("#{Rails.root}/app/models/**/*.rb").sort.map do |filename|
|
10
|
+
Model.new(filename).update!
|
173
11
|
end
|
174
|
-
ret
|
175
12
|
end
|
176
13
|
|
177
|
-
def self.wrap_text(txt, col)
|
178
|
-
txt.gsub(/(.{1,#{col}})( +|$)\n?|(.{#{col}})/,"\\1\\3\n")
|
179
|
-
end
|
180
|
-
|
181
|
-
def self.opts
|
182
|
-
{
|
183
|
-
:max_chars_per_line => 120
|
184
|
-
}
|
185
|
-
end
|
186
|
-
|
187
|
-
|
188
14
|
end
|
189
15
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Annotator
|
2
|
+
|
3
|
+
# Attributes within given model file
|
4
|
+
class Attributes
|
5
|
+
R_ATTRIBUTE = /^# \* (\w+) \[(.*?)\]( \- )?(.*)$/
|
6
|
+
R_ATTRIBUTE_NEXT_LINE = /^# (.*?)$/
|
7
|
+
R_ATTRIBUTE_LINE = /(#{R_ATTRIBUTE})|(#{R_ATTRIBUTE_NEXT_LINE})/
|
8
|
+
HEADER = "# Attributes:"
|
9
|
+
MAX_CHARS_PER_LINE = 120
|
10
|
+
|
11
|
+
def initialize(model, lines)
|
12
|
+
@model = model
|
13
|
+
@lines = lines
|
14
|
+
@attrs = []
|
15
|
+
@changes = []
|
16
|
+
parse
|
17
|
+
end
|
18
|
+
|
19
|
+
# Convert attributes array back to attributes lines representation to be put into file
|
20
|
+
def lines
|
21
|
+
ret = [Attributes::HEADER]
|
22
|
+
# Sort by name, but id goes first
|
23
|
+
@attrs.sort_by{|x| x[:name] == 'id' ? '_' : x[:name]}.each do |row|
|
24
|
+
line = "# * #{row[:name]} [#{row[:type]}]#{row[:desc].to_s.empty? ? "" : " - #{row[:desc]}"}"
|
25
|
+
# split into lines that don't exceed 80 chars
|
26
|
+
lt = wrap_text(line, MAX_CHARS_PER_LINE-3).split("\n")
|
27
|
+
line = ([lt[0]] + lt[1..-1].map{|x| "# #{x}"}).join("\n")
|
28
|
+
ret << line
|
29
|
+
end
|
30
|
+
ret
|
31
|
+
end
|
32
|
+
|
33
|
+
# Update attribudes array to the current database state
|
34
|
+
def update!
|
35
|
+
@model.columns.each do |column|
|
36
|
+
if row = @attrs.find {|x| x[:name] == column.name}
|
37
|
+
if row[:type] != type_str(column)
|
38
|
+
puts " M #{@model}##{column.name} [#{row[:type]} -> #{type_str(column)}]"
|
39
|
+
row[:type] = type_str(column)
|
40
|
+
end
|
41
|
+
else
|
42
|
+
puts " A #{@model}##{column.name} [#{type_str(column)}]"
|
43
|
+
@attrs << {
|
44
|
+
:name => column.name,
|
45
|
+
:type => type_str(column),
|
46
|
+
:desc => InitialDescription.for(@model, column.name)
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# find columns that no more exist in db
|
52
|
+
orphans = @attrs.map{|x| x[:name]} - @model.columns.map(&:name)
|
53
|
+
unless orphans.empty?
|
54
|
+
orphans.each do |orphan|
|
55
|
+
puts " D #{@model}#{orphan}"
|
56
|
+
@attrs = @attrs.select {|x| x[0] != orphan}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
@attrs
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
# Convert attributes lines into meaniningful array
|
66
|
+
def parse
|
67
|
+
@lines.each do |line|
|
68
|
+
if m = line.match(R_ATTRIBUTE)
|
69
|
+
@attrs << {:name => m[1].strip, :type => m[2].strip, :desc => m[4].strip}
|
70
|
+
elsif m = line.match(R_ATTRIBUTE_NEXT_LINE)
|
71
|
+
@attrs[-1][:desc] += " #{m[1].strip}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Human readable description of given column type
|
77
|
+
def type_str(c)
|
78
|
+
ret = c.type.to_s
|
79
|
+
ret << ", primary" if c.primary
|
80
|
+
ret << ", default=#{c.default}" if c.default
|
81
|
+
ret << ", not null" unless c.null
|
82
|
+
ret << ", limit=#{c.limit}" if c.limit && (c.limit != 255 && c.type != :string)
|
83
|
+
ret
|
84
|
+
end
|
85
|
+
|
86
|
+
# Wraps text nicely, not breaking in the middle of the word
|
87
|
+
def wrap_text(txt, col)
|
88
|
+
txt.gsub(/(.{1,#{col}})( +|$)\n?|(.{#{col}})/,"\\1\\3\n")
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'annotator/initial_description/base'
|
2
|
+
Dir[File.dirname(__FILE__) + '/initial_description/*.rb'].each {|file| require file }
|
3
|
+
|
4
|
+
module Annotator
|
5
|
+
module InitialDescription
|
6
|
+
|
7
|
+
NO_DESCRIPTION_COLUMNS = %w{email name title body}
|
8
|
+
|
9
|
+
# Get initial description for given model & column
|
10
|
+
def self.for(model, column)
|
11
|
+
# Check if any module provides such description
|
12
|
+
Base.providers.each do |klass|
|
13
|
+
provider = klass.new model, column
|
14
|
+
return provider.text if provider.check
|
15
|
+
end
|
16
|
+
# Some columns are just too obvious
|
17
|
+
return "" if NO_DESCRIPTION_COLUMNS.include? column
|
18
|
+
# Let user do the work
|
19
|
+
return "TODO: document me"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Annotator
|
2
|
+
module InitialDescription
|
3
|
+
|
4
|
+
# Base class from which all other description providers inherit
|
5
|
+
class Base
|
6
|
+
def initialize(model, column)
|
7
|
+
@model = model
|
8
|
+
@column = column
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.inherited(klass)
|
12
|
+
@providers ||= []
|
13
|
+
@providers << klass
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.providers
|
17
|
+
@providers
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Annotator
|
2
|
+
module InitialDescription
|
3
|
+
|
4
|
+
# Initial descriptions for columns associated with belongs_to
|
5
|
+
class BelongsTo < Base
|
6
|
+
|
7
|
+
def check
|
8
|
+
# check if there is belongs to association where this column is a foreign key
|
9
|
+
@model.reflect_on_all_associations.each do |reflection|
|
10
|
+
if reflection.foreign_key == @column && reflection.macro == :belongs_to
|
11
|
+
@reflection = reflection
|
12
|
+
return true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Polymorphic association type column
|
17
|
+
if @column.ends_with? '_type'
|
18
|
+
return true if @reflection = @model.reflect_on_association(@column.match(/(.*?)_type$/)[1].to_sym)
|
19
|
+
end
|
20
|
+
|
21
|
+
return false
|
22
|
+
end
|
23
|
+
|
24
|
+
def text
|
25
|
+
"belongs to :#{@reflection.name}#{@reflection.options[:polymorphic] ? ' (polymorphic)' : ''}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Annotator
|
2
|
+
module InitialDescription
|
3
|
+
|
4
|
+
# Initila descriptions for devise specific columns
|
5
|
+
class Devise < Base
|
6
|
+
|
7
|
+
def check
|
8
|
+
@model.respond_to?(:devise_modules) && columns.keys.include?(@column.to_sym)
|
9
|
+
end
|
10
|
+
|
11
|
+
def columns
|
12
|
+
{
|
13
|
+
:reset_password_token => "Devise Recoverable module",
|
14
|
+
:reset_password_sent_at => "Devise Recoverable module",
|
15
|
+
:remember_created_at => "Devise Rememberable module",
|
16
|
+
:sign_in_count => "Devise Trackable module",
|
17
|
+
:current_sign_in_at => "Devise Trackable module",
|
18
|
+
:last_sign_in_at => "Devise Trackable module",
|
19
|
+
:current_sign_in_ip => "Devise Trackable module",
|
20
|
+
:last_sign_in_ip => "Devise Trackable module",
|
21
|
+
:password_salt => "Devise Encriptable module",
|
22
|
+
:confirmation_token => "Devise Confirmable module",
|
23
|
+
:confirmed_at => "Devise Confirmable module",
|
24
|
+
:confiramtion_sent_at => "Devise Confirmable module",
|
25
|
+
:unconfirmed_email => "Devise Confirmable module",
|
26
|
+
:failed_attempts => "Devise Lockable module",
|
27
|
+
:unlock_token => "Devise Locakble module",
|
28
|
+
:locked_at => "Devise Lockable module",
|
29
|
+
:authentication_token => "Devise Token authenticable module"
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def text
|
34
|
+
columns[@column.to_sym]
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Annotator
|
2
|
+
module InitialDescription
|
3
|
+
|
4
|
+
# Initial descriptinos for paperclip attachments columns
|
5
|
+
class Paperclip < Base
|
6
|
+
|
7
|
+
def check
|
8
|
+
if @model.respond_to? :attachments_definitions
|
9
|
+
@model.attachments_definitions.keys.each do |att|
|
10
|
+
cols = ["#{att}_file_name", "#{att}_content_type", "#{att}_file_size", "#{att}_updated_at"]
|
11
|
+
if cols.include? @column
|
12
|
+
@attachment = att
|
13
|
+
return true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
|
20
|
+
def text
|
21
|
+
"Paperclip for #{@attachment}"
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Annotator
|
2
|
+
module InitialDescription
|
3
|
+
|
4
|
+
# Initial descriptions for rails specific columns
|
5
|
+
class Rails < Base
|
6
|
+
def check
|
7
|
+
columns.keys.include? @column.to_sym
|
8
|
+
end
|
9
|
+
|
10
|
+
def columns
|
11
|
+
{
|
12
|
+
:id => "primary key", # TODO check if it actually is a primary key, find primary keys with other names
|
13
|
+
:created_at => "creation time",
|
14
|
+
:updated_at => "last update time"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def text
|
19
|
+
columns[@column.to_sym]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Annotator
|
2
|
+
|
3
|
+
# Represents a single model file and associated class
|
4
|
+
class Model
|
5
|
+
|
6
|
+
def initialize(filename)
|
7
|
+
@filename = filename
|
8
|
+
@blocks = Hash.new {[]}
|
9
|
+
end
|
10
|
+
|
11
|
+
# Model class
|
12
|
+
def klass
|
13
|
+
@filename.split('app/models/').last.split(/\.rb$/).first.camelize.constantize rescue nil
|
14
|
+
end
|
15
|
+
|
16
|
+
# Split file into 3 blocks: before attributes, attributes block, and after
|
17
|
+
# If there's no attributes block, content will be in :after part (for easier insertion)
|
18
|
+
def parse
|
19
|
+
@file = File.read(@filename).strip
|
20
|
+
current_block = :before
|
21
|
+
return @nodoc = true if @file.match(/^# Attributes\(nodoc\):$/i)
|
22
|
+
@file.split("\n").each do |line|
|
23
|
+
if line.match(/^#{Regexp.escape Attributes::HEADER} *$/)
|
24
|
+
current_block = :attributes
|
25
|
+
next
|
26
|
+
end
|
27
|
+
current_block = :after if current_block == :attributes && !line.match(Attributes::R_ATTRIBUTE_LINE)
|
28
|
+
@blocks[current_block] += [line]
|
29
|
+
end
|
30
|
+
|
31
|
+
@blocks[:after], @blocks[:before] = @blocks[:before], [] if @blocks[:after].empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
# If this file does not have associated AR class it should be skipped
|
35
|
+
def skipped?
|
36
|
+
!klass || !klass.ancestors.include?(ActiveRecord::Base) || @nodoc
|
37
|
+
end
|
38
|
+
|
39
|
+
# Save changes to file if there were any
|
40
|
+
def update_file
|
41
|
+
output = (@blocks[:before] + @blocks[:attributes] + @blocks[:after]).join("\n").strip + "\n"
|
42
|
+
File.open(@filename,'w') { |f| f.write(output) } if output != @file
|
43
|
+
end
|
44
|
+
|
45
|
+
# Update file with new database information
|
46
|
+
def update!
|
47
|
+
parse
|
48
|
+
return true if skipped?
|
49
|
+
attributes = Attributes.new klass, @blocks[:attributes]
|
50
|
+
attributes.update!
|
51
|
+
@blocks[:attributes] = attributes.lines
|
52
|
+
update_file
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
data/lib/annotator/version.rb
CHANGED
data/test/annotator_test.rb
CHANGED
@@ -3,7 +3,7 @@ require 'tempfile'
|
|
3
3
|
|
4
4
|
class AnnotatorTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
|
-
@output = execute("
|
6
|
+
@output = execute("rake annotate")
|
7
7
|
end
|
8
8
|
|
9
9
|
test "annotating foo" do
|
@@ -12,13 +12,13 @@ class AnnotatorTest < ActiveSupport::TestCase
|
|
12
12
|
|
13
13
|
test "leaving existing comments" do
|
14
14
|
FileUtils.cp asset_file('foo_annotated_with_comments.rb'), app_file('foo.rb')
|
15
|
-
|
15
|
+
execute "rake annotate"
|
16
16
|
assert_equal File.read(asset_file 'foo_annotated_with_comments.rb' ), File.read(app_file 'foo.rb' )
|
17
17
|
end
|
18
18
|
|
19
19
|
test "updating column type" do
|
20
20
|
FileUtils.cp asset_file('foo_annotated_bad_column.rb'), app_file('foo.rb')
|
21
|
-
output = execute
|
21
|
+
output = execute "rake annotate"
|
22
22
|
assert_equal File.read(asset_file 'foo_annotated_column_fixed.rb' ), File.read(app_file 'foo.rb' )
|
23
23
|
assert output.include?('M Foo#title [octopus -> string]')
|
24
24
|
assert output.include?('M Foo#created_at [foobar -> datetime, not null]')
|
@@ -26,34 +26,44 @@ class AnnotatorTest < ActiveSupport::TestCase
|
|
26
26
|
|
27
27
|
test "skipping when nodoc is preesnt" do
|
28
28
|
FileUtils.cp asset_file('foo_annotated_bad_column_nodoc.rb'), app_file('foo.rb')
|
29
|
-
execute
|
29
|
+
execute "rake annotate"
|
30
30
|
assert_equal File.read(asset_file 'foo_annotated_bad_column_nodoc.rb' ), File.read(app_file 'foo.rb' )
|
31
31
|
end
|
32
32
|
|
33
33
|
test "annotating devise columns" do
|
34
34
|
assert_equal File.read(asset_file 'user_annotated.rb' ), File.read(app_file 'user.rb' )
|
35
|
-
end
|
35
|
+
end
|
36
36
|
|
37
37
|
test "annotating paperclip columns" do
|
38
38
|
assert_equal File.read(asset_file 'paper_annotated.rb' ), File.read(app_file 'paper.rb' )
|
39
39
|
end
|
40
40
|
|
41
|
-
test "annotating belongs_to associations" do
|
41
|
+
test "annotating belongs_to and polymorphic associations" do
|
42
42
|
assert_equal File.read(asset_file 'boo_annotated.rb' ), File.read(app_file 'boo.rb' )
|
43
43
|
end
|
44
44
|
|
45
|
+
test "handling some code before annotitions block" do
|
46
|
+
FileUtils.cp asset_file('foo_require_first.rb'), app_file('foo.rb')
|
47
|
+
execute "rake annotate"
|
48
|
+
assert_equal File.read(asset_file 'foo_require_first.rb' ), File.read(app_file 'foo.rb' )
|
49
|
+
end
|
50
|
+
|
51
|
+
test "annotating namespaced models" do
|
52
|
+
assert_equal File.read(asset_file 'moo_hoo_annotated.rb' ), File.read(app_file 'moo/hoo.rb' )
|
53
|
+
end
|
54
|
+
|
45
55
|
def asset_file(name)
|
46
56
|
File.join(File.expand_path("../assets/", __FILE__), name)
|
47
57
|
end
|
48
58
|
|
49
59
|
def app_file(name)
|
50
|
-
File.join(
|
60
|
+
File.join(TestApp.path,'app','models',name)
|
51
61
|
end
|
52
62
|
|
53
63
|
# Check exit code while grabbing output
|
54
64
|
def execute(command)
|
55
65
|
tmp = Tempfile.new "output"
|
56
|
-
assert system("#{command} > #{tmp.path}")
|
66
|
+
assert system("cd #{TestApp.path} && #{command} > #{tmp.path}")
|
57
67
|
output = tmp.read
|
58
68
|
tmp.unlink
|
59
69
|
output
|
@@ -1,8 +1,11 @@
|
|
1
1
|
# Attributes:
|
2
2
|
# * id [integer, primary, not null] - primary key
|
3
3
|
# * created_at [datetime, not null] - creation time
|
4
|
-
# * foo_id [integer] - belongs to
|
4
|
+
# * foo_id [integer] - belongs to :foo
|
5
|
+
# * poly_id [integer] - belongs to :poly (polymorphic)
|
6
|
+
# * poly_type [string] - belongs to :poly (polymorphic)
|
5
7
|
# * updated_at [datetime, not null] - last update time
|
6
8
|
class Boo < ActiveRecord::Base
|
7
9
|
belongs_to :foo
|
10
|
+
belongs_to :poly, :polymorphic => true
|
8
11
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
# Attributes:
|
4
|
+
# * id [integer, primary, not null] - primary key
|
5
|
+
# * body [text]
|
6
|
+
# * created_at [datetime, not null] - creation time
|
7
|
+
# * random_number [integer] - TODO: document me
|
8
|
+
# * title [string]
|
9
|
+
# * updated_at [datetime, not null] - last update time
|
10
|
+
class Foo < ActiveRecord::Base
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Attributes:
|
2
|
+
# * id [integer, primary, not null] - primary key
|
3
|
+
# * body [text]
|
4
|
+
# * created_at [datetime, not null] - creation time
|
5
|
+
# * random_number [integer] - TODO: document me
|
6
|
+
# * title [string]
|
7
|
+
# * updated_at [datetime, not null] - last update time
|
8
|
+
# Some existing stupid comment
|
9
|
+
module Moo
|
10
|
+
class Hoo < ActiveRecord::Base
|
11
|
+
self.table_name = 'foos'
|
12
|
+
end
|
13
|
+
end
|
Binary file
|
data/test/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,15 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended to check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:version =>
|
14
|
+
ActiveRecord::Schema.define(:version => 20120527025142) do
|
15
|
+
|
16
|
+
create_table "boos", :force => true do |t|
|
17
|
+
t.integer "foo_id"
|
18
|
+
t.integer "poly_id"
|
19
|
+
t.string "poly_type"
|
20
|
+
t.datetime "created_at", :null => false
|
21
|
+
t.datetime "updated_at", :null => false
|
22
|
+
end
|
15
23
|
|
16
24
|
create_table "foos", :force => true do |t|
|
17
25
|
t.text "body"
|
@@ -21,6 +29,15 @@ ActiveRecord::Schema.define(:version => 20120527020350) do
|
|
21
29
|
t.datetime "updated_at", :null => false
|
22
30
|
end
|
23
31
|
|
32
|
+
create_table "papers", :force => true do |t|
|
33
|
+
t.datetime "created_at", :null => false
|
34
|
+
t.datetime "updated_at", :null => false
|
35
|
+
t.string "avatar_file_name"
|
36
|
+
t.string "avatar_content_type"
|
37
|
+
t.integer "avatar_file_size"
|
38
|
+
t.datetime "avatar_updated_at"
|
39
|
+
end
|
40
|
+
|
24
41
|
create_table "users", :force => true do |t|
|
25
42
|
t.string "email", :default => "", :null => false
|
26
43
|
t.string "encrypted_password", :default => "", :null => false
|
@@ -71,3 +71,100 @@ Migrating to DeviseCreateUsers (20120527020350)
|
|
71
71
|
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_confirmation_token')
|
72
72
|
[1m[36m (0.0ms)[0m [1mPRAGMA index_info('index_users_on_reset_password_token')[0m
|
73
73
|
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_email')
|
74
|
+
[1m[36m (0.1ms)[0m [1mSELECT "schema_migrations"."version" FROM "schema_migrations" [0m
|
75
|
+
Migrating to CreateFoos (20120219112425)
|
76
|
+
Migrating to DeviseCreateUsers (20120527020350)
|
77
|
+
Migrating to CreatePapers (20120527023350)
|
78
|
+
[1m[35m (0.0ms)[0m select sqlite_version(*)
|
79
|
+
[1m[36m (0.0ms)[0m [1mbegin transaction[0m
|
80
|
+
[1m[35m (0.2ms)[0m CREATE TABLE "papers" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL)
|
81
|
+
[1m[36m (0.1ms)[0m [1mINSERT INTO "schema_migrations" ("version") VALUES ('20120527023350')[0m
|
82
|
+
[1m[35m (5.4ms)[0m commit transaction
|
83
|
+
Migrating to AddAttachmentAvatarToPapers (20120527023417)
|
84
|
+
[1m[36m (0.0ms)[0m [1mbegin transaction[0m
|
85
|
+
[1m[35m (0.3ms)[0m ALTER TABLE "papers" ADD "avatar_file_name" varchar(255)
|
86
|
+
[1m[36m (0.2ms)[0m [1mALTER TABLE "papers" ADD "avatar_content_type" varchar(255)[0m
|
87
|
+
[1m[35m (0.2ms)[0m ALTER TABLE "papers" ADD "avatar_file_size" integer
|
88
|
+
[1m[36m (0.2ms)[0m [1mALTER TABLE "papers" ADD "avatar_updated_at" datetime[0m
|
89
|
+
[1m[35m (0.1ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ('20120527023417')
|
90
|
+
[1m[36m (3.8ms)[0m [1mcommit transaction[0m
|
91
|
+
Migrating to CreateBoos (20120527025142)
|
92
|
+
[1m[35m (0.0ms)[0m begin transaction
|
93
|
+
[1m[36m (0.4ms)[0m [1mCREATE TABLE "boos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "foo_id" integer, "poly_id" integer, "poly_type" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL) [0m
|
94
|
+
[1m[35m (0.1ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ('20120527025142')
|
95
|
+
[1m[36m (4.0ms)[0m [1mcommit transaction[0m
|
96
|
+
[1m[35m (0.4ms)[0m select sqlite_version(*)
|
97
|
+
[1m[36m (0.1ms)[0m [1mSELECT "schema_migrations"."version" FROM "schema_migrations" [0m
|
98
|
+
[1m[35m (0.0ms)[0m PRAGMA index_list("boos")
|
99
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_list("foos")[0m
|
100
|
+
[1m[35m (0.0ms)[0m PRAGMA index_list("papers")
|
101
|
+
[1m[36m (0.1ms)[0m [1mPRAGMA index_list("users")[0m
|
102
|
+
[1m[35m (0.1ms)[0m PRAGMA index_info('index_users_on_authentication_token')
|
103
|
+
[1m[36m (0.1ms)[0m [1mPRAGMA index_info('index_users_on_unlock_token')[0m
|
104
|
+
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_confirmation_token')
|
105
|
+
[1m[36m (0.1ms)[0m [1mPRAGMA index_info('index_users_on_reset_password_token')[0m
|
106
|
+
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_email')
|
107
|
+
[1m[36m (0.1ms)[0m [1mselect sqlite_version(*)[0m
|
108
|
+
[1m[35m (14.9ms)[0m CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL)
|
109
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_list("schema_migrations")[0m
|
110
|
+
[1m[35m (4.1ms)[0m CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
|
111
|
+
[1m[36m (0.1ms)[0m [1mSELECT "schema_migrations"."version" FROM "schema_migrations" [0m
|
112
|
+
Migrating to CreateFoos (20120219112425)
|
113
|
+
[1m[35m (0.0ms)[0m begin transaction
|
114
|
+
[1m[36m (0.4ms)[0m [1mCREATE TABLE "foos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "body" text, "title" varchar(255), "random_number" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL) [0m
|
115
|
+
[1m[35m (0.1ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ('20120219112425')
|
116
|
+
[1m[36m (7.1ms)[0m [1mcommit transaction[0m
|
117
|
+
Migrating to DeviseCreateUsers (20120527020350)
|
118
|
+
[1m[35m (0.0ms)[0m begin transaction
|
119
|
+
[1m[36m (0.4ms)[0m [1mCREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "email" varchar(255) DEFAULT '' NOT NULL, "encrypted_password" varchar(255) DEFAULT '' NOT NULL, "reset_password_token" varchar(255), "reset_password_sent_at" datetime, "remember_created_at" datetime, "sign_in_count" integer DEFAULT 0, "current_sign_in_at" datetime, "last_sign_in_at" datetime, "current_sign_in_ip" varchar(255), "last_sign_in_ip" varchar(255), "password_salt" varchar(255), "confirmation_token" varchar(255), "confirmed_at" datetime, "confirmation_sent_at" datetime, "unconfirmed_email" varchar(255), "failed_attempts" integer DEFAULT 0, "unlock_token" varchar(255), "locked_at" datetime, "authentication_token" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL) [0m
|
120
|
+
[1m[35m (0.0ms)[0m PRAGMA index_list("users")
|
121
|
+
[1m[36m (0.3ms)[0m [1mCREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email")[0m
|
122
|
+
[1m[35m (0.1ms)[0m PRAGMA index_list("users")
|
123
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_info('index_users_on_email')[0m
|
124
|
+
[1m[35m (0.2ms)[0m CREATE UNIQUE INDEX "index_users_on_reset_password_token" ON "users" ("reset_password_token")
|
125
|
+
[1m[36m (0.1ms)[0m [1mPRAGMA index_list("users")[0m
|
126
|
+
[1m[35m (0.1ms)[0m PRAGMA index_info('index_users_on_reset_password_token')
|
127
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_info('index_users_on_email')[0m
|
128
|
+
[1m[35m (0.2ms)[0m CREATE UNIQUE INDEX "index_users_on_confirmation_token" ON "users" ("confirmation_token")
|
129
|
+
[1m[36m (0.1ms)[0m [1mPRAGMA index_list("users")[0m
|
130
|
+
[1m[35m (0.1ms)[0m PRAGMA index_info('index_users_on_confirmation_token')
|
131
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_info('index_users_on_reset_password_token')[0m
|
132
|
+
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_email')
|
133
|
+
[1m[36m (0.2ms)[0m [1mCREATE UNIQUE INDEX "index_users_on_unlock_token" ON "users" ("unlock_token")[0m
|
134
|
+
[1m[35m (0.1ms)[0m PRAGMA index_list("users")
|
135
|
+
[1m[36m (0.1ms)[0m [1mPRAGMA index_info('index_users_on_unlock_token')[0m
|
136
|
+
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_confirmation_token')
|
137
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_info('index_users_on_reset_password_token')[0m
|
138
|
+
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_email')
|
139
|
+
[1m[36m (0.2ms)[0m [1mCREATE UNIQUE INDEX "index_users_on_authentication_token" ON "users" ("authentication_token")[0m
|
140
|
+
[1m[35m (0.1ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ('20120527020350')
|
141
|
+
[1m[36m (3.8ms)[0m [1mcommit transaction[0m
|
142
|
+
Migrating to CreatePapers (20120527023350)
|
143
|
+
[1m[35m (0.0ms)[0m begin transaction
|
144
|
+
[1m[36m (0.2ms)[0m [1mCREATE TABLE "papers" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL) [0m
|
145
|
+
[1m[35m (0.1ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ('20120527023350')
|
146
|
+
[1m[36m (3.8ms)[0m [1mcommit transaction[0m
|
147
|
+
Migrating to AddAttachmentAvatarToPapers (20120527023417)
|
148
|
+
[1m[35m (0.0ms)[0m begin transaction
|
149
|
+
[1m[36m (0.3ms)[0m [1mALTER TABLE "papers" ADD "avatar_file_name" varchar(255)[0m
|
150
|
+
[1m[35m (0.1ms)[0m ALTER TABLE "papers" ADD "avatar_content_type" varchar(255)
|
151
|
+
[1m[36m (0.2ms)[0m [1mALTER TABLE "papers" ADD "avatar_file_size" integer[0m
|
152
|
+
[1m[35m (0.2ms)[0m ALTER TABLE "papers" ADD "avatar_updated_at" datetime
|
153
|
+
[1m[36m (0.1ms)[0m [1mINSERT INTO "schema_migrations" ("version") VALUES ('20120527023417')[0m
|
154
|
+
[1m[35m (3.2ms)[0m commit transaction
|
155
|
+
Migrating to CreateBoos (20120527025142)
|
156
|
+
[1m[36m (0.0ms)[0m [1mbegin transaction[0m
|
157
|
+
[1m[35m (0.3ms)[0m CREATE TABLE "boos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "foo_id" integer, "poly_id" integer, "poly_type" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL)
|
158
|
+
[1m[36m (0.1ms)[0m [1mINSERT INTO "schema_migrations" ("version") VALUES ('20120527025142')[0m
|
159
|
+
[1m[35m (3.7ms)[0m commit transaction
|
160
|
+
[1m[36m (0.4ms)[0m [1mselect sqlite_version(*)[0m
|
161
|
+
[1m[35m (0.1ms)[0m SELECT "schema_migrations"."version" FROM "schema_migrations"
|
162
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_list("boos")[0m
|
163
|
+
[1m[35m (0.0ms)[0m PRAGMA index_list("foos")
|
164
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_list("papers")[0m
|
165
|
+
[1m[35m (0.0ms)[0m PRAGMA index_list("users")
|
166
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_info('index_users_on_authentication_token')[0m
|
167
|
+
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_unlock_token')
|
168
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_info('index_users_on_confirmation_token')[0m
|
169
|
+
[1m[35m (0.0ms)[0m PRAGMA index_info('index_users_on_reset_password_token')
|
170
|
+
[1m[36m (0.0ms)[0m [1mPRAGMA index_info('index_users_on_email')[0m
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module TestApp
|
2
|
+
|
3
|
+
# No mattr_accessor before initialization ;(
|
4
|
+
def self.path=(new_path)
|
5
|
+
@path = new_path
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.path
|
9
|
+
@path
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.prepare!
|
13
|
+
self.path = File.expand_path("../../../tmp/dummy", __FILE__)
|
14
|
+
FileUtils.rm_rf path
|
15
|
+
FileUtils.mkdir_p path
|
16
|
+
FileUtils.cp_r File.expand_path("../../dummy//", __FILE__), File.expand_path(path+"/../")
|
17
|
+
system("cd #{path} && bundle exec rake db:migrate > /dev/null")
|
18
|
+
end
|
19
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -3,17 +3,13 @@ require 'fileutils'
|
|
3
3
|
# Configure Rails Environment
|
4
4
|
ENV["RAILS_ENV"] = "test"
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
system("cd #{$test_app} && bundle exec rake db:migrate > /dev/null")
|
11
|
-
|
6
|
+
# Load support files
|
7
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
8
|
+
|
9
|
+
TestApp.prepare!
|
12
10
|
|
13
|
-
require File.expand_path("#{
|
11
|
+
require File.expand_path("#{TestApp.path}/config/environment.rb", __FILE__)
|
14
12
|
require "rails/test_help"
|
15
13
|
|
16
14
|
Rails.backtrace_cleaner.remove_silencers!
|
17
15
|
|
18
|
-
# Load support files
|
19
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: annotator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-05
|
13
|
+
date: 2012-06-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
@@ -53,11 +53,20 @@ extra_rdoc_files: []
|
|
53
53
|
files:
|
54
54
|
- lib/tasks/annotator_tasks.rake
|
55
55
|
- lib/annotator.rb
|
56
|
+
- lib/annotator/initial_description/belongs_to.rb
|
57
|
+
- lib/annotator/initial_description/devise.rb
|
58
|
+
- lib/annotator/initial_description/paperclip.rb
|
59
|
+
- lib/annotator/initial_description/base.rb
|
60
|
+
- lib/annotator/initial_description/rails.rb
|
61
|
+
- lib/annotator/model.rb
|
56
62
|
- lib/annotator/version.rb
|
63
|
+
- lib/annotator/attributes.rb
|
64
|
+
- lib/annotator/initial_description.rb
|
57
65
|
- lib/annotator/railtie.rb
|
58
66
|
- MIT-LICENSE
|
59
67
|
- Rakefile
|
60
68
|
- README.rdoc
|
69
|
+
- test/support/test_app.rb
|
61
70
|
- test/test_helper.rb
|
62
71
|
- test/assets/paper_annotated.rb
|
63
72
|
- test/assets/foo_annotated_bad_column.rb
|
@@ -67,6 +76,8 @@ files:
|
|
67
76
|
- test/assets/boo_annotated.rb
|
68
77
|
- test/assets/foo_annotated.rb
|
69
78
|
- test/assets/foo_annotated_column_fixed.rb
|
79
|
+
- test/assets/foo_require_first.rb
|
80
|
+
- test/assets/moo_hoo_annotated.rb
|
70
81
|
- test/annotator_test.rb
|
71
82
|
- test/dummy/public/500.html
|
72
83
|
- test/dummy/public/favicon.ico
|
@@ -93,6 +104,7 @@ files:
|
|
93
104
|
- test/dummy/app/helpers/application_helper.rb
|
94
105
|
- test/dummy/app/models/boo.rb
|
95
106
|
- test/dummy/app/models/paper.rb
|
107
|
+
- test/dummy/app/models/moo/hoo.rb
|
96
108
|
- test/dummy/app/models/user.rb
|
97
109
|
- test/dummy/app/models/foo.rb
|
98
110
|
- test/dummy/app/models/nomodel.rb
|
@@ -138,11 +150,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
150
|
version: '0'
|
139
151
|
requirements: []
|
140
152
|
rubyforge_project:
|
141
|
-
rubygems_version: 1.8.
|
153
|
+
rubygems_version: 1.8.23
|
142
154
|
signing_key:
|
143
155
|
specification_version: 3
|
144
156
|
summary: Annotate your models and keep your comments about fields.
|
145
157
|
test_files:
|
158
|
+
- test/support/test_app.rb
|
146
159
|
- test/test_helper.rb
|
147
160
|
- test/assets/paper_annotated.rb
|
148
161
|
- test/assets/foo_annotated_bad_column.rb
|
@@ -152,6 +165,8 @@ test_files:
|
|
152
165
|
- test/assets/boo_annotated.rb
|
153
166
|
- test/assets/foo_annotated.rb
|
154
167
|
- test/assets/foo_annotated_column_fixed.rb
|
168
|
+
- test/assets/foo_require_first.rb
|
169
|
+
- test/assets/moo_hoo_annotated.rb
|
155
170
|
- test/annotator_test.rb
|
156
171
|
- test/dummy/public/500.html
|
157
172
|
- test/dummy/public/favicon.ico
|
@@ -178,6 +193,7 @@ test_files:
|
|
178
193
|
- test/dummy/app/helpers/application_helper.rb
|
179
194
|
- test/dummy/app/models/boo.rb
|
180
195
|
- test/dummy/app/models/paper.rb
|
196
|
+
- test/dummy/app/models/moo/hoo.rb
|
181
197
|
- test/dummy/app/models/user.rb
|
182
198
|
- test/dummy/app/models/foo.rb
|
183
199
|
- test/dummy/app/models/nomodel.rb
|