chronicles 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ ---
2
+ abc_max: "10"
3
+ line_length: "80"
4
+ no_doc: "y"
5
+ no_readme: "y"
@@ -0,0 +1,6 @@
1
+ ---
2
+ ignore_files:
3
+ - spec
4
+ - config
5
+ minimum_churn_count: 0
6
+ start_date: "1 year ago"
@@ -0,0 +1,2 @@
1
+ ---
2
+ minimum_score: 5
@@ -0,0 +1,15 @@
1
+ ---
2
+ folders: # The list of folders to be used by any metric.
3
+ - lib
4
+ - app
5
+ metrics: # The list of allowed metrics. The other metrics are disabled.
6
+ - cane
7
+ - churn
8
+ - flay
9
+ - flog
10
+ - reek
11
+ - roodi
12
+ - saikuro
13
+ format: html
14
+ output: tmp/metric_fu
15
+ verbose: false
@@ -0,0 +1 @@
1
+ ---
@@ -0,0 +1,24 @@
1
+ ---
2
+ AssignmentInConditionalCheck:
3
+ CaseMissingElseCheck:
4
+ ClassLineCountCheck:
5
+ line_count: 300
6
+ ClassNameCheck:
7
+ pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
8
+ ClassVariableCheck:
9
+ CyclomaticComplexityBlockCheck:
10
+ complexity: 4
11
+ CyclomaticComplexityMethodCheck:
12
+ complexity: 8
13
+ EmptyRescueBodyCheck:
14
+ ForLoopCheck:
15
+ MethodLineCountCheck:
16
+ line_count: 20
17
+ MethodNameCheck:
18
+ pattern: !ruby/regexp /^[\||\^|\&|\!]$|^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
19
+ ModuleLineCountCheck:
20
+ line_count: 300
21
+ ModuleNameCheck:
22
+ pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
23
+ ParameterNumberCheck:
24
+ parameter_count: 5
@@ -0,0 +1,77 @@
1
+ ---
2
+ # settings added by the 'hexx-suit' module
3
+ # output: "tmp/rubocop"
4
+ # format: "html"
5
+
6
+ AllCops:
7
+ Exclude:
8
+ - '**/db/schema.rb'
9
+
10
+ Lint/HandleExceptions:
11
+ Exclude:
12
+ - '**/*_spec.rb'
13
+
14
+ Lint/RescueException:
15
+ Exclude:
16
+ - '**/*_spec.rb'
17
+
18
+ Style/AccessorMethodName:
19
+ Exclude:
20
+ - '**/*_spec.rb'
21
+
22
+ Style/AsciiComments:
23
+ Enabled: false
24
+
25
+ Style/ClassAndModuleChildren:
26
+ Exclude:
27
+ - '**/*_spec.rb'
28
+
29
+ Style/Documentation:
30
+ Enabled: false
31
+
32
+ Style/EmptyLinesAroundBlockBody:
33
+ Enabled: false
34
+
35
+ Style/EmptyLinesAroundClassBody:
36
+ Enabled: false
37
+
38
+ Style/EmptyLinesAroundMethodBody:
39
+ Enabled: false
40
+
41
+ Style/EmptyLinesAroundModuleBody:
42
+ Enabled: false
43
+
44
+ Style/EmptyLineBetweenDefs:
45
+ Enabled: false
46
+
47
+ Style/FileName:
48
+ Enabled: false
49
+
50
+ Style/MethodCallParentheses:
51
+ Exclude:
52
+ - '**/updater.rb'
53
+
54
+ Style/RaiseArgs:
55
+ EnforcedStyle: compact
56
+
57
+ Style/SingleLineMethods:
58
+ Exclude:
59
+ - '**/*_spec.rb'
60
+
61
+ Style/SingleSpaceBeforeFirstArg:
62
+ Enabled: false
63
+
64
+ Style/SpecialGlobalVars:
65
+ Exclude:
66
+ - '**/Gemfile'
67
+ - '**/*.gemspec'
68
+
69
+ Style/StringLiterals:
70
+ EnforcedStyle: double_quotes
71
+
72
+ Style/StringLiteralsInInterpolation:
73
+ EnforcedStyle: double_quotes
74
+
75
+ Style/TrivialAccessors:
76
+ Exclude:
77
+ - '**/*_spec.rb'
@@ -0,0 +1,3 @@
1
+ ---
2
+ warn_cyclo: 4
3
+ error_cyclo: 6
@@ -0,0 +1,8 @@
1
+ ---
2
+ output: tmp/coverage
3
+ filters: # The list of paths to be excluded from coverage checkup
4
+ - "spec/"
5
+ - "config/"
6
+ groups: # The list of groups to be shown in the coverage report
7
+ Libraries: "lib/"
8
+ Application: "app/"
@@ -0,0 +1,37 @@
1
+ ---
2
+ # Settings added by the 'hexx-suit' gem
3
+ output: "tmp/yardstick/output.log"
4
+ path: "lib/**/*.rb"
5
+ rules:
6
+ ApiTag::Presence:
7
+ enabled: true
8
+ exclude: []
9
+ ApiTag::Inclusion:
10
+ enabled: true
11
+ exclude: []
12
+ ApiTag::ProtectedMethod:
13
+ enabled: true
14
+ exclude: []
15
+ ApiTag::PrivateMethod:
16
+ enabled: false
17
+ exclude: []
18
+ ExampleTag:
19
+ enabled: true
20
+ exclude: []
21
+ ReturnTag:
22
+ enabled: true
23
+ exclude: []
24
+ Summary::Presence:
25
+ enabled: true
26
+ exclude: []
27
+ Summary::Length:
28
+ enabled: true
29
+ exclude: []
30
+ Summary::Delimiter:
31
+ enabled: true
32
+ exclude: []
33
+ Summary::SingleLine:
34
+ enabled: true
35
+ exclude: []
36
+ threshold: 100
37
+ verbose: false
@@ -0,0 +1,80 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative "chronicles/version"
4
+ require_relative "chronicles/methods"
5
+ require_relative "chronicles/updater"
6
+ require_relative "chronicles/injector"
7
+
8
+ # The module adds features to keep chronicles of object's methods calls
9
+ module Chronicles
10
+
11
+ # @!attribute [r] chronicles
12
+ # Returns the array of object methods having been called
13
+ #
14
+ # @return [Array<Symbol>]
15
+ def chronicles
16
+ @chronicles ||= []
17
+ end
18
+
19
+ # Starts registation of calls of the selected methods of the object
20
+ #
21
+ # @example
22
+ # class Test
23
+ # include Chronicles
24
+ # end
25
+ #
26
+ # test = Test.new
27
+ # test.start_chronicles only: :foo
28
+ # test.foo
29
+ # test.bar
30
+ # test.baz
31
+ # test.foo
32
+ # test.chronicles # => [:foo, :foo]
33
+ #
34
+ # @param [Hash] options
35
+ # describes the selection of methods to include to chronicles
36
+ # @option options [Boolean] :public (true)
37
+ # whether public methods should be looked after
38
+ # @option options [Boolean] :protected (true)
39
+ # whether protected methods should be looked after
40
+ # @option options [Boolean] :private (true)
41
+ # whether private methods should be looked after
42
+ # @option options [Array<#to_sym>] :except ([])
43
+ # the whitelist of methods that shouldn't be looked after
44
+ # @option options [Array<#to_sym>] :only ([])
45
+ # the whitelist of methods that should be looked after
46
+ #
47
+ # @return [undefined]
48
+ def start_chronicles(**options)
49
+ Injector.new(self, "chronicles << __method__", options).run
50
+ end
51
+
52
+ # Stops registation of calls of the selected methods of the object
53
+ #
54
+ # @example
55
+ # class Test
56
+ # include Chronicles
57
+ # end
58
+ #
59
+ # test = Test.new
60
+ # test.start_chronicles
61
+ # test.foo
62
+ # test.bar
63
+ # test.baz
64
+ # test.chronicles # => [:foo, :bar, :baz]
65
+ #
66
+ # test.stop_chronicles except: :foo
67
+ # test.foo
68
+ # test.bar
69
+ # test.baz
70
+ # test.chronicles # => [:foo, :bar, :baz, :foo]
71
+ #
72
+ # @param (see #start_chronicles)
73
+ # @option (see #start_chronicles)
74
+ #
75
+ # @return [undefined]
76
+ def stop_chronicles(**options)
77
+ Injector.new(self, options).run
78
+ end
79
+
80
+ end # module Chronicles
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ module Chronicles
4
+
5
+ # Injects the code to object methods selected by options
6
+ #
7
+ # @private
8
+ class Injector
9
+
10
+ attr_reader :object, :code, :list
11
+
12
+ def initialize(object, code = nil, **options)
13
+ @object = object
14
+ @code = code
15
+ @list = Methods.new(object, options)
16
+ end
17
+
18
+ def updaters
19
+ list.map { |name| Updater.new(object, name, code) }
20
+ end
21
+
22
+ def run
23
+ updaters.each(&:run)
24
+ end
25
+
26
+ end # class Injector
27
+
28
+ end # module Chronicles
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ module Chronicles
4
+
5
+ # Array of object methods selected by options
6
+ #
7
+ # @private
8
+ class Methods < Array
9
+
10
+ def initialize(object, **options)
11
+ @object = object
12
+ @options = options
13
+ super(whitelist.empty? ? list : list & whitelist)
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :object, :options
19
+
20
+ def list
21
+ [public_list, protected_list, private_list].flatten.compact - blacklist
22
+ end
23
+
24
+ def whitelist
25
+ Array(options[:only]).map(&:to_sym)
26
+ end
27
+
28
+ def blacklist
29
+ Array(options[:except]).map(&:to_sym)
30
+ end
31
+
32
+ def public_list
33
+ return if options[:public].equal?(false)
34
+ object.public_methods - Object.public_instance_methods - own_list
35
+ end
36
+
37
+ def own_list
38
+ %i(chronicles start_chronicles stop_chronicles)
39
+ end
40
+
41
+ def protected_list
42
+ return if options[:protected].equal?(false)
43
+ object.protected_methods
44
+ end
45
+
46
+ def private_list
47
+ return if options[:private].equal?(false)
48
+ object.private_methods - Object.private_instance_methods
49
+ end
50
+
51
+ end # class Methods
52
+
53
+ end # module Chronicles
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ module Chronicles
4
+
5
+ # Reloads object method
6
+ #
7
+ # @private
8
+ class Updater
9
+
10
+ def initialize(object, name, code = nil)
11
+ @object = object
12
+ @name = name
13
+ @code = code
14
+ type
15
+ end
16
+
17
+ attr_reader :object, :name, :code
18
+
19
+ def type
20
+ @type ||= %w(public private protected).detect do |item|
21
+ object.public_send("#{ item }_methods").include? name
22
+ end
23
+ end
24
+
25
+ def klass
26
+ object.singleton_class
27
+ end
28
+
29
+ def run
30
+ redefine_method
31
+ protect_method
32
+ end
33
+
34
+ private
35
+
36
+ def redefine_method
37
+ code = code()
38
+ klass.__send__ :define_method, name do |*args|
39
+ instance_eval(code) if code
40
+ super(*args)
41
+ end
42
+ end
43
+
44
+ def protect_method
45
+ klass.instance_eval "#{ type } :#{ name }"
46
+ end
47
+
48
+ end # class Updater
49
+
50
+ end # module Chronicles
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ module Chronicles
4
+
5
+ # The semantic version of the module.
6
+ # @see http://semver.org/ Semantic versioning 2.0
7
+ VERSION = "0.0.1".freeze
8
+
9
+ end # module Chronicles
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require "hexx-suit"
5
+ Hexx::Suit.load_metrics_for(self)
6
+ rescue LoadError
7
+ require "hexx-rspec"
8
+ Hexx::RSpec.load_metrics_for(self)
9
+ end
10
+
11
+ # Loads the code under test
12
+ require "chronicles"
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+
3
+ describe Chronicles::Injector do
4
+
5
+ let(:object) { double foo: nil, bar: nil, baz: nil }
6
+ let(:options) { { only: %i(foo bar), private: false } }
7
+ let(:code) { "chronicles << __method__" }
8
+ subject { described_class.new object, code, options }
9
+
10
+ describe "#object" do
11
+
12
+ it "is initialized" do
13
+ expect(subject.object).to eq object
14
+ end
15
+
16
+ end # describe #object
17
+
18
+ describe "#list" do
19
+
20
+ let(:list) { Chronicles::Methods.new(object, options).to_a }
21
+
22
+ it "is initialized" do
23
+ expect(subject.list).to eq list
24
+ end
25
+
26
+ end # describe #list
27
+
28
+ describe "#code" do
29
+
30
+ it "is initialized" do
31
+ expect(subject.code).to eq code
32
+ end
33
+
34
+ it "can be nil" do
35
+ subject = described_class.new object, options
36
+ expect(subject.code).to be_nil
37
+ end
38
+
39
+ end # describe #code
40
+
41
+ describe "#updaters" do
42
+
43
+ let(:list) { %i(foo bar baz) }
44
+ before { allow(subject).to receive(:list).and_return list }
45
+
46
+ it "returns updaters" do
47
+ subject.updaters.each do |updater|
48
+ expect(updater).to be_kind_of Chronicles::Updater
49
+ end
50
+ end
51
+
52
+ it "constructed for #object" do
53
+ subject.updaters.each do |updater|
54
+ expect(updater.object).to eq subject.object
55
+ end
56
+ end
57
+
58
+ it "constructed for #list of methods" do
59
+ expect(subject.updaters.map(&:name)).to eq subject.list
60
+ end
61
+
62
+ it "constructed for #code" do
63
+ subject.updaters.each do |updater|
64
+ expect(updater.code).to eq subject.code
65
+ end
66
+ end
67
+
68
+ end # describe #updaters
69
+
70
+ describe ".run" do
71
+
72
+ let(:updaters) { 2.times.map { double run: nil } }
73
+ before { allow(subject).to receive(:updaters).and_return updaters }
74
+
75
+ it "runs updaters" do
76
+ updaters.each { |updater| expect(updater).to receive(:run) }
77
+ subject.run
78
+ end
79
+
80
+ end # describe .run
81
+
82
+ end # describe Chronicles::Injector