signal 0.3.0 → 1.3.0

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,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Signal
4
+ class Mock
5
+ def calls
6
+ @calls ||= []
7
+ end
8
+
9
+ def method_missing(name, *args)
10
+ return super unless respond_to_missing?(name)
11
+
12
+ calls << {event: name.to_s.gsub(/^on_/, "").to_sym, args: args}
13
+ end
14
+
15
+ def respond_to_missing?(name, _include_all = false)
16
+ name =~ /^on_/
17
+ end
18
+
19
+ def received?(event, options = {})
20
+ received_event?(event, options[:times] || -1) &&
21
+ received_with?(event, options[:with])
22
+ end
23
+
24
+ def to_proc
25
+ proc {|action| action.add_listener(self) }
26
+ end
27
+
28
+ def on(event)
29
+ proc {|*args| calls << {event: event, args: args} }
30
+ end
31
+
32
+ private def received_event?(event, count)
33
+ received_calls = calls.count {|call| call[:event] == event }
34
+
35
+ return received_calls.nonzero? if count == -1
36
+
37
+ received_calls == count
38
+ end
39
+
40
+ private def received_with?(event, args)
41
+ return true unless args
42
+
43
+ calls.any? do |call|
44
+ next unless call[:event] == event
45
+ next args.call(call[:args]) if args.is_a?(Proc)
46
+
47
+ args == call[:args]
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Signal
2
- VERSION = '0.3.0'
4
+ VERSION = "1.3.0"
3
5
  end
data/lib/signal.rb CHANGED
@@ -1,7 +1,9 @@
1
- require 'signal/active_record'
2
- require 'signal/listener'
3
- require 'signal/call'
4
- require 'signal/version'
1
+ # frozen_string_literal: true
2
+
3
+ require "signal/version"
4
+ require "signal/listener"
5
+ require "signal/extensions/active_record"
6
+ require "signal/extensions/call"
5
7
 
6
8
  module Signal
7
9
  def on(event, &block)
@@ -35,11 +37,13 @@ module Signal
35
37
  @listeners ||= []
36
38
  end
37
39
 
38
- private
39
- def emit_signal(type, event, *args)
40
+ private def emit_signal(type, event, *args)
40
41
  listeners.each do |listener|
41
42
  method_name = "#{type}_#{event}"
42
- listener.send(method_name, *args) if listener.respond_to?(method_name, true)
43
+
44
+ if listener.respond_to?(method_name, true)
45
+ listener.send(method_name, *args)
46
+ end
43
47
  end
44
48
  end
45
49
  end
data/signal.gemspec CHANGED
@@ -1,21 +1,34 @@
1
- require './lib/signal/version'
1
+ # frozen_string_literal: true
2
2
 
3
- Gem::Specification.new do |gem|
4
- gem.name = 'signal'
5
- gem.version = Signal::VERSION
6
- gem.authors = ['Nando Vieira']
7
- gem.email = ['fnando.vieira@gmail.com']
8
- gem.description = 'A simple observer implementation for POROs (Plain Old Ruby Object) and ActiveRecord objects.'
9
- gem.summary = gem.description
10
- gem.homepage = 'http://github.com/fnando/signal'
3
+ require "./lib/signal/version"
11
4
 
12
- gem.files = `git ls-files`.split($/)
13
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
- gem.require_paths = ['lib']
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "signal"
7
+ spec.version = Signal::VERSION
8
+ spec.authors = ["Nando Vieira"]
9
+ spec.email = ["fnando.vieira@gmail.com"]
10
+ spec.description = %w[
11
+ A simple observer implementation for POROs (Plain Old Ruby Object) and
12
+ ActiveRecord objects.
13
+ ].join(" ")
14
+ spec.summary = spec.description
15
+ spec.homepage = "http://github.com/fnando/signal"
16
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
16
17
 
17
- gem.add_development_dependency 'activerecord'
18
- gem.add_development_dependency 'sqlite3'
19
- gem.add_development_dependency 'rspec'
20
- gem.add_development_dependency 'codeclimate-test-reporter'
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+
22
+ spec.executables = spec.files.grep(%r{^bin/}).map {|f| File.basename(f) }
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_development_dependency "activerecord"
27
+ spec.add_development_dependency "minitest-utils"
28
+ spec.add_development_dependency "pry-meta"
29
+ spec.add_development_dependency "rake"
30
+ spec.add_development_dependency "rubocop"
31
+ spec.add_development_dependency "rubocop-fnando"
32
+ spec.add_development_dependency "simplecov"
33
+ spec.add_development_dependency "sqlite3"
21
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: signal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-24 00:00:00.000000000 Z
11
+ date: 2021-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -25,7 +25,21 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: sqlite3
28
+ name: minitest-utils
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry-meta
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
@@ -39,7 +53,7 @@ dependencies:
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: rspec
56
+ name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
@@ -53,7 +67,49 @@ dependencies:
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: codeclimate-test-reporter
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-fnando
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sqlite3
57
113
  requirement: !ruby/object:Gem::Requirement
