sandi_meter 1.0.5 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +2 -2
- data/lib/sandi_meter/calculator.rb +13 -6
- data/lib/sandi_meter/cli.rb +69 -50
- data/lib/sandi_meter/rules_checker.rb +4 -3
- data/lib/sandi_meter/version.rb +1 -1
- data/spec/calculator_spec.rb +51 -0
- data/spec/rules_checker_spec.rb +5 -14
- data/spec/test_classes/10_controller.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MTM2ZjcwMzM2NmQ5ZTliOGU5OGY0ZGY0Zjg1NjRhMzM1ZmJhNTVkNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTYzNDVjNmM1NDcxOGE2MmVlZjZlYjMzMTI2N2Y0YTRmNzdiYjBmNg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YTgwMTUwZmQ3ZjEwNTBlYmExM2ExMjU5NzU1YTkxZmZlNWU2MTc5YTRkODE4
|
10
|
+
YjU5N2JkMGQyYzUyMGQwMTFhYWJiMTIyNjUzYTg1YjhhMDRjMjM5OTQwNzlk
|
11
|
+
NmJiZWJlZDZiZDZlNGNhZTI5OGRhMzlkMTJiMzMxN2JkMzY1NGM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZjA4YTQzNWVhMDZhZThkZjg4NjdmZTFjYmQ1MDZiNzc0ZjQzOTY2ODQ4NTMw
|
14
|
+
MWE2YTdjZWQyY2VhZDliMmFlZTlmMDI4ZmUzM2I1ZTQwMzVkY2EzOGViM2Zj
|
15
|
+
ZDE1NmY2ZDM4ZGQyOWQyZmExM2VhMGFkZmU3MGEyOTE4MDg1ZmI=
|
data/README.md
CHANGED
@@ -65,8 +65,8 @@ Controllers with 1+ instance variables
|
|
65
65
|
|
66
66
|
Try using gem with `-g (--graph)` option, so it will create a folder with beautiful html output and log file with results of any scan.
|
67
67
|
|
68
|
-
![SandiMeter HTML mode pie charts](http://
|
69
|
-
![SandiMeter HTML mode details](http://
|
68
|
+
![SandiMeter HTML mode pie charts](http://cl.ly/image/1p142M3K1S2x/content)
|
69
|
+
![SandiMeter HTML mode details](http://cl.ly/image/2R163v283V3Q/content)
|
70
70
|
|
71
71
|
Add ignore files and folders in `sandi_meter/.sandi_meter` file.
|
72
72
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module SandiMeter
|
2
2
|
class Calculator
|
3
3
|
def initialize
|
4
|
-
@data = {}
|
4
|
+
@data = {classes: [], methods: {}, method_calls: []}
|
5
5
|
@output = {}
|
6
6
|
end
|
7
7
|
|
@@ -77,15 +77,21 @@ module SandiMeter
|
|
77
77
|
@output[:fourth_rule][:log] ||={}
|
78
78
|
@output[:fourth_rule][:log][:controllers] ||= []
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
@output[:fourth_rule][:log][:controllers] << [klass.name, method.name, method.ivars]
|
80
|
+
controllers.each do |controller|
|
81
|
+
methods_for(controller).select { |m| m.ivars.length > 1 }.each do |method|
|
82
|
+
@output[:fourth_rule][:log][:controllers] << [controller.name, method.name, method.ivars.uniq]
|
85
83
|
end
|
86
84
|
end
|
87
85
|
end
|
88
86
|
|
87
|
+
def controllers
|
88
|
+
@data[:classes].select { |c| c.controller? }
|
89
|
+
end
|
90
|
+
|
91
|
+
def methods_for(controller)
|
92
|
+
@data[:methods].fetch(controller.name) { [] }
|
93
|
+
end
|
94
|
+
|
89
95
|
def check_first_rule
|
90
96
|
total_classes_amount = @data[:classes].size
|
91
97
|
small_classes_amount = @data[:classes].select(&:small?).size
|
@@ -154,5 +160,6 @@ module SandiMeter
|
|
154
160
|
|
155
161
|
log_fourth_rule if @store_details
|
156
162
|
end
|
163
|
+
|
157
164
|
end
|
158
165
|
end
|
data/lib/sandi_meter/cli.rb
CHANGED
@@ -6,6 +6,7 @@ require 'sandi_meter/rules_checker'
|
|
6
6
|
require 'sandi_meter/logger'
|
7
7
|
require 'sandi_meter/version'
|
8
8
|
require 'sandi_meter/html_generator'
|
9
|
+
require 'yaml'
|
9
10
|
|
10
11
|
module SandiMeter
|
11
12
|
class CommandParser
|
@@ -58,71 +59,89 @@ module SandiMeter
|
|
58
59
|
end
|
59
60
|
|
60
61
|
class CLI
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
file.write %w(db vendor).join("\n")
|
73
|
-
end
|
62
|
+
class << self
|
63
|
+
def execute
|
64
|
+
cli = CommandParser.new
|
65
|
+
cli.parse_options
|
66
|
+
|
67
|
+
if cli.config[:graph]
|
68
|
+
log_dir_path = File.join(cli.config[:path], 'sandi_meter')
|
69
|
+
FileUtils.mkdir(log_dir_path) unless Dir.exists?(log_dir_path)
|
70
|
+
|
71
|
+
create_config_file(cli.config[:path], 'sandi_meter/.sandi_meter', %w(db vendor).join("\n"))
|
72
|
+
create_config_file(cli.config[:path], 'sandi_meter/config.yml', YAML.dump({ threshold: 90 }))
|
74
73
|
end
|
75
|
-
end
|
76
74
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
75
|
+
if cli.config[:version]
|
76
|
+
puts version_info
|
77
|
+
exit 0
|
78
|
+
end
|
82
79
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
80
|
+
if cli.config[:rules]
|
81
|
+
show_sandi_rules
|
82
|
+
exit 0
|
83
|
+
end
|
87
84
|
|
88
|
-
|
89
|
-
|
85
|
+
scanner = SandiMeter::FileScanner.new(cli.config[:log])
|
86
|
+
data = scanner.scan(cli.config[:path], cli.config[:details] || cli.config[:graph])
|
90
87
|
|
91
|
-
|
88
|
+
formatter = SandiMeter::Formatter.new
|
89
|
+
formatter.print_data(data)
|
92
90
|
|
93
|
-
|
91
|
+
if cli.config[:graph]
|
92
|
+
if File.directory?(cli.config[:path])
|
93
|
+
logger = SandiMeter::Logger.new(data)
|
94
|
+
logger.log!(cli.config[:path])
|
94
95
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
html_generator = SandiMeter::HtmlGenerator.new
|
97
|
+
html_generator.copy_assets!(cli.config[:path])
|
98
|
+
html_generator.generate_data!(cli.config[:path])
|
99
|
+
html_generator.generate_details!(cli.config[:path], data)
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
101
|
+
index_html_path = File.join(cli.config[:path], 'sandi_meter/index.html')
|
102
|
+
system "open #{index_html_path}"
|
103
|
+
else
|
104
|
+
puts "WARNING!!! HTML mode works only if you scan folder."
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
config_file_path = File.join(cli.config[:path], 'sandi_meter', 'config.yml')
|
109
|
+
config = if File.exists?(config_file_path)
|
110
|
+
YAML.load(File.read(config_file_path))
|
111
|
+
else
|
112
|
+
{ threshold: 90 }
|
113
|
+
end
|
104
114
|
|
105
|
-
|
106
|
-
|
115
|
+
if RulesChecker.new(data, config).ok?
|
116
|
+
exit 0
|
107
117
|
else
|
108
|
-
|
118
|
+
exit 1
|
109
119
|
end
|
110
120
|
end
|
111
121
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
122
|
+
def show_sandi_rules
|
123
|
+
puts %(
|
124
|
+
1. 100 lines per class
|
125
|
+
2. 5 lines per method
|
126
|
+
3. 4 params per method call (and don't even try cheating with hash params)
|
127
|
+
4. 1 instance variables per controller' action
|
128
|
+
)
|
116
129
|
end
|
117
|
-
end
|
118
130
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
131
|
+
private
|
132
|
+
def create_config_file(path, relative_path, content)
|
133
|
+
file_path = File.join(path, relative_path)
|
134
|
+
if File.directory?(path) && !File.exists?(file_path)
|
135
|
+
File.open(file_path, "w") do |file|
|
136
|
+
file.write(content)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def version_info
|
142
|
+
# stolen from gem 'bubs' :)
|
143
|
+
"SandiMeter ".tr('A-Za-z1-90', 'Ⓐ-Ⓩⓐ-ⓩ①-⑨⓪').split('').join(' ') + SandiMeter::VERSION
|
144
|
+
end
|
126
145
|
end
|
127
146
|
end
|
128
147
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module SandiMeter
|
2
2
|
class RulesChecker
|
3
|
-
def initialize(data)
|
3
|
+
def initialize(data, config)
|
4
|
+
@config = config
|
4
5
|
@rules = []
|
5
6
|
@rules << percentage(data[:first_rule][:small_classes_amount], data[:first_rule][:total_classes_amount])
|
6
7
|
@rules << percentage(data[:second_rule][:small_methods_amount], data[:second_rule][:total_methods_amount])
|
@@ -9,12 +10,12 @@ module SandiMeter
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def ok?
|
12
|
-
@rules.
|
13
|
+
@rules.reduce(:+) / 4 > @config[:threshold]
|
13
14
|
end
|
14
15
|
|
15
16
|
private
|
16
17
|
def percentage(amount, total)
|
17
|
-
total > 0 ? amount / total :
|
18
|
+
total > 0 ? (amount / total.to_f)*100 : 100
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
data/lib/sandi_meter/version.rb
CHANGED
data/spec/calculator_spec.rb
CHANGED
@@ -26,4 +26,55 @@ describe SandiMeter::Calculator do
|
|
26
26
|
method_params[2].should eq(6)
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
describe "#log_fourth_rule" do
|
31
|
+
context "when there are violations of the fourth rule" do
|
32
|
+
let(:test_class) { test_file_path("10_controller") }
|
33
|
+
|
34
|
+
before do
|
35
|
+
data = analyzer.analyze(test_class)
|
36
|
+
calculator.push(data)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "adds the expected entries to the log" do
|
40
|
+
output = calculator.calculate!(true)
|
41
|
+
|
42
|
+
fourth_rule_log_entry = output[:fourth_rule][:log][:controllers][0]
|
43
|
+
controller_name = fourth_rule_log_entry[0]
|
44
|
+
action = fourth_rule_log_entry[1]
|
45
|
+
instance_variables = fourth_rule_log_entry[2]
|
46
|
+
|
47
|
+
expect(controller_name).to eq "AnotherUsersController"
|
48
|
+
expect(action).to eq "index"
|
49
|
+
expect(instance_variables).to include("@users")
|
50
|
+
expect(instance_variables).to include("@excess_variable")
|
51
|
+
expect(instance_variables.length).to eq 2
|
52
|
+
end
|
53
|
+
end
|
54
|
+
context "when there are no violations of the fourth rule" do
|
55
|
+
let(:test_class) { test_file_path("9_controller") }
|
56
|
+
|
57
|
+
before do
|
58
|
+
data = analyzer.analyze(test_class)
|
59
|
+
calculator.push(data)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "does not add any entries to the log" do
|
63
|
+
output = calculator.calculate!(true)
|
64
|
+
expect(output[:fourth_rule][:log][:controllers]).to eq []
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'no matchig ruby files found' do
|
70
|
+
it 'counts class lines' do
|
71
|
+
output = calculator.calculate!(false)
|
72
|
+
output[:first_rule][:total_classes_amount].should eql(0)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'counts method lines' do
|
76
|
+
output = calculator.calculate!(true)
|
77
|
+
output[:second_rule][:total_methods_amount].should eql(0)
|
78
|
+
end
|
79
|
+
end
|
29
80
|
end
|
data/spec/rules_checker_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
require_relative '../lib/sandi_meter/rules_checker'
|
3
3
|
|
4
4
|
describe SandiMeter::RulesChecker do
|
5
|
-
let(:
|
5
|
+
let(:conditions) do
|
6
6
|
{
|
7
7
|
first_rule: { small_classes_amount: 1, total_classes_amount: 2 },
|
8
8
|
second_rule: { small_methods_amount: 2, total_methods_amount: 2 },
|
@@ -11,22 +11,13 @@ describe SandiMeter::RulesChecker do
|
|
11
11
|
}
|
12
12
|
end
|
13
13
|
|
14
|
-
let(:succeed_conditions) do
|
15
|
-
{
|
16
|
-
first_rule: { small_classes_amount: 2, total_classes_amount: 2 },
|
17
|
-
second_rule: { small_methods_amount: 2, total_methods_amount: 2 },
|
18
|
-
third_rule: { proper_method_calls: 2, total_method_calls: 2 },
|
19
|
-
fourth_rule: { proper_controllers_amount: 0, total_controllers_amount: 0 }
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
14
|
describe "#ok?" do
|
24
|
-
it "returns false
|
25
|
-
expect(SandiMeter::RulesChecker.new(
|
15
|
+
it "returns false with 100 threshold" do
|
16
|
+
expect(SandiMeter::RulesChecker.new(conditions, {threshold: 100})).to_not be_ok
|
26
17
|
end
|
27
18
|
|
28
|
-
it "returns true
|
29
|
-
expect(SandiMeter::RulesChecker.new(
|
19
|
+
it "returns true with threshold less than 100" do
|
20
|
+
expect(SandiMeter::RulesChecker.new(conditions, {threshold: 50})).to be_ok
|
30
21
|
end
|
31
22
|
end
|
32
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sandi_meter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anatoli Makarevich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|