informator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +9 -0
- data/.metrics +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +15 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +5 -0
- data/Guardfile +14 -0
- data/LICENSE +21 -0
- data/README.md +141 -0
- data/Rakefile +27 -0
- data/config/metrics/STYLEGUIDE +226 -0
- data/config/metrics/cane.yml +5 -0
- data/config/metrics/churn.yml +6 -0
- data/config/metrics/flay.yml +2 -0
- data/config/metrics/metric_fu.yml +15 -0
- data/config/metrics/reek.yml +1 -0
- data/config/metrics/roodi.yml +24 -0
- data/config/metrics/rubocop.yml +76 -0
- data/config/metrics/saikuro.yml +3 -0
- data/config/metrics/simplecov.yml +8 -0
- data/config/metrics/yardstick.yml +37 -0
- data/informator.gemspec +23 -0
- data/lib/informator.rb +82 -0
- data/lib/informator/event.rb +80 -0
- data/lib/informator/reporter.rb +67 -0
- data/lib/informator/subscriber.rb +88 -0
- data/lib/informator/version.rb +9 -0
- data/spec/integration/informator_spec.rb +147 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/unit/informator/event_spec.rb +71 -0
- data/spec/unit/informator/reporter_spec.rb +75 -0
- data/spec/unit/informator/subscriber_spec.rb +86 -0
- metadata +100 -0
@@ -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,76 @@
|
|
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
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/Documentation:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/EmptyLinesAroundBlockBody:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/EmptyLinesAroundClassBody:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Style/EmptyLinesAroundMethodBody:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Style/EmptyLinesAroundModuleBody:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
Style/EmptyLineBetweenDefs:
|
44
|
+
Enabled: false
|
45
|
+
|
46
|
+
Style/FileName:
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
Style/RaiseArgs:
|
50
|
+
EnforcedStyle: compact
|
51
|
+
|
52
|
+
Style/RescueModifier:
|
53
|
+
Exclude:
|
54
|
+
- '**/*_spec.rb'
|
55
|
+
|
56
|
+
Style/SingleLineMethods:
|
57
|
+
Exclude:
|
58
|
+
- '**/*_spec.rb'
|
59
|
+
|
60
|
+
Style/SingleSpaceBeforeFirstArg:
|
61
|
+
Enabled: false
|
62
|
+
|
63
|
+
Style/SpecialGlobalVars:
|
64
|
+
Exclude:
|
65
|
+
- '**/Gemfile'
|
66
|
+
- '**/*.gemspec'
|
67
|
+
|
68
|
+
Style/StringLiterals:
|
69
|
+
EnforcedStyle: double_quotes
|
70
|
+
|
71
|
+
Style/StringLiteralsInInterpolation:
|
72
|
+
EnforcedStyle: double_quotes
|
73
|
+
|
74
|
+
Style/TrivialAccessors:
|
75
|
+
Exclude:
|
76
|
+
- '**/*_spec.rb'
|
@@ -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
|
data/informator.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "informator/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
|
6
|
+
gem.name = "informator"
|
7
|
+
gem.version = Informator::VERSION.dup
|
8
|
+
gem.author = "Andrew Kozin"
|
9
|
+
gem.email = "andrew.kozin@gmail.com"
|
10
|
+
gem.homepage = "https://github.com/nepalez/informator"
|
11
|
+
gem.summary = "Implementation of subscribe/publish design pattern"
|
12
|
+
gem.license = "MIT"
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
15
|
+
gem.test_files = Dir["spec/**/*.rb"]
|
16
|
+
gem.extra_rdoc_files = Dir["README.md", "LICENSE"]
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
|
19
|
+
gem.required_ruby_version = "~> 2.1"
|
20
|
+
|
21
|
+
gem.add_development_dependency "hexx-rspec", "~> 0.4"
|
22
|
+
|
23
|
+
end # Gem::Specification
|
data/lib/informator.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative "informator/event"
|
4
|
+
require_relative "informator/subscriber"
|
5
|
+
require_relative "informator/reporter"
|
6
|
+
|
7
|
+
# The module provides subscribe/publish/report features
|
8
|
+
#
|
9
|
+
module Informator
|
10
|
+
|
11
|
+
# Subscribes the listener for receiving events notifications via callback
|
12
|
+
#
|
13
|
+
# @param [Object] listener
|
14
|
+
# The object to send events to
|
15
|
+
# @param [#to_sym] callback (:receive)
|
16
|
+
# The name of the listener method to send events through
|
17
|
+
#
|
18
|
+
# @return [self] itself
|
19
|
+
#
|
20
|
+
def subscribe(listener, callback = :receive)
|
21
|
+
sub = Subscriber.new(listener, callback)
|
22
|
+
__subscribers__ << sub unless __subscribers__.include? sub
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
# @!method remember(type, messages, data)
|
28
|
+
# Builds and stores the event waiting for being published
|
29
|
+
#
|
30
|
+
# @param (see Informator::Event.new)
|
31
|
+
#
|
32
|
+
# @return [self] itself
|
33
|
+
#
|
34
|
+
def remember(*args)
|
35
|
+
__reporter__.remember(*args)
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
# @overload publish(type, messages, data)
|
41
|
+
# Builds the event and then publishes all unpublished events
|
42
|
+
#
|
43
|
+
# @param (see #remember)
|
44
|
+
#
|
45
|
+
# @overload publish
|
46
|
+
# Publishes all unpublished events without adding a new one
|
47
|
+
#
|
48
|
+
# @return [Array<Informator::Event>] list of events having been published
|
49
|
+
#
|
50
|
+
def publish(*args)
|
51
|
+
remember(*args) if args.any?
|
52
|
+
__reporter__.notify __subscribers__
|
53
|
+
end
|
54
|
+
|
55
|
+
# The same as `publish` except for it throws `:published` afterwards
|
56
|
+
#
|
57
|
+
# @overload publish(type, messages, data)
|
58
|
+
# Builds the event and then publishes all unpublished events
|
59
|
+
#
|
60
|
+
# @param (see #remember)
|
61
|
+
#
|
62
|
+
# @overload publish
|
63
|
+
# Publishes all unpublished events without adding a new one
|
64
|
+
#
|
65
|
+
# @raise [UncaughtThrowError, ArgumentError]
|
66
|
+
# for `:published` events being carried
|
67
|
+
#
|
68
|
+
def publish!(*args)
|
69
|
+
throw :published, publish(*args)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def __reporter__
|
75
|
+
@__reporter__ ||= Reporter.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def __subscribers__
|
79
|
+
@__subscribers__ ||= []
|
80
|
+
end
|
81
|
+
|
82
|
+
end # module Informator
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Informator
|
4
|
+
|
5
|
+
# Class Event provides an immutable container for hash of some data, to
|
6
|
+
# which a type is attached. It also contains an array of human-readable
|
7
|
+
# messages describing the event.
|
8
|
+
#
|
9
|
+
# The primary goal of events is folding data to be returned and/or sent
|
10
|
+
# between various objects into unified format.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# event = Event.new :success, "bingo!", foo: :bar
|
14
|
+
# # => #<Event @type=:success, @messages=["bingo!"], @data={ :foo => :bar }>
|
15
|
+
# event.frozen?
|
16
|
+
# # => true
|
17
|
+
#
|
18
|
+
class Event
|
19
|
+
|
20
|
+
include Comparable
|
21
|
+
|
22
|
+
# @!attribute [r] type
|
23
|
+
#
|
24
|
+
# @return [Symbol] the type of the event
|
25
|
+
#
|
26
|
+
attr_reader :type
|
27
|
+
|
28
|
+
# @!attribute [r] data
|
29
|
+
#
|
30
|
+
# @return [Hash] the event-specific data
|
31
|
+
#
|
32
|
+
attr_reader :data
|
33
|
+
|
34
|
+
# @!attribute [r] messages
|
35
|
+
#
|
36
|
+
# @return [Array<String>] human-readable messages, describing the event
|
37
|
+
#
|
38
|
+
attr_reader :messages
|
39
|
+
|
40
|
+
# @!scope class
|
41
|
+
# @!method new(type, messages, data)
|
42
|
+
# Builds the event
|
43
|
+
#
|
44
|
+
# @param [#to_sym] type
|
45
|
+
# @param [#to_s, Array<#to_s>] messages
|
46
|
+
# @param [Hash] data
|
47
|
+
#
|
48
|
+
# @return [Informator::Event]
|
49
|
+
|
50
|
+
# @private
|
51
|
+
def initialize(type, *messages, **data)
|
52
|
+
@type = type.to_sym
|
53
|
+
@messages = messages.flatten.map(&:to_s)
|
54
|
+
@data = data
|
55
|
+
freeze
|
56
|
+
end
|
57
|
+
|
58
|
+
# Compares the event to another one by their types and data
|
59
|
+
#
|
60
|
+
# @param [Object] other
|
61
|
+
#
|
62
|
+
# @return [Boolean]
|
63
|
+
#
|
64
|
+
def ==(other)
|
65
|
+
other.is_a?(self.class) && other.value.eql?(value)
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
# Returns value to compare events by
|
71
|
+
#
|
72
|
+
# @return [Array]
|
73
|
+
#
|
74
|
+
def value
|
75
|
+
[type, data]
|
76
|
+
end
|
77
|
+
|
78
|
+
end # class Event
|
79
|
+
|
80
|
+
end # module Informator
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Informator
|
4
|
+
|
5
|
+
# Builds, collects and publishes events to selected subscribers
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# reporter = Reporter.new
|
9
|
+
# reporter.events # => []
|
10
|
+
#
|
11
|
+
# reporter.remember :success
|
12
|
+
# reporter.events # => [#<Event @type=:success @data={} @messages=[]>]
|
13
|
+
#
|
14
|
+
# # this will call subscriber.notify for any event
|
15
|
+
# reporter.notify subscriber
|
16
|
+
# reporter.events # => []
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
class Reporter
|
21
|
+
|
22
|
+
# @private
|
23
|
+
def initialize
|
24
|
+
@events = []
|
25
|
+
freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
# @!attribute [r] events
|
29
|
+
# @return [Array<Informator::Event>]
|
30
|
+
# the list of registered events that havent'b been published yet
|
31
|
+
attr_reader :events
|
32
|
+
|
33
|
+
# @!method remember(type, messages, data)
|
34
|
+
# Registers the event to be published to subscribers
|
35
|
+
#
|
36
|
+
# @param (see Informator::Event.new)
|
37
|
+
#
|
38
|
+
# @return [self] itself
|
39
|
+
#
|
40
|
+
def remember(*args)
|
41
|
+
events << Event.new(*args)
|
42
|
+
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
# Notifies subscribers on events registered since the last notification
|
47
|
+
#
|
48
|
+
# Mutates [#events] by excluding all events having been published.
|
49
|
+
#
|
50
|
+
# @param [Informator::Subscriber, Array<Informator::Subscriber>] subscribers
|
51
|
+
# the list of subscribers to be notified
|
52
|
+
#
|
53
|
+
# @return [Array<Informator::Event>] the list of published events
|
54
|
+
def notify(*subscribers)
|
55
|
+
events.dup.each { publish subscribers.flatten }
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def publish(subscribers)
|
61
|
+
event = events.shift
|
62
|
+
subscribers.each { |subscriber| subscriber.notify event }
|
63
|
+
end
|
64
|
+
|
65
|
+
end # class Reporter
|
66
|
+
|
67
|
+
end # module Informator
|