hospital 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c2d250697eb93225f8674b4374369688af80a6d32efcbfc70406ae2130d0bba
4
- data.tar.gz: bb30e0f93629c922d9723c943061e9dddad28fcab7406ab24496cd5f893a5b6d
3
+ metadata.gz: c474d0a653f97f57a2e281a594c0e9b45d3e03bd17bd0b4ea80140e79b8d6572
4
+ data.tar.gz: 24c2232ea33222d4c470c2c736a6bf93745049d332fa07c44970c4f654bcc5eb
5
5
  SHA512:
6
- metadata.gz: 6ca63659e83bd3a662612b41b2a645776ca06132241fd5033c169f8fb4be1547445fb34e2160731adced86f7ba6a8995f92a6d1fa573751002ce6d2c85869c70
7
- data.tar.gz: 91f8b05eddcbfc0fbbc1cb44b7d9a0c340312207267bd4589237480f9fd95a5473af493d0c274d4231c6aaa914fb2820b7e3985039b1ad089eb523764d5ce89c
6
+ metadata.gz: 05540eb19dbdd3277ef4d76bca4f8692e69c6eba340e0a8f91a8c554dd81bf654fa478c7f9396925eed5e2deca3ac28d75b872cec652b38128b84291a65d3b02
7
+ data.tar.gz: 0eb85a41d00fe122217b07eef2d6a69f5d8f6dadbbfcd95b21991d0e055c2be35e2aeec4c9d4f4a86d133d50b960f7697746a26cb08e7fb584389905491d5fb3
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hospital
4
+ class Checkup
5
+ attr_reader :code, :condition, :diagnosis, :group, :skipped, :klass, :precondition
6
+
7
+ def initialize klass, code, title: nil, condition: -> { true }, precondition: false
8
+ @klass = klass
9
+ @code = code
10
+ @condition = condition
11
+ @diagnosis = Hospital::Diagnosis.new([klass.to_s, title].compact.join(' - '))
12
+ @precondition = precondition
13
+ @group = nil
14
+ end
15
+
16
+ def reset_diagnosis
17
+ diagnosis.reset
18
+ end
19
+
20
+ def check verbose: false
21
+ diagnosis.reset
22
+
23
+ if condition.nil? || condition.call
24
+ @skipped = false
25
+ code.call(diagnosis)
26
+ diagnosis
27
+ else
28
+ @skipped = true
29
+ nil
30
+ end
31
+ rescue StandardError => e
32
+ diagnosis.add_error "Unrescued exception in #{klass}.checkup:\n#{e.full_message}.\nThis is a bug inside the checkup method that should be fixed!"
33
+ end
34
+
35
+ def success?
36
+ diagnosis.success?
37
+ end
38
+
39
+ def set_group group
40
+ @group = group
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ require_relative "string_formatter"
2
+
3
+ using StringFormatter
4
+
5
+ module Hospital
6
+ class CheckupGroup
7
+ attr_reader :name, :checkups, :precondition_checkups, :skipped
8
+
9
+ def initialize name
10
+ @name = name
11
+ @precondition_checkups = []
12
+ @checkups = []
13
+ @skipped = false
14
+ end
15
+
16
+ def all_checkups
17
+ @precondition_checkups + @checkups
18
+ end
19
+
20
+ def header
21
+ "#{name.to_s.capitalize.gsub(/_/, ' ')} checks"
22
+ end
23
+
24
+ def add_checkup checkup
25
+ checkup.set_group self
26
+
27
+ if checkup.precondition
28
+ @precondition_checkups << checkup
29
+ else
30
+ @checkups << checkup
31
+ end
32
+ end
33
+
34
+ def run_checkups verbose: false
35
+ run_precondition_checkups verbose: verbose
36
+
37
+ unless @skipped
38
+ run_dependent_checkups verbose: verbose
39
+ end
40
+ end
41
+
42
+ def run_precondition_checkups verbose: false
43
+ @precondition_checkups.each do |checkup|
44
+ checkup.check verbose: verbose
45
+ @skipped = true unless checkup.success?
46
+ end
47
+ end
48
+
49
+ def run_dependent_checkups verbose: false
50
+ @checkups.each do |checkup|
51
+ checkup.check verbose: verbose
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,9 @@
1
- class Hospital::Diagnosis
2
- attr_reader :infos, :warnings, :errors, :name, :results
1
+ require_relative "string_formatter"
2
+
3
+ using StringFormatter
4
+
5
+ class Hospital::Diagnosis
6
+ attr_reader :infos, :warnings, :skips, :errors, :name, :results
3
7
 
