u-observers 2.3.0 → 3.0.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.
data/bin/setup CHANGED
@@ -3,6 +3,10 @@ set -euo pipefail
3
3
  IFS=$'\n\t'
4
4
  set -vx
5
5
 
6
+ rm -f Gemfile.lock
7
+
6
8
  bundle install
7
9
 
10
+ bundle exec appraisal install
11
+
8
12
  # Do any other automated setup that you need to do here
@@ -6,7 +6,7 @@ module Micro
6
6
 
7
7
  module ActiveModel
8
8
  module ClassMethods
9
- def notify_observers!(events)
9
+ def notify_observers_proc(events)
10
10
  proc do |object|
11
11
  object.observers.subject_changed!
12
12
  object.observers.send(:broadcast_if_subject_changed, events)
@@ -14,19 +14,133 @@ module Micro
14
14
  end
15
15
 
16
16
  def notify_observers(*events)
17
- notify_observers!(Event::Names.fetch(events))
17
+ notify_observers_proc(Event::Names.fetch(events))
18
18
  end
19
19
 
20
20
  def notify_observers_on(*callback_methods)
21
21
  Utils::Arrays.fetch_from_args(callback_methods).each do |callback_method|
22
- self.public_send(callback_method, &notify_observers!([callback_method]))
22
+ self.public_send(callback_method, &notify_observers_proc([callback_method]))
23
23
  end
24
24
  end
25
+
26
+ NO_OBSERVERS_TO_NOTIFY_MSG =
27
+ 'no observers (expected at least one observer in `with:`)'.freeze
28
+
29
+ NO_EVENT_TO_NOTIFY_MSG =
30
+ 'no event (expected a callback name in `event:`)'.freeze
31
+
32
+ def notify_observers!(event:, with:, context: nil, **callback_options)
33
+ observers = Utils::Arrays.flatten_and_compact(with)
34
+
35
+ raise ArgumentError, NO_OBSERVERS_TO_NOTIFY_MSG if observers.empty?
36
+
37
+ events = Utils::Arrays.flatten_and_compact(event)
38
+
39
+ raise ArgumentError, NO_EVENT_TO_NOTIFY_MSG if events.empty?
40
+
41
+ events.each do |callback_method|
42
+ register_observers_to_notify(callback_method, observers, context)
43
+
44
+ install_observers_to_notify_callback(callback_method, callback_options)
45
+ end
46
+ end
47
+
48
+ # Introspection: the observers declared via `notify_observers!`, keyed
49
+ # by the callback they fire on. e.g. { after_commit: [TitlePrinter] }
50
+ def observers_to_notify
51
+ __observers_to_notify.each_with_object({}) do |(event, entries), result|
52
+ result[event] = entries.map { |observer, _context| observer } unless entries.empty?
53
+ end
54
+ end
55
+
56
+ # Remove previously declared observers. Without `from:` they are
57
+ # removed from every callback; pass `from:` (a callback name or an
58
+ # array of them) to scope it. With no observers, clears the callback(s).
59
+ def detach_observers_to_notify(*observers, from: nil)
60
+ observers = Utils::Arrays.flatten_and_compact(observers)
61
+ events = from ? Utils::Arrays.flatten_and_compact(from) : __observers_to_notify.keys
62
+
63
+ events.each do |event|
64
+ entries = __observers_to_notify[event]
65
+
66
+ next unless entries
67
+
68
+ if observers.empty?
69
+ __observers_to_notify.delete(event)
70
+ else
71
+ entries.reject! { |observer, _context| observers.include?(observer) }
72
+ __observers_to_notify.delete(event) if entries.empty?
73
+ end
74
+ end
75
+
76
+ observers_to_notify
77
+ end
78
+
79
+ def register_observers_to_notify(event, observers, context)
80
+ entries = (__observers_to_notify[event] ||= [])
81
+
82
+ observers.each do |observer|
83
+ entries << [observer, context] unless entries.any? { |existing, _| existing == observer }
84
+ end
85
+ end
86
+
87
+ def install_observers_to_notify_callback(event, callback_options)
88
+ installed = __observers_to_notify_callbacks
89
+
90
+ return if installed[event]
91
+
92
+ installed[event] = true
93
+
94
+ declaring_class = self
95
+
96
+ callback_block = proc do |record|
97
+ declaring_class.send(:notify_registered_observers, record, event)
98
+ end
99
+
100
+ if callback_options.empty?
101
+ self.public_send(event, &callback_block)
102
+ else
103
+ self.public_send(event, **callback_options, &callback_block)
104
+ end
105
+ end
106
+
107
+ def notify_registered_observers(record, event)
108
+ entries = __observers_to_notify[event]
109
+
110
+ return if entries.nil? || entries.empty?
111
+
112
+ set = record.observers
113
+
114
+ entries.each do |observer, context|
115
+ context ? set.attach(observer, context: context) : set.attach(observer)
116
+ end
117
+
118
+ set.subject_changed!
119
+ set.send(:broadcast_if_subject_changed, [event])
120
+ end
121
+
122
+ def __observers_to_notify
123
+ @__observers_to_notify ||= {}
124
+ end
125
+
126
+ def __observers_to_notify_callbacks
127
+ @__observers_to_notify_callbacks ||= {}
128
+ end
129
+
130
+ private_constant :NO_OBSERVERS_TO_NOTIFY_MSG, :NO_EVENT_TO_NOTIFY_MSG
25
131
  end
