-
Notifications
You must be signed in to change notification settings - Fork 588
/
annotate_routes.rb
147 lines (122 loc) · 4.44 KB
/
annotate_routes.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# == Annotate Routes
#
# Based on:
#
#
#
# Prepends the output of "rake routes" to the top of your routes.rb file.
# Yes, it's simple but I'm thick and often need a reminder of what my routes
# mean.
#
# Running this task will replace any exising route comment generated by the
# task. Best to back up your routes file before running:
#
# Author:
# Gavin Montague
# gavin@leftbrained.co.uk
#
# Released under the same license as Ruby. No Support. No Warranty.
#
module AnnotateRoutes
PREFIX = "# == Route Map"
def self.do_annotations(options={})
return unless(routes_exists?)
position_after = ! %w(before top).include?(options[:position_in_routes])
routes_map = `rake routes`.split(/\n/, -1)
# In old versions of Rake, the first line of output was the cwd. Not so
# much in newer ones. We ditch that line if it exists, and if not, we
# keep the line around.
routes_map.shift if(routes_map.first =~ /^\(in \//)
header = [
"#{PREFIX}" + (options[:timestamp] ? " (Updated #{Time.now.strftime("%Y-%m-%d %H:%M")})" : ""),
"#"
] + routes_map.map { |line| "# #{line}".rstrip }
(content, where_header_found) = strip_annotations(File.read(routes_file))
changed = where_header_found != 0 # This will either be :before, :after, or
# a number. If the number is > 0, the
# annotation was found somewhere in the
# middle of the file. If the number is
# zero, no annotation was found.
if(position_after)
# Ensure we have adequate trailing newlines at the end of the file to
# ensure a blank line separating the content from the annotation.
content << '' if(content.last != '')
# We're moving something from the top of the file to the bottom, so ditch
# the spacer we put in the first time around.
if(changed && where_header_found == :before)
content.shift if(content.first == '')
end
else
header = header << '' if(content.first != '' || changed)
end
content = position_after ? (content + header) : header + content
write_contents(content)
puts "Route file annotated."
end
def self.remove_annotations(options={})
return unless(routes_exists?)
(content, where_header_found) = strip_annotations(File.read(routes_file))
content = strip_on_removal(content, where_header_found)
write_contents(content)
puts "Removed annotations from routes file."
end
protected
def self.routes_file
@routes_rb ||= File.join("config", "routes.rb")
end
def self.routes_exists?
routes_exists = File.exists?(routes_file)
puts "Can`t find routes.rb" if(!routes_exists)
return routes_exists
end
def self.write_contents(content)
content << '' unless(content.last == '') # Make sure we end on a trailing
# newline.
File.open(routes_file, "wb") { |f| f.puts(content.join("\n")) }
end
def self.strip_annotations(content)
real_content = []
mode = :content
line_number = 0
header_found_at = 0
content.split(/\n/, -1).each do |line|
line_number += 1
begin
if(mode == :header)
if(line !~ /\s*#/)
mode = :content
raise unless (line == '')
end
elsif(mode == :content)
if(line =~ /^\s*#\s*== Route.*$/)
header_found_at = line_number
mode = :header
else
real_content << line
end
end
rescue
retry
end
end
content_lines = real_content.count
# By default assume the annotation was found in the middle of the file...
where_header_found = header_found_at
# ... unless we have evidence it was at the beginning ...
where_header_found = :before if(header_found_at == 1)
# ... or that it was at the end.
where_header_found = :after if(header_found_at >= content_lines)
return real_content, where_header_found
end
def self.strip_on_removal(content, where_header_found)
if(where_header_found == :before)
content.shift while(content.first == '')
elsif(where_header_found == :after)
content.pop while(content.last == '')
end
# TODO: If the user buried it in the middle, we should probably see about
# TODO: preserving a single line of space between the content above and
# TODO: below...
return content
end
end