58
114
  requirements:
59
115
  - - ">="
@@ -74,8 +130,9 @@ executables: []
74
130
  extensions: []
75
131
  extra_rdoc_files: []
76
132
  files:
133
+ - ".github/FUNDING.yml"
77
134
  - ".gitignore"
78
- - ".rspec"
135
+ - ".rubocop.yml"
79
136
  - ".travis.yml"
80
137
  - Gemfile
81
138
  - LICENSE.txt
@@ -85,27 +142,20 @@ files:
85
142
  - examples/arguments.rb
86
143
  - examples/block_context.rb
87
144
  - examples/blocks.rb
145
+ - examples/call.rb
88
146
  - examples/chain.rb
89
147
  - examples/listener.rb
90
148
  - lib/signal.rb
91
- - lib/signal/active_record.rb
92
- - lib/signal/call.rb
149
+ - lib/signal/extensions/active_record.rb
150
+ - lib/signal/extensions/call.rb
93
151
  - lib/signal/listener.rb
152
+ - lib/signal/mock.rb
94
153
  - lib/signal/version.rb
95
154
  - signal.gemspec
96
- - spec/signal/activerecord_spec.rb
97
- - spec/signal/call_spec.rb
98
- - spec/signal/listener_spec.rb
99
- - spec/signal/signal_spec.rb
100
- - spec/spec_helper.rb
101
- - spec/support/callable.rb
102
- - spec/support/observable.rb
103
- - spec/support/observable_with_call.rb
104
- - spec/support/user.rb
105
155
  homepage: http://github.com/fnando/signal
106
156
  licenses: []
107
157
  metadata: {}
108
- post_install_message:
158
+ post_install_message:
109
159
  rdoc_options: []
110
160
  require_paths:
111
161
  - lib
@@ -113,26 +163,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
163
  requirements:
114
164
  - - ">="
115
165
  - !ruby/object:Gem::Version
116
- version: '0'
166
+ version: 2.7.0
117
167
  required_rubygems_version: !ruby/object:Gem::Requirement
118
168
  requirements:
119
169
  - - ">="
120
170
  - !ruby/object:Gem::Version
121
171
  version: '0'
122
172
  requirements: []
123
- rubyforge_project:
124
- rubygems_version: 2.4.5.1
125
- signing_key:
173
+ rubygems_version: 3.2.32
174
+ signing_key:
126
175
  specification_version: 4
127
176
  summary: A simple observer implementation for POROs (Plain Old Ruby Object) and ActiveRecord
128
177
  objects.