26
132
 
27
133
  def self.included(base)
28
134
  base.extend(ClassMethods)
29
- base.send(:private_class_method, :notify_observers!)
135
+ base.send(
136
+ :private_class_method,
137
+ :notify_observers_proc,
138
+ :register_observers_to_notify,
139
+ :install_observers_to_notify_callback,
140
+ :notify_registered_observers,
141
+ :__observers_to_notify,
142
+ :__observers_to_notify_callbacks
143
+ )
30
144
  base.send(:include, ::Micro::Observers)
31
145
  end
32
146
  end
@@ -1,5 +1,5 @@
1
1
  module Micro
2
2
  module Observers
3
- VERSION = '2.3.0'
3
+ VERSION = '3.0.0'
4
4
  end
5
5
  end
data/u-observers.gemspec CHANGED
@@ -8,12 +8,13 @@ Gem::Specification.new do |spec|
8
8
 
9
9
  spec.summary = %q{Simple and powerful implementation of the observer pattern.}
10
10
  spec.description = %q{Simple and powerful implementation of the observer pattern.}
11
- spec.homepage = 'https://github.com/serradura/u-observers'
11
+ spec.homepage = 'https://github.com/u-gems/u-observers'
12
12
  spec.license = 'MIT'
13
13
 
14
14
  spec.metadata['homepage_uri'] = spec.homepage
15
- spec.metadata['source_code_uri'] = 'https://github.com/serradura/u-observers'
16
- spec.metadata['changelog_uri'] = 'https://github.com/serradura/u-observers/releases'
15
+ spec.metadata['source_code_uri'] = 'https://github.com/u-gems/u-observers'
16
+ spec.metadata['changelog_uri'] = 'https://github.com/u-gems/u-observers/blob/main/CHANGELOG.md'
17
+ spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
17
18
 
18
19
  # Specify which files should be added to the gem when it is released.
19
20
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -24,8 +25,9 @@ Gem::Specification.new do |spec|
24
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
26
  spec.require_paths = ['lib']
26
27
 
27
- spec.required_ruby_version = Gem::Requirement.new('>= 2.2.0')
28
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
28
29
 
30
+ spec.add_development_dependency 'appraisal', '~> 2.5'
29
31
  spec.add_development_dependency 'bundler'
30
32
  spec.add_development_dependency 'rake', '~> 13.0'
31
33
  end
metadata CHANGED
@@ -1,15 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-observers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2020-11-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: appraisal
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.5'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.5'
13
26
  - !ruby/object:Gem::Dependency
14
27
  name: bundler
15
28
  requirement: !ruby/object:Gem::Requirement
@@ -45,10 +58,12 @@ executables: []
45
58
  extensions: []
46
59
  extra_rdoc_files: []
47
60
  files:
61
+ - ".github/workflows/ci.yml"
48
62
  - ".gitignore"
49
63
  - ".tool-versions"
50
- - ".travis.sh"
51
- - ".travis.yml"
64
+ - Appraisals
65
+ - CHANGELOG.md
66
+ - CLAUDE.md
52
67
  - CODE_OF_CONDUCT.md
53
68
  - Gemfile
54
69
  - LICENSE.txt
@@ -56,6 +71,7 @@ files:
56
71
  - README.pt-BR.md
57
72
  - Rakefile
58
73
  - bin/console
74
+ - bin/matrix
59
75
  - bin/setup
60
76
  - lib/micro/observers.rb
61
77
  - lib/micro/observers/broadcast.rb
@@ -70,16 +86,15 @@ files:
70
86
  - lib/u-observers.rb
