Skip to content

Commit

Permalink
Add JSON output format option to rails stats
Browse files Browse the repository at this point in the history
Enhance the rails stats command to support JSON formatted output,
enabling easier consumption of architecture metrics by automated systems.
This modification improves the utility of the stats command for continuous
monitoring of application maturity and health.

Example usage:
```
$ bin/rails stats[json] | jq .
{
  "code_statistics": [
    {
      "name": "Controllers",
      "statistic": {
        "lines": 12345,
        "code_lines": 12345,
        "classes": 123,
        "methods": 1234
      }
    },
    ...
  ],
  "total": {
    "lines": 12345,
    "code_lines": 12345,
    "classes": 123,
    "methods": 1234
  }
}
```
  • Loading branch information
euglena1215 committed Apr 27, 2024
1 parent 0a9e39d commit a3ddbe2
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 2 deletions.
30 changes: 30 additions & 0 deletions railties/CHANGELOG.md
@@ -1,3 +1,33 @@
* Add JSON output format to `rails stats` via `format` option.

Enables JSON formatted output for better integration with automated systems. Maintains default table format unless specified.

```shell
$ bin/rails stats[json] | jq .
{
"code_statistics": [
{
"name": "Controllers",
"statistic": {
"lines": 12345,
"code_lines": 12345,
"classes": 123,
"methods": 1234
}
},
...
],
"total": {
"lines": 12345,
"code_lines": 12345,
"classes": 123,
"methods": 1234
}
}
```

*Teppei Shintani*

* Allow Actionable Errors encountered when running tests to be retried.

```txt
Expand Down
12 changes: 12 additions & 0 deletions railties/lib/rails/code_statistics.rb
Expand Up @@ -35,6 +35,18 @@ def to_s
print_code_test_stats
end

def to_h
{
code_statistics: @statistics.map do |k, v|
{
name: k,
statistic: v.to_h
}
end,
total: @total&.to_h
}
end

private
def calculate_statistics
Hash[@pairs.map { |pair| [pair.first, calculate_directory_statistics(pair.last)] }]
Expand Down
9 changes: 9 additions & 0 deletions railties/lib/rails/code_statistics_calculator.rb
Expand Up @@ -86,6 +86,15 @@ def add_by_io(io, file_type)
end
end

def to_h
{
lines: lines,
code_lines: code_lines,
classes: classes,
methods: methods
}
end

private
def file_type(file_path)
if file_path.end_with? "_test.rb"
Expand Down
10 changes: 8 additions & 2 deletions railties/lib/rails/tasks/statistics.rake
Expand Up @@ -29,10 +29,16 @@ STATS_DIRECTORIES ||= [
]

desc "Report code statistics (KLOCs, etc) from the application or engine"
task :stats do
task :stats, :format do |_, args|
require "rails/code_statistics"
stat_directories = STATS_DIRECTORIES.collect do |name, dir|
[ name, "#{File.dirname(Rake.application.rakefile_location)}/#{dir}" ]
end.select { |name, dir| File.directory?(dir) }
CodeStatistics.new(*stat_directories).to_s
statistics = CodeStatistics.new(*stat_directories)
case args[:format]
when "json"
puts statistics.to_h.to_json
else
statistics.to_s
end
end
5 changes: 5 additions & 0 deletions railties/test/code_statistics_calculator_test.rb
Expand Up @@ -84,6 +84,11 @@ class A; end
assert_equal 6, @code_statistics_calculator.methods
end

test "return statistics as a hash" do
code_statistics_calculator = CodeStatisticsCalculator.new(1, 2, 3, 4)
assert_equal({ lines: 1, code_lines: 2, classes: 3, methods: 4 }, code_statistics_calculator.to_h)
end

test "calculate number of Ruby methods" do
code = <<-'CODE'
def foo
Expand Down
55 changes: 55 additions & 0 deletions railties/test/code_statistics_test.rb
Expand Up @@ -31,4 +31,59 @@ def foo
CodeStatistics.new(["hidden file", @tmp_path])
end
end

test "output results in table format" do
File.write File.join(@tmp_path, "example.rb"), <<-CODE
class Example
def foo
puts 'foo'
end
end
CODE

code_statistics = CodeStatistics.new(["tmp dir", @tmp_path])
expected = <<~TABLE
+----------------------+--------+--------+---------+---------+-----+-------+
| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
+----------------------+--------+--------+---------+---------+-----+-------+
| tmp dir | 5 | 5 | 1 | 1 | 1 | 3 |
+----------------------+--------+--------+---------+---------+-----+-------+
Code LOC: 5 Test LOC: 0 Code to Test Ratio: 1:0.0
TABLE

output, _ = capture_io do
code_statistics.to_s
end

assert_equal expected, output
end

test "return results in hash format" do
File.write File.join(@tmp_path, "example.rb"), <<-CODE
class Example
def foo
puts 'foo'
end
end
CODE

code_statistics = CodeStatistics.new(["tmp dir", @tmp_path])
expected = {
code_statistics: [
{
name: "tmp dir",
statistic: {
lines: 5,
code_lines: 5,
classes: 1,
methods: 1
}
}
],
total: nil
}

assert_equal expected, code_statistics.to_h
end
end

0 comments on commit a3ddbe2

Please sign in to comment.