129
- test_files:
130
- - spec/signal/activerecord_spec.rb
131
- - spec/signal/call_spec.rb
132
- - spec/signal/listener_spec.rb
133
- - spec/signal/signal_spec.rb
134
- - spec/spec_helper.rb
135
- - spec/support/callable.rb
136
- - spec/support/observable.rb
137
- - spec/support/observable_with_call.rb
138
- - spec/support/user.rb
178
+ test_files: []
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --color
data/lib/signal/call.rb DELETED
@@ -1,21 +0,0 @@
1
- module Signal
2
- def self.call
3
- Call
4
- end
5
-
6
- module Call
7
- def self.included(target)
8
- target.include(Signal)
9
- target.extend(ClassMethods)
10
- end
11
-
12
- module ClassMethods
13
- def call(*args, &block)
14
- new(*args).tap do |instance|
15
- yield(instance)
16
- instance.call
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,132 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Signal::ActiveRecord do
4
- let(:callable) { Callable.new }
5
- let(:user) { User.new(:username => 'johndoe') }
6
-
7
- context 'create event' do
8
- it 'triggers before event' do
9
- user.before(:create, &callable)
10
- expect(callable).to receive(:called).with(user)
11
- user.save!
12
- end
13
-
14
- it 'triggers event' do
15
- user.on(:create, &callable)
16
- expect(callable).to receive(:called).with(user)
17
- user.save!
18
- end
19
-
20
- it 'triggers after event' do
21
- user.after(:create, &callable)
22
- expect(callable).to receive(:called).with(user)
23
- user.save!
24
- end
25
-
26
- it 'does not trigger on/after events when record is invalid' do
27
- user = User.new
28
-
29
- on_callable = Callable.new
30
- after_callable = Callable.new
31
-
32
- user
33
- .on(:create, &on_callable)
34
- .after(:create, &after_callable)
35
-
36
- expect(on_callable).not_to receive(:called)
37
- expect(after_callable).not_to receive(:called)
38
-
39
- user.save
40
- end
41
- end
42
-
43
- context 'validation event' do
44
- it 'triggers before event' do
45
- user.before(:validation, &callable)
46
- expect(callable).to receive(:called).with(user)
47
- user.save!
48
- end
49
-
50
- it 'triggers after event' do
51
- user.after(:validation, &callable)
52
- expect(callable).to receive(:called).with(user)
53
- user.save!
54
- end
55
-
56
- it 'triggers validation event when record is invalid' do
57
- user.username = nil
58
- user.on(:validation, &callable)
59
- expect(callable).to receive(:called).with(user)
60
- user.save
61
- end
62
-
63
- it 'skips validation event when record is valid' do
64
- user.on(:validation, &callable)
65
- expect(callable).not_to receive(:called)
66
- user.save!
67
- end
68
- end
69
-
70
- context 'update event' do
71
- let(:user) { User.create!(:username => 'johndoe') }
72
-
73
- it 'triggers before event' do
74
- user.before(:update, &callable)
75
- expect(callable).to receive(:called).with(user)
76
- user.update_attributes!(:username => 'johnd')
77
- end
78
-
79
- it 'triggers on event' do
80
- user.on(:update, &callable)
81
- expect(callable).to receive(:called).with(user)
82
- user.update_attributes!(:username => 'johnd')
83
- end
84
-
85
- it 'triggers after event' do
86
- user.after(:update, &callable)
87
- expect(callable).to receive(:called).with(user)
88
- user.update_attributes!(:username => 'johnd')
89
- end
90
-
91
- it 'does not trigger on/after events when record is invalid' do
92
- user.username = nil
93
-
94
- on_callable = Callable.new
95
- after_callable = Callable.new
96
-
97
- user
98
- .on(:update, &on_callable)
99
- .after(:update, &after_callable)
100
-
101
- expect(on_callable).not_to receive(:called)
102
- expect(after_callable).not_to receive(:called)
103
-
104
- user.save
105
- end
106
- end
107
-
108
- context 'remove event' do
109
- let(:user) { User.create!(:username => 'johndoe') }
110
-
111
- it 'triggers before event' do
112
- user.before(:remove, &callable)
113
- expect(callable).to receive(:called).with(user)
114
-
115
- user.destroy
116
- end
117
-
118
- it 'triggers on event' do
119
- user.on(:remove, &callable)
120
- expect(callable).to receive(:called).with(user)
121
-
122
- user.destroy
123
- end
124
-
125
- it 'triggers after event' do
126
- user.after(:remove, &callable)
127
- expect(callable).to receive(:called).with(user)
128
-
129
- user.destroy
130
- end
131
- end
132
- end
@@ -1,18 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Signal::Call do
4
- let(:callable) { Callable.new }
5
-
6
- it 'initializes observable with arguments' do
7
- observable = ObservableWithCall.call(1, 2, 3) {}
8
- expect(observable.args).to eq([1, 2, 3])
9
- end
10
-
11
- it 'triggers event' do
12
- expect(callable).to receive(:called).with([1, 2, 3])
13
-
14
- ObservableWithCall.call(1, 2, 3) do |o|
15
- o.on(:args, &callable)
16
- end
17
- end
18
- end
@@ -1,8 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Signal::Listener do
4
- it 'sets string representation' do
5
- listener = Signal::Listener.new(self, :on, :ready, &->{})
6
- expect(listener.to_s).to eq('<Signal::Listener event: on_ready>')
7
- end
8
- end
@@ -1,123 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Signal do
4
- let(:observable) { Observable.new }
5
- let(:callable) { Callable.new }
6
-
7
- context 'add listener' do
8
- it 'runs listener' do
9
- callable.respond_to(:on_ready)
10
- observable.add_listener(callable)
11
- expect(callable).to receive(:called).with(no_args)
12
-
13
- observable.emit(:ready)
14
- end
15
-
16
- it 'returns itself' do
17
- expect(observable.add_listener(callable)).to eq(observable)
18
- end
19
- end
20
-
21
- context 'using blocks' do
22
- it 'triggers event' do
23
- observable.on(:ready, &callable)
24
- expect(callable).to receive(:called).with(no_args)
25
-
26
- observable.emit(:ready)
27
- end
28
-
29
- it 'triggers event with arguments' do
30
- observable.on(:ready, &callable)
31
- expect(callable).to receive(:called).with(1, 2, 3)
32
-
33
- observable.emit(:ready, 1, 2, 3)
34
- end
35
-
36
- it 'triggers before event' do
37
- observable.before(:ready, &callable)
38
- expect(callable).to receive(:called).with(no_args)
39
-
40
- observable.emit(:ready)
41
- end
42
-
43
- it 'triggers before event with arguments' do
44
- observable.before(:ready, &callable)
45
- expect(callable).to receive(:called).with(1, 2, 3)
46
-
47
- observable.emit(:ready, 1, 2, 3)
48
- end
49
-
50
- it 'triggers after event' do
51
- observable.after(:ready, &callable)
52
- expect(callable).to receive(:called).with(no_args)
53
-
54
- observable.emit(:ready)
55
- end
56
-
57
- it 'triggers after event with arguments' do
58
- observable.after(:ready, &callable)
59
- expect(callable).to receive(:called).with(1, 2, 3)
60
-
61
- observable.emit(:ready, 1, 2, 3)
62
- end
63
-
64
- it 'chains events' do
65
- before_callable = Callable.new
66
- on_callable = Callable.new
67
- after_callable = Callable.new
68
-
69
- observable
70
- .before(:ready, &before_callable)
71
- .on(:ready, &on_callable)
72
- .after(:ready, &after_callable)
73
-
74
- expect(before_callable).to receive(:called).with(no_args).ordered
75
- expect(on_callable).to receive(:called).with(no_args).ordered
76
- expect(after_callable).to receive(:called).with(no_args).ordered
77
-
78
- observable.emit(:ready)
79
- end
80
-
81
- it 'keeps context' do
82
- context = nil
83
- callable = -> { context = self }
84
- observable.on(:ready, &callable)
85
- observable.emit(:ready)
86
-
87
- expect(context).to eql(self)
88
- end
89
- end
90
-
91
- context 'using listeners' do
92
- it 'triggers event for listener' do
93
- callable.respond_to(:on_ready)
94
- observable.listeners << callable
95
- expect(callable).to receive(:called).with(no_args)
96
-
97
- observable.emit(:ready)
98
- end
99
-
100
- it 'triggers event for listener with arguments' do
101
- callable.respond_to(:on_ready)
102
- observable.listeners << callable
103
- expect(callable).to receive(:called).with(1, 2, 3)
104
-
105
- observable.emit(:ready, 1, 2, 3)
106
- end
107
- end
108
-
109
- context 'mixed listeners' do
110
- it 'calls all listeners' do
111
- callable.respond_to(:on_ready)
112
- another_callable = Callable.new
113
-
114
- expect(callable).to receive(:called).ordered
115
- expect(another_callable).to receive(:called).ordered
116
-
117
- observable
118
- .add_listener(callable)
119
- .on(:ready, &another_callable)
120
- .emit(:ready)
121
- end
122
- end
123
- end
data/spec/spec_helper.rb DELETED
@@ -1,24 +0,0 @@
1
- require 'codeclimate-test-reporter'
2
- CodeClimate::TestReporter.start
3
-
4
- require 'bundler/setup'
5
- require 'active_record'
6
-
7
- I18n.enforce_available_locales = false
8
-
9
- require 'signal'
10
- require 'support/observable'
11
- require 'support/observable_with_call'
12
- require 'support/callable'
13
- require 'support/user'
14
-
15
- ActiveRecord::Base.establish_connection({
16
- :adapter => 'sqlite3',
17
- :database => ':memory:'
18
- })
19
-
20
- ActiveRecord::Schema.define(:version => 0) do
21
- create_table :users do |t|
22
- t.string :username
23
- end
24
- end
@@ -1,10 +0,0 @@
1
- class Callable
2
- def to_proc
3
- callable = self
4
- proc {|*args| callable.called(*args) }
5
- end
6
-
7
- def respond_to(method_name)
8
- define_singleton_method(method_name, &to_proc)
9
- end
10
- end
@@ -1,3 +0,0 @@
1
- class Observable
2
- include Signal
3
- end
@@ -1,13 +0,0 @@
1
- class ObservableWithCall
2
- include Signal.call
3
-
4
- attr_reader :args
5
-
6
- def initialize(*args)
7
- @args = args
8
- end
9
-
10
- def call
11
- emit(:args, @args)
12
- end
13
- end
data/spec/support/user.rb DELETED
@@ -1,4 +0,0 @@
1
- class User < ActiveRecord::Base
2
- include Signal::ActiveRecord
3
- validates_presence_of :username
4
- end