Skip to content

Commit cbeff8c

Browse files
authored
Merge pull request #20 from fastruby/feature/output-json-string
Support JSON output
2 parents 6d7427a + dea39e0 commit cbeff8c

11 files changed

+372
-149
lines changed

README.md

+12
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,18 @@ Directory: /users/brian/examples/spree
270270

271271
```
272272

273+
#### JSON Format
274+
275+
If you want to export the details using JSON, you can use this command:
276+
277+
```
278+
$ rake stats\[test/dummy,json\]
279+
280+
Directory: /Users/etagwerker/Projects/fastruby/rails_stats/test/dummy
281+
282+
[{"name":"Mailers","lines":"4","loc":"4","classes":"1","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Models","lines":"3","loc":"3","classes":"1","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Javascripts","lines":"27","loc":"7","classes":"0","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Jobs","lines":"7","loc":"2","classes":"1","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Controllers","lines":"7","loc":"6","classes":"1","methods":"1","m_over_c":"1","loc_over_m":"4"},{"name":"Helpers","lines":"3","loc":"3","classes":"0","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Channels","lines":"8","loc":"8","classes":"2","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Configuration","lines":"417","loc":"111","classes":"1","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Total","lines":"476","loc":"144","classes":"7","methods":"1","m_over_c":"0","loc_over_m":"142","code_to_test_ratio":"0.0","total":true}]
283+
```
284+
273285
### Testing
274286

275287
In order to run the tests for this gem:

lib/rails_stats/all.rb

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
require 'rails_stats/stats_calculator'
2+
require 'rails_stats/stats_formatter'
3+
require 'rails_stats/json_formatter'
4+
require 'rails_stats/console_formatter'
15
require 'rails_stats/inflector'
26
require 'rails_stats/code_statistics_calculator'
37
require 'rails_stats/util'

lib/rails_stats/code_statistics.rb

+9-146
Original file line numberDiff line numberDiff line change
@@ -2,160 +2,23 @@
22

33
module RailsStats
44
class CodeStatistics
5-
6-
RAILS_APP_FOLDERS = ['models',
7-
'controllers',
8-
'helpers',
9-
'mailers',
10-
'views',
11-
'assets']
12-
13-
def initialize(root_directory)
14-
@root_directory = root_directory
15-
@key_concepts = calculate_key_concepts
16-
@projects = calculate_projects
17-
@statistics = calculate_statistics
18-
@code_total, @tests_total, @grand_total = calculate_totals
5+
def initialize(root_directory, opts = {})
6+
@calculator = RailsStats::StatsCalculator.new(root_directory)
7+
@formatter = load_formatter(opts)
198
end
209

2110
def to_s
22-
print_header
23-
sorted_keys = @statistics.keys.sort
24-
sorted_keys.each { |key| print_line(key, @statistics[key]) }
25-
print_splitter
26-
27-
print_line("Code", @code_total)
28-
print_line("Tests", @tests_total)
29-
print_line("Total", @grand_total)
30-
print_splitter
31-
32-
print_code_test_stats
11+
@formatter.to_s
3312
end
3413

3514
private
36-
def calculate_key_concepts
37-
# returns names of main things like models, controllers, services, etc
38-
concepts = {}
39-
app_projects.each do |project|
40-
project.key_concepts.each do |key|
41-
concepts[key] = true
42-
end
43-
end
44-
45-
# TODO: maybe gem names?
46-
47-
concepts.keys
48-
end
49-
50-
def calculate_projects
51-
out = []
52-
out += app_projects
53-
out += calculate_root_projects
54-
out += calculate_gem_projects
55-
out += calculate_spec_projects
56-
out += calculate_test_projects
57-
out += calculate_cucumber_projects
58-
out
59-
end
60-
61-
def app_projects
62-
@app_projects ||= calculate_app_projects
63-
end
64-
65-
def calculate_app_projects
66-
apps = Util.calculate_projects(@root_directory, "**", "app", RAILS_APP_FOLDERS)
67-
apps.collect do |root_path|
68-
AppStatistics.new(root_path)
69-
end
70-
end
71-
72-
def calculate_gem_projects
73-
gems = Util.calculate_projects(@root_directory, "*", "**", "*.gemspec")
74-
gems.collect do |root_path|
75-
GemStatistics.new(root_path)
76-
end
77-
end
78-
79-
def calculate_spec_projects
80-
specs = Util.calculate_shared_projects("spec", @root_directory, "**", "spec", "**", "*_spec.rb")
81-
specs.collect do |root_path|
82-
SpecStatistics.new(root_path, @key_concepts)
83-
end
84-
end
85-
86-
def calculate_test_projects
87-
tests = Util.calculate_shared_projects("test", @root_directory, "**", "test", "**", "*_test.rb")
88-
tests.collect do |root_path|
89-
TestStatistics.new(root_path, @key_concepts)
90-
end
91-
end
92-
93-
def calculate_root_projects
94-
[RootStatistics.new(@root_directory)]
95-
end
96-
97-
def calculate_cucumber_projects
98-
cukes = Util.calculate_projects(@root_directory, "**", "*.feature")
99-
cukes.collect do |root_path|
100-
CucumberStatistics.new(root_path)
101-
end
102-
end
10315

104-
def calculate_statistics
105-
out = {}
106-
@projects.each do |project|
107-
project.statistics.each do |key, stats|
108-
out[key] ||= CodeStatisticsCalculator.new(project.test)
109-
out[key].add(stats)
110-
end
16+
def load_formatter(opts = {})
17+
if opts[:format] == "json"
18+
RailsStats::JSONFormatter.new(@calculator, opts)
19+
else
20+
RailsStats::ConsoleFormatter.new(@calculator, opts)
11121
end
112-
out
113-
end
114-
115-
def calculate_totals
116-
# TODO: make this a single loop
117-
code_total = @statistics.each_with_object(CodeStatisticsCalculator.new) do |pair, code_total|
118-
code_total.add(pair.last) unless pair.last.test
119-
end
120-
121-
tests_total = @statistics.each_with_object(CodeStatisticsCalculator.new) do |pair, tests_total|
122-
tests_total.add(pair.last) if pair.last.test
123-
end
124-
125-
grand_total = @statistics.each_with_object(CodeStatisticsCalculator.new) do |pair, total|
126-
total.add(pair.last)
127-
end
128-
129-
[code_total, tests_total, grand_total]
130-
end
131-
132-
def print_header
133-
print_splitter
134-
puts "| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |"
135-
print_splitter
136-
end
137-
138-
def print_splitter
139-
puts "+----------------------+---------+---------+---------+---------+-----+-------+"
140-
end
141-
142-
def print_line(name, statistics)
143-
m_over_c = (statistics.methods / statistics.classes) rescue m_over_c = 0
144-
loc_over_m = (statistics.code_lines / statistics.methods) - 2 rescue loc_over_m = 0
145-
146-
puts "| #{name.ljust(20)} " \
147-
"| #{statistics.lines.to_s.rjust(7)} " \
148-
"| #{statistics.code_lines.to_s.rjust(7)} " \
149-
"| #{statistics.classes.to_s.rjust(7)} " \
150-
"| #{statistics.methods.to_s.rjust(7)} " \
151-
"| #{m_over_c.to_s.rjust(3)} " \
152-
"| #{loc_over_m.to_s.rjust(5)} |"
153-
end
154-
155-
def print_code_test_stats
156-
code_to_test_ratio = @tests_total.code_lines.to_f / @code_total.code_lines
157-
puts " Code LOC: #{@code_total.code_lines} Test LOC: #{@tests_total.code_lines} Code to Test Ratio: 1:#{sprintf("%.1f", code_to_test_ratio)}"
158-
puts ""
15922
end
16023
end
16124
end

lib/rails_stats/console_formatter.rb

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
module RailsStats
2+
class ConsoleFormatter < StatsFormatter
3+
def to_s
4+
print_header
5+
sorted_keys = @statistics.keys.sort
6+
sorted_keys.each { |key| print_line(key, @statistics[key]) }
7+
print_splitter
8+
9+
if @grand_total
10+
print_line("Code", @code_total)
11+
print_line("Tests", @tests_total)
12+
print_line("Total", @grand_total)
13+
print_splitter
14+
end
15+
16+
print_code_test_stats
17+
end
18+
19+
private
20+
21+
def print_header
22+
print_splitter
23+
puts "| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |"
24+
print_splitter
25+
end
26+
27+
def print_splitter
28+
puts "+----------------------+---------+---------+---------+---------+-----+-------+"
29+
end
30+
31+
def print_line(name, statistics)
32+
m_over_c = (statistics.methods / statistics.classes) rescue m_over_c = 0
33+
loc_over_m = (statistics.code_lines / statistics.methods) - 2 rescue loc_over_m = 0
34+
35+
puts "| #{name.ljust(20)} " \
36+
"| #{statistics.lines.to_s.rjust(7)} " \
37+
"| #{statistics.code_lines.to_s.rjust(7)} " \
38+
"| #{statistics.classes.to_s.rjust(7)} " \
39+
"| #{statistics.methods.to_s.rjust(7)} " \
40+
"| #{m_over_c.to_s.rjust(3)} " \
41+
"| #{loc_over_m.to_s.rjust(5)} |"
42+
end
43+
44+
def print_code_test_stats
45+
code = calculator.code_loc
46+
tests = calculator.test_loc
47+
48+
puts " Code LOC: #{code} Test LOC: #{tests} Code to Test Ratio: 1:#{sprintf("%.1f", tests.to_f/code)}"
49+
puts ""
50+
end
51+
end
52+
end

lib/rails_stats/json_formatter.rb

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
require "json"
2+
3+
module RailsStats
4+
class JSONFormatter < StatsFormatter
5+
def result
6+
@result = @statistics.map { |key, stats| stat_hash(key, stats) }
7+
8+
if @grand_total
9+
@result << stat_hash("Total", @grand_total).merge(code_test_hash)
10+
end
11+
12+
@result
13+
end
14+
15+
def to_s
16+
puts result.to_json
17+
end
18+
19+
private
20+
21+
def code_test_hash
22+
code = calculator.code_loc
23+
tests = calculator.test_loc
24+
25+
{
26+
"code_to_test_ratio" => "#{sprintf("%.1f", tests.to_f/code)}", "total" => true
27+
}
28+
end
29+
30+
def stat_hash(name, statistics)
31+
m_over_c = (statistics.methods / statistics.classes) rescue m_over_c = 0
32+
loc_over_m = (statistics.code_lines / statistics.methods) - 2 rescue loc_over_m = 0
33+
34+
{
35+
"name" => name,
36+
"lines" => statistics.lines.to_s,
37+
"loc" => statistics.code_lines.to_s,
38+
"classes" => statistics.classes.to_s,
39+
"methods" => statistics.methods.to_s,
40+
"m_over_c" => m_over_c.to_s,
41+
"loc_over_m" => loc_over_m.to_s
42+
}
43+
end
44+
end
45+
end

0 commit comments

Comments
 (0)