4
8
  def initialize name
5
9
  @name = name.to_s
@@ -9,6 +13,7 @@ class Hospital::Diagnosis
9
13
  def reset
10
14
  @infos = []
11
15
  @warnings = []
16
+ @skips = []
12
17
  @errors = []
13
18
  @results = []
14
19
  end
@@ -44,8 +49,8 @@ class Hospital::Diagnosis
44
49
  "#{prefix} #{message.gsub(/\n\z/, '').gsub(/\n/, prefix ? "\n " : "\n")}"
45
50
  end
46
51
 
47
- def put
48
- puts output
52
+ def put out
53
+ out.put_diagnosis_result output
49
54
  end
50
55
  end
51
56
 
@@ -54,11 +59,15 @@ class Hospital::Diagnosis
54
59
  end
55
60
 
56
61
  class Warning < Result
57
- def prefix; '🟠'; end
62
+ def prefix; '🟠' end
63
+ end
64
+
65
+ class Skip < Result
66
+ def prefix; '🟠' end
58
67
  end
59
68
 
60
69
  class Error < Result
61
- def prefix; '🔴'; end
70
+ def prefix; '🔴' end
62
71
  end
63
72
 
64
73
  def add_info message
@@ -73,13 +82,31 @@ class Hospital::Diagnosis
73
82
  @results << warning
74
83
  end
75
84
 
85
+ def add_skip message
86
+ skip = Skip.new message
87
+ @skips << skip
88
+ @results << skip
89
+ end
90
+
76
91
  def add_error message
77
92
  error = Error.new message
78
93
  @errors << error
79
94
  @results << error
80
95
  end
81
96
 
82
- def put_results
83
- results.each &:put
97
+ def put_results out
98
+ results.each do |result|
99
+ result.put out
100
+ end
101
+ end
102
+
103
+ def success?
104
+ errors.count == 0 && skips.count == 0
105
+ end
106
+
107
+ def on_success_message message
108
+ if success?
109
+ add_info message
110
+ end
84
111
  end
85
112
  end
@@ -0,0 +1,11 @@
1
+ module Hospital
2
+ module Formatter
3
+ class Base
4
+ attr_reader :buffer
5
+
6
+ def initialize
7
+ @buffer = ""
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ require_relative "base"
2
+
3
+ using StringFormatter
4
+
5
+ module Hospital
6
+ module Formatter
7
+ class Pre < Base
8
+ def put_group_header text
9
+ @buffer << "\n\n### #{text}"
10
+ end
11
+
12
+ def put_diagnosis_header text
13
+ @buffer << "\n\n## #{text}"
14
+ end
15
+
16
+ def put_summary errors_count, warnings_count
17
+ @buffer << <<~END
18
+ \n\n
19
+ #### Summary:
20
+ Errors: #{errors_count}
21
+ Warnings: #{warnings_count}
22
+ END
23
+ end
24
+
25
+ def put_diagnosis_result text
26
+ @buffer << "\n#{text}"
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require_relative "base"
2
+
3
+ using StringFormatter
4
+
5
+ module Hospital
6
+ module Formatter
7
+ class Shell < Base
8
+ def put_group_header text
9
+ @buffer << "\n### #{text}".h1
10
+ end
11
+
12
+ def put_diagnosis_header text
13
+ @buffer << "\n#{text.h2.indented}"
14
+ end
15
+
16
+ def put_summary errors_count, warnings_count
17
+ @buffer << <<~END
18
+
19
+ #{"Summary:".h1}
20
+ #{"Errors: #{errors_count}".red}
21
+ #{"Warnings: #{warnings_count}".yellow}
22
+ END
23
+ end
24
+
25
+ def put_diagnosis_result text
26
+ @buffer << "\n#{text.indented}"
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ module StringFormatter
2
+ refine String do
3
+ def bold
4
+ "\e[1m#{self}\e[0m"
5
+ end
6
+
7
+ def underline
8
+ "\e[4m#{self}\e[0m"
9
+ end
10
+
11
+ def h1
12
+ "\n#{self}".underline.bold
13
+ end
14
+
15
+ def h2
16
+ "\n#{self}".underline
17
+ end
18
+
19
+ def red
20
+ "\e[31m#{self}\e[0m"
21
+ end
22
+
23
+ def yellow
24
+ "\e[33m#{self}\e[0m"
25
+ end
26
+
27
+ def indented
28
+ "#{self}"
29
+ end
30
+ end
31
+ end
@@ -2,17 +2,12 @@
2
2
 
