signal 0.3.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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