71
87
  - lib/u-observers/for/active_model.rb
72
88
  - lib/u-observers/for/active_record.rb
73
- - test.sh
74
89
  - u-observers.gemspec
75
- homepage: https://github.com/serradura/u-observers
90
+ homepage: https://github.com/u-gems/u-observers
76
91
  licenses:
77
92
  - MIT
78
93
  metadata:
79
- homepage_uri: https://github.com/serradura/u-observers
80
- source_code_uri: https://github.com/serradura/u-observers
81
- changelog_uri: https://github.com/serradura/u-observers/releases
82
- post_install_message:
94
+ homepage_uri: https://github.com/u-gems/u-observers
95
+ source_code_uri: https://github.com/u-gems/u-observers
96
+ changelog_uri: https://github.com/u-gems/u-observers/blob/main/CHANGELOG.md
97
+ bug_tracker_uri: https://github.com/u-gems/u-observers/issues
83
98
  rdoc_options: []
84
99
  require_paths:
85
100
  - lib
@@ -87,15 +102,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
102
  requirements:
88
103
  - - ">="
89
104
  - !ruby/object:Gem::Version
90
- version: 2.2.0
105
+ version: 2.7.0
91
106
  required_rubygems_version: !ruby/object:Gem::Requirement
92
107
  requirements:
93
108
  - - ">="
94
109
  - !ruby/object:Gem::Version
95
110
  version: '0'
96
111
  requirements: []
97
- rubygems_version: 3.0.6
98
- signing_key:
112
+ rubygems_version: 4.0.12
99
113
  specification_version: 4
100
114
  summary: Simple and powerful implementation of the observer pattern.
101
115
  test_files: []
data/.travis.sh DELETED
@@ -1,34 +0,0 @@
1
- #!/bin/bash
2
-
3
- ruby_v=$(ruby -v)
4
-
5
- bundle update
6
- bundle exec rake test
7
-
8
- ACTIVERECORD_VERSION='3.2' bundle update
9
- ACTIVERECORD_VERSION='3.2' bundle exec rake test
10
-
11
- ACTIVERECORD_VERSION='4.0' bundle update
12
- ACTIVERECORD_VERSION='4.0' bundle exec rake test
13
-
14
- ACTIVERECORD_VERSION='4.1' bundle update
15
- ACTIVERECORD_VERSION='4.1' bundle exec rake test
16
-
17
- ACTIVERECORD_VERSION='4.2' bundle update
18
- ACTIVERECORD_VERSION='4.2' bundle exec rake test
19
-
20
- ACTIVERECORD_VERSION='5.0' bundle update
21
- ACTIVERECORD_VERSION='5.0' bundle exec rake test
22
-
23
- ACTIVERECORD_VERSION='5.1' bundle update
24
- ACTIVERECORD_VERSION='5.1' bundle exec rake test
25
-
26
- if [[ ! $ruby_v =~ '2.2.0' ]]; then
27
- ACTIVERECORD_VERSION='5.2' bundle update
28
- ACTIVERECORD_VERSION='5.2' bundle exec rake test
29
- fi
30
-
31
- if [[ $ruby_v =~ '2.5.' ]] || [[ $ruby_v =~ '2.6.' ]] || [[ $ruby_v =~ '2.7.' ]]; then
32
- ACTIVERECORD_VERSION='6.0' bundle update
33
- ACTIVERECORD_VERSION='6.0' bundle exec rake test
34
- fi
data/.travis.yml DELETED
@@ -1,30 +0,0 @@
1
- ---
2
- language: ruby
3
-
4
- sudo: false
5
-
6
- rvm:
7
- - 2.2.0
8
- - 2.3.0
9
- - 2.4.0
10
- - 2.5.0
11
- - 2.6.0
12
- - 2.7.0
13
-
14
- cache: bundler
15
-
16
- before_install:
17
- - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
18
- - gem install bundler -v '< 2'
19
-
20
- install: bundle install --jobs=3 --retry=3
21
-
22
- before_script:
23
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
24
- - chmod +x ./cc-test-reporter
25
- - "./cc-test-reporter before-build"
26
-
27
- script: "./.travis.sh"
28
-
29
- after_success:
30
- - "./cc-test-reporter after-build -t simplecov"
data/test.sh DELETED
@@ -1,11 +0,0 @@
1
- #!/bin/bash
2
-
3
- bundle
4
-
5
- rm Gemfile.lock
6
-
7
- source $(dirname $0)/.travis.sh
8
-
9
- rm Gemfile.lock
10
-
11
- bundle