3
3
  require_relative '../../hospital'
4
4
 
5
+ # usage:
6
+ # rake doctor
7
+ # rake doctor[true]
8
+
5
9
  desc 'Check system setup sanity.'
6
10
  task :doctor, [:verbose] => :environment do |t, args|
7
- # at_exit { Rake::Task['doctor:summary'].invoke if $!.nil? }
8
-
9
- ActiveRecord::Base.connection_pool.disconnect!
10
- ActiveSupport.on_load(:active_record) do
11
- config = ActiveRecord::Base.configurations[Rails.env]
12
- config['pool'] = 100
13
- ActiveRecord::Base.establish_connection(config)
14
- end
15
-
16
11
  verbose = args[:verbose] == "true"
17
12
 
18
13
  # silence warnings about double constant definitions
@@ -20,7 +15,7 @@ task :doctor, [:verbose] => :environment do |t, args|
20
15
  p "eager load all classes" if verbose
21
16
  Rails.application.eager_load!
22
17
  end
23
-
18
+
24
19
  p "start checkup" if verbose
25
- Hospital.do_checkup_all verbose: verbose
20
+ puts Hospital::Runner.new(verbose: verbose).do_checkup_all
26
21
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hospital
4
- VERSION = "0.5.0"
4
+ VERSION = "0.7.0"
5
5
  end
data/lib/hospital.rb CHANGED
@@ -1,114 +1,104 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "byebug"
4
+ require 'require_all'
3
5
  require_relative "hospital/version"
6
+ require_relative "hospital/checkup"
7
+ require_relative "hospital/checkup_group"
4
8
  require_relative "hospital/diagnosis"
5
- require_relative "hospital/formatter"
9
+ require_relative "hospital/string_formatter"
10
+ require_relative "hospital/formatter/shell"
11
+ require_relative "hospital/formatter/pre"
6
12
 
7
- using Formatter
13
+ using StringFormatter
8
14
 
9
15
  module Hospital
10
16
  require_relative 'railtie' if defined?(Rails)
11
17
 
12
18
  class Error < StandardError; end
13
19
 
14
- class Checkup
15
- attr_reader :code, :condition, :diagnosis, :group, :skipped, :klass
20
+ @@groups = []
16
21
 
17
- def initialize klass, code, group: :general, title: nil, condition: -> { true }
18
- @klass = klass
19
- @code = code
20
- @group = group
21
- @condition = condition
22
- @diagnosis = Hospital::Diagnosis.new([klass.to_s, title].compact.join(' - '))
23
- end
22
+ class << self
24
23
 
25
- def reset_diagnosis
26
- diagnosis.reset
24
+ def included(klass)
25
+ raise Hospital::Error.new("Cannot include Hospital, please extend instead.")
27
26
  end
28
27
 
29
- def check verbose: false
30
- diagnosis.reset
28
+ # used to call the checkup for a specific class directly (in specs)
29
+ def do_checkup(klass, verbose: false)
30
+ @@groups.map(&:all_checkups).flatten.select{|cu| cu.klass == klass }.map do |cu|
31
+ cu.check verbose: verbose
32
+ end
33
+ end
31
34
 
32
- if condition.nil? || condition.call
33
- @skipped = false
34
- code.call(diagnosis)
35
- diagnosis
36
- else
37
- @skipped = true
38
- nil
35
+ def find_or_create_checkup_group name
36
+ unless checkup_group = @@groups.detect{|g| g.name == name }
37
+ checkup_group = CheckupGroup.new name
38
+ @@groups << checkup_group
39
39
  end
40
- rescue StandardError => e
41
- diagnosis.add_error "Unrescued exception in #{klass}.checkup:\n#{e.inspect}.\nThis is a bug inside the checkup method that should be fixed!"
40
+ checkup_group
41
+ end
42
+
43
+ def groups
44
+ @@groups
42
45
  end
43
46
  end
44
47
 
45
- @@checkups = {}
48
+ def checkup if: -> { true }, group: :general, title: nil, precondition: false, &code
49
+ checkup_group = Hospital.find_or_create_checkup_group group
50
+ checkup = Checkup.new(
51
+ self,
52
+ code,
53
+ title: title,
54
+ condition: binding.local_variable_get('if'),
55
+ precondition: precondition
56
+ )
57
+
58
+ # p "adding #{checkup.inspect} to #{group_name}"
59
+ checkup_group.add_checkup checkup
60
+ end
46
61
 
47
- class << self
62
+ class Runner
63
+ attr_reader :verbose
48
64
 
49
- def included(klass)
50
- raise Hospital::Error.new("Cannot include Hospital, please extend instead.")
51
- end
65
+ def initialize verbose: false, formatter: :shell
66
+ @verbose = verbose
67
+ @formatter = case formatter
68
+ when :pre then Formatter::Pre
69
+ else Formatter::Shell
70
+ end
52
71
 
53
- def extended(klass)
54
- # only relevant if the class does not yet define a real checkup method
55
- @@checkups[klass] = Checkup.new klass, -> (diagnosis) do
56
- diagnosis.add_warning("#{klass}: No checks defined! Please call checkup with a lambda.")
57
- end, group: :general
72
+ @out = @formatter.new
73
+ # @out.put_group_header "using formatter #{@formatter}"
58
74
  end
59
75
 
60
- def do_checkup_all verbose: false
76
+ def do_checkup_all
61
77
  errcount = 0
62
78
  warcount = 0
63
79
 
64
- threads = @@checkups.map do |klass, checkup|
65
- Thread.new do
66
- Thread.current.report_on_exception = false
67
- checkup.check(verbose: verbose)
68
- end
69
- end
70
-
71
- threads.each &:join
80
+ Hospital.groups.each do |group|
81
+ @out.put_group_header group.header
82
+ group.run_checkups verbose: verbose
72
83
 
73
- @@checkups.group_by{|klass, checkup| checkup.group}.map do |group, checkups|
74
- puts group_header(group)
75
- first = false
76
-
77
- checkups.each do |klass, checkup|
84
+ group.all_checkups.each do |checkup|
78
85
  if diagnosis = checkup.diagnosis
79
86
  errcount += diagnosis.errors.count
80
87
  warcount += diagnosis.warnings.count
81
88
 
82
- if !checkup.skipped
83
- puts "Checking #{diagnosis.name}:".h2
84
- diagnosis.put_results
89
+ if !checkup.skipped && (!checkup.group.skipped || checkup.precondition)
90
+ @out.put_diagnosis_header "Checking #{diagnosis.name}:"
91
+ diagnosis.put_results @out
85
92
  elsif verbose
86
- puts "Skipped #{diagnosis.name}.".h2
93
+ @out.put_diagnosis_header "Skipped #{diagnosis.name}."
87
94
  end
88
95
  end
89
96
  end
90
97
  end
91
98
 
92
- puts <<~END
99
+ @out.put_summary errcount, warcount
93
100
 
94
- #{"Summary:".h1}
95
- #{"Errors: #{errcount}".red}
96
- #{"Warnings: #{warcount}".yellow}
97
- END
98
- end
99
-
100
- # used to call the checkup for a specific class directly (in specs)
101
- def do_checkup(klass)
102
- @@checkups[klass].check
103
- end
104
-
105
- def group_header group
106
- "### #{group.to_s.capitalize.gsub(/_/, ' ')} checks".h1
101
+ @out.buffer
107
102
  end
108
103
  end
109
-
110
- def checkup if: -> { true }, group: :general, title: nil, &code
111
- @@checkups[self] = Checkup.new self, code, group: group, title: title, condition: binding.local_variable_get('if')
112
- end
113
-
114
104
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hospital
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-26 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2024-03-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: byebug
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: require_all
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  description: Imagine a team of little doctors creating diagnoses and creating a useful
14
42
  report.
15
43
  email:
@@ -21,8 +49,13 @@ files:
21
49
  - LICENSE.txt
22
50
  - README.md
23
51
  - lib/hospital.rb
52
+ - lib/hospital/checkup.rb
53
+ - lib/hospital/checkup_group.rb
24
54
  - lib/hospital/diagnosis.rb
25
- - lib/hospital/formatter.rb
55
+ - lib/hospital/formatter/base.rb
56
+ - lib/hospital/formatter/pre.rb
57
+ - lib/hospital/formatter/shell.rb
58
+ - lib/hospital/string_formatter.rb
26
59
  - lib/hospital/tasks/checkup.rake
27
60
  - lib/hospital/version.rb
28
61
  - lib/railtie.rb
@@ -1,19 +0,0 @@
1
- module Formatter
2
- refine String do
3
- def h1
4
- "\n\e[4m\e[1m#{self}\e[0m"
5
- end
6
-
7
- def h2
8
- "\n\e[4m#{self}\e[0m"
9
- end
10
-
11
- def red
12
- "\e[31m#{self}\e[0m"
13
- end
14
-
15
- def yellow
16
- "\e[33m#{self}\e[0m"
17
- end
18
- end
19
- end