u-observers 2.2.1 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +66 -0
- data/.gitignore +8 -0
- data/.tool-versions +1 -1
- data/Appraisals +92 -0
- data/CHANGELOG.md +169 -0
- data/CLAUDE.md +157 -0
- data/Gemfile +6 -32
- data/README.md +190 -40
- data/README.pt-BR.md +193 -42
- data/Rakefile +31 -1
- data/bin/matrix +16 -0
- data/bin/setup +4 -0
- data/lib/micro/observers/for/active_model.rb +118 -4
- data/lib/micro/observers/set.rb +12 -5
- data/lib/micro/observers/version.rb +1 -1
- data/u-observers.gemspec +6 -4
- metadata +28 -14
- data/.travis.sh +0 -34
- data/.travis.yml +0 -30
- data/test.sh +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 96024c50cb6b93ecb1558bdf3dd744617e62cc933887403c3e16e0ab5577077d
|
|
4
|
+
data.tar.gz: e6f90d85540ad09adc8af2c75b2fe927cb1f31ef0fc83d5bc8accfdec446b28e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c1237a6cf905e1044a9d0937018acde2d1b4c21a1695b54f8477d78652375e9c20b44d4f10f16ff0f852fd35e9bc2402f4263c6c45a207f6782c6376faba3e5c
|
|
7
|
+
data.tar.gz: c259528bf1763741618018f255bb0572b89cb0cab6a3115b4dac71bfd7988179dc106c72ed08573c94fe5440b98d679a11fb23402ac6f7998d99e455a9fa6fb3
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Ruby
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
pull_request:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
name: Ruby ${{ matrix.ruby }}
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
ruby: ["2.7", "3.0", "3.1", "3.2", "3.3", "3.4", "4.0", head]
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
persist-credentials: false
|
|
24
|
+
- name: Set up Ruby
|
|
25
|
+
uses: ruby/setup-ruby@v1
|
|
26
|
+
with:
|
|
27
|
+
ruby-version: ${{ matrix.ruby }}
|
|
28
|
+
- name: Install bundler
|
|
29
|
+
run: gem install bundler -v 2.4.22
|
|
30
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' }}
|
|
31
|
+
- name: Bundle install
|
|
32
|
+
run: bundle install
|
|
33
|
+
- name: Setup project
|
|
34
|
+
run: bundle exec appraisal install
|
|
35
|
+
- name: Run baseline tests (no activerecord)
|
|
36
|
+
run: bundle exec rake test
|
|
37
|
+
- name: Run tests for Rails 6.0
|
|
38
|
+
run: bundle exec appraisal rails-6-0 rake test
|
|
39
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' }}
|
|
40
|
+
- name: Run tests for Rails 6.1
|
|
41
|
+
run: bundle exec appraisal rails-6-1 rake test
|
|
42
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' }}
|
|
43
|
+
- name: Run tests for Rails 7.0
|
|
44
|
+
run: bundle exec appraisal rails-7-0 rake test
|
|
45
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' || matrix.ruby == '3.1' || matrix.ruby == '3.2' || matrix.ruby == '3.3' }}
|
|
46
|
+
- name: Run tests for Rails 7.1
|
|
47
|
+
run: bundle exec appraisal rails-7-1 rake test
|
|
48
|
+
if: ${{ matrix.ruby == '2.7' || matrix.ruby == '3.0' || matrix.ruby == '3.1' || matrix.ruby == '3.2' || matrix.ruby == '3.3' }}
|
|
49
|
+
- name: Run tests for Rails 7.2
|
|
50
|
+
run: bundle exec appraisal rails-7-2 rake test
|
|
51
|
+
if: ${{ matrix.ruby == '3.1' || matrix.ruby == '3.2' || matrix.ruby == '3.3' || matrix.ruby == '3.4' }}
|
|
52
|
+
- name: Run tests for Rails 8.0
|
|
53
|
+
run: bundle exec appraisal rails-8-0 rake test
|
|
54
|
+
if: ${{ matrix.ruby == '3.2' || matrix.ruby == '3.3' || matrix.ruby == '3.4' }}
|
|
55
|
+
- name: Run tests for Rails 8.1
|
|
56
|
+
run: bundle exec appraisal rails-8-1 rake test
|
|
57
|
+
if: ${{ matrix.ruby == '3.3' || matrix.ruby == '3.4' || matrix.ruby == '4.0' }}
|
|
58
|
+
- name: Run tests for Rails edge
|
|
59
|
+
run: bundle exec appraisal rails-edge rake test
|
|
60
|
+
if: ${{ matrix.ruby == '4.0' || matrix.ruby == 'head' }}
|
|
61
|
+
- name: Upload coverage to Qlty
|
|
62
|
+
uses: qltysh/qlty-action/coverage@v2
|
|
63
|
+
if: ${{ matrix.ruby == '3.4' && !github.base_ref }}
|
|
64
|
+
with:
|
|
65
|
+
token: ${{ secrets.QLTY_COVERAGE_TOKEN }}
|
|
66
|
+
files: coverage/.resultset.json
|
data/.gitignore
CHANGED
data/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby 2.
|
|
1
|
+
ruby 4.0.1 3.2.11 3.1.7 3.0.7 2.7.8
|
data/Appraisals
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
if RUBY_VERSION < "3.1"
|
|
2
|
+
appraise "rails-6-0" do
|
|
3
|
+
group :test do
|
|
4
|
+
gem "logger", "~> 1.6", ">= 1.6.6"
|
|
5
|
+
gem "stringio", "~> 3.2"
|
|
6
|
+
|
|
7
|
+
gem "minitest", "5.26.1"
|
|
8
|
+
gem "sqlite3", "~> 1.4"
|
|
9
|
+
gem "activerecord", "~> 6.0.0"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
appraise "rails-6-1" do
|
|
14
|
+
group :test do
|
|
15
|
+
gem "logger", "~> 1.6", ">= 1.6.6"
|
|
16
|
+
gem "stringio", "~> 3.2"
|
|
17
|
+
|
|
18
|
+
gem "minitest", "5.26.1"
|
|
19
|
+
gem "sqlite3", "~> 1.4"
|
|
20
|
+
gem "activerecord", "~> 6.1.0"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if RUBY_VERSION >= "2.7" && RUBY_VERSION < "3.4"
|
|
26
|
+
appraise "rails-7-0" do
|
|
27
|
+
group :test do
|
|
28
|
+
gem "logger", "~> 1.6", ">= 1.6.6"
|
|
29
|
+
gem "stringio", "~> 3.2"
|
|
30
|
+
gem "securerandom", "~> 0.3.2"
|
|
31
|
+
|
|
32
|
+
gem "minitest", "5.26.1"
|
|
33
|
+
gem "sqlite3", "~> 1.4"
|
|
34
|
+
gem "activerecord", "~> 7.0.0"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
appraise "rails-7-1" do
|
|
39
|
+
group :test do
|
|
40
|
+
gem "logger", "~> 1.6", ">= 1.6.6"
|
|
41
|
+
gem "stringio", "~> 3.2"
|
|
42
|
+
gem "securerandom", "~> 0.3.2"
|
|
43
|
+
|
|
44
|
+
gem "minitest", "5.26.1"
|
|
45
|
+
gem "sqlite3", "~> 1.4"
|
|
46
|
+
gem "activerecord", "~> 7.1.0"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if RUBY_VERSION >= "3.1" && RUBY_VERSION < "4.0"
|
|
52
|
+
appraise "rails-7-2" do
|
|
53
|
+
group :test do
|
|
54
|
+
gem "minitest", "~> 5.27"
|
|
55
|
+
gem "sqlite3", "~> 1.4"
|
|
56
|
+
gem "activerecord", "~> 7.2.0"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if RUBY_VERSION >= "3.2" && RUBY_VERSION < "4.0"
|
|
62
|
+
appraise "rails-8-0" do
|
|
63
|
+
group :test do
|
|
64
|
+
gem "ostruct", "~> 0.6.3"
|
|
65
|
+
gem "minitest", "~> 5.27"
|
|
66
|
+
gem "sqlite3", "~> 2.1"
|
|
67
|
+
gem "activerecord", "~> 8.0.0"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if RUBY_VERSION >= "3.3.0"
|
|
73
|
+
minitest_version = (RUBY_VERSION >= "4.0.0") ? "~> 6.0" : "~> 5.27"
|
|
74
|
+
|
|
75
|
+
appraise "rails-8-1" do
|
|
76
|
+
group :test do
|
|
77
|
+
gem "ostruct", "~> 0.6.3"
|
|
78
|
+
gem "minitest", minitest_version
|
|
79
|
+
gem "sqlite3", "~> 2.1"
|
|
80
|
+
gem "activerecord", "~> 8.1.0"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
appraise "rails-edge" do
|
|
85
|
+
group :test do
|
|
86
|
+
gem "ostruct", "~> 0.6.3"
|
|
87
|
+
gem "minitest", minitest_version
|
|
88
|
+
gem "sqlite3", "~> 2.1"
|
|
89
|
+
gem "activerecord", github: "rails/rails", branch: "main"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
Per the project's stability policy, a major version bump signals only that a
|
|
9
|
+
Ruby or Rails version was dropped from the supported matrix — a dependency-floor
|
|
10
|
+
change, not a behavior break.
|
|
11
|
+
|
|
12
|
+
## [Unreleased]
|
|
13
|
+
|
|
14
|
+
## [3.0.0] - 2026-06-01
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `notify_observers!` — declare observers on an `ActiveModel`/`ActiveRecord`
|
|
19
|
+
model **at the class level**, so they no longer need to be attached on every
|
|
20
|
+
instance. Takes `event:` (the callback to hook, also the broadcast event
|
|
21
|
+
name), `with:` (the observer(s) to attach), an optional `context:` forwarded
|
|
22
|
+
to those observers, and any extra option (e.g. `on:`) passed straight through
|
|
23
|
+
to the underlying callback.
|
|
24
|
+
- `observers_to_notify` — introspect the observers declared via
|
|
25
|
+
`notify_observers!`, keyed by callback.
|
|
26
|
+
- `detach_observers_to_notify(*observers, from: nil)` — remove declared
|
|
27
|
+
observers from a callback (or from all of them); with no observers it clears
|
|
28
|
+
the callback entirely.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Raised the supported floor to **Ruby >= 2.7** (was `>= 2.2`) and
|
|
33
|
+
**ActiveRecord/Rails >= 6.0** (was `>= 3.2`).
|
|
34
|
+
- Modernized CI/test setup: the suite now runs on Ruby 2.7 through 4.0 + head
|
|
35
|
+
against Rails 6.0 through 8.1 + edge via [Appraisal](https://github.com/thoughtbot/appraisal),
|
|
36
|
+
with a no-`activerecord` baseline run.
|
|
37
|
+
|
|
38
|
+
## [2.3.0] - 2020-11-25
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- Allow defining observers using blocks (e.g. `after_commit(¬ify_observers(:event))`).
|
|
43
|
+
|
|
44
|
+
## [2.2.1] - 2020-11-18
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- `observers.once()` when its callable returns `nil`.
|
|
49
|
+
|
|
50
|
+
## [2.2.0] - 2020-11-18
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
|
|
54
|
+
- `Observers::Set#once` and `Observers::Set#off`.
|
|
55
|
+
- Allow defining multiple callables for the same event.
|
|
56
|
+
- `Observers::Set#include?` (with `included?` kept as an alias).
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- Observer deletion when it must be performed only once.
|
|
61
|
+
- `Observers::Set#inspect`.
|
|
62
|
+
|
|
63
|
+
## [2.1.0] - 2020-10-16
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
|
|
67
|
+
- Allow defining callable observers with a context.
|
|
68
|
+
- Portuguese documentation ([`README.pt-BR.md`](https://github.com/u-gems/u-observers/blob/main/README.pt-BR.md)).
|
|
69
|
+
|
|
70
|
+
## [2.0.0] - 2020-10-06
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
|
|
74
|
+
- `Micro::Observers::Event` to represent the notification payload.
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
- Renamed `Micro::Observers::Manager` to `Micro::Observers::Set`.
|
|
79
|
+
- Transformed `Micro::Observers::Events` into `Micro::Observers::Event::Names`.
|
|
80
|
+
- `subject_changed` methods now return booleans.
|
|
81
|
+
|
|
82
|
+
## [1.0.0] - 2020-10-05
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
|
|
86
|
+
- `Micro::Observers::For::ActiveModel` and `Micro::Observers::For::ActiveRecord`
|
|
87
|
+
integrations (`notify_observers_on`, `notify_observers`).
|
|
88
|
+
- `call!` and `notify!` to broadcast even when the subject hasn't been changed.
|
|
89
|
+
- `Micro::Observers::Manager#inspect`.
|
|
90
|
+
|
|
91
|
+
## [0.9.0] - 2020-09-29
|
|
92
|
+
|
|
93
|
+
### Added
|
|
94
|
+
|
|
95
|
+
- CI running against multiple Ruby and ActiveRecord versions.
|
|
96
|
+
|
|
97
|
+
### Changed
|
|
98
|
+
|
|
99
|
+
- Added `subject_changed` to ensure idempotency of notifications.
|
|
100
|
+
|
|
101
|
+
### Removed
|
|
102
|
+
|
|
103
|
+
- The concept of "actions".
|
|
104
|
+
|
|
105
|
+
## [0.8.0] - 2020-09-28
|
|
106
|
+
|
|
107
|
+
### Changed
|
|
108
|
+
|
|
109
|
+
- Resolve a callable observer's argument only when the observer is executed.
|
|
110
|
+
|
|
111
|
+
## [0.7.0] - 2020-09-26
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
- Attach and detach multiple observers at once.
|
|
116
|
+
|
|
117
|
+
## [0.6.0] - 2020-09-26
|
|
118
|
+
|
|
119
|
+
### Changed
|
|
120
|
+
|
|
121
|
+
- Optimized `Micro::Observers::Manager#notify` and `#call`.
|
|
122
|
+
|
|
123
|
+
## [0.5.0] - 2020-09-26
|
|
124
|
+
|
|
125
|
+
### Changed
|
|
126
|
+
|
|
127
|
+
- Normalized the class and instance methods.
|
|
128
|
+
|
|
129
|
+
## [0.4.0] - 2020-09-25
|
|
130
|
+
|
|
131
|
+
### Added
|
|
132
|
+
|
|
133
|
+
- Notify events and call actions.
|
|
134
|
+
|
|
135
|
+
## [0.3.0] - 2020-09-25
|
|
136
|
+
|
|
137
|
+
### Added
|
|
138
|
+
|
|
139
|
+
- `Micro::Observers#on`.
|
|
140
|
+
|
|
141
|
+
## [0.2.0] - 2020-09-25
|
|
142
|
+
|
|
143
|
+
### Changed
|
|
144
|
+
|
|
145
|
+
- `Micro::Observers::Manager` receives the subject through its constructor.
|
|
146
|
+
|
|
147
|
+
## [0.1.0] - 2020-09-25
|
|
148
|
+
|
|
149
|
+
### Added
|
|
150
|
+
|
|
151
|
+
- Initial release — the `Micro::Observers` implementation of the observer pattern.
|
|
152
|
+
|
|
153
|
+
[Unreleased]: https://github.com/u-gems/u-observers/compare/v3.0.0...HEAD
|
|
154
|
+
[3.0.0]: https://github.com/u-gems/u-observers/compare/v2.3.0...v3.0.0
|
|
155
|
+
[2.3.0]: https://github.com/u-gems/u-observers/compare/v2.2.1...v2.3.0
|
|
156
|
+
[2.2.1]: https://github.com/u-gems/u-observers/compare/v2.2.0...v2.2.1
|
|
157
|
+
[2.2.0]: https://github.com/u-gems/u-observers/compare/v2.1.0...v2.2.0
|
|
158
|
+
[2.1.0]: https://github.com/u-gems/u-observers/compare/v2.0.0...v2.1.0
|
|
159
|
+
[2.0.0]: https://github.com/u-gems/u-observers/compare/v1.0.0...v2.0.0
|
|
160
|
+
[1.0.0]: https://github.com/u-gems/u-observers/compare/v0.9.0...v1.0.0
|
|
161
|
+
[0.9.0]: https://github.com/u-gems/u-observers/compare/v0.8.0...v0.9.0
|
|
162
|
+
[0.8.0]: https://github.com/u-gems/u-observers/compare/v0.7.0...v0.8.0
|
|
163
|
+
[0.7.0]: https://github.com/u-gems/u-observers/compare/v0.6.0...v0.7.0
|
|
164
|
+
[0.6.0]: https://github.com/u-gems/u-observers/compare/v0.5.0...v0.6.0
|
|
165
|
+
[0.5.0]: https://github.com/u-gems/u-observers/compare/v0.4.0...v0.5.0
|
|
166
|
+
[0.4.0]: https://github.com/u-gems/u-observers/compare/v0.3.0...v0.4.0
|
|
167
|
+
[0.3.0]: https://github.com/u-gems/u-observers/compare/v0.2.0...v0.3.0
|
|
168
|
+
[0.2.0]: https://github.com/u-gems/u-observers/compare/v0.1.0...v0.2.0
|
|
169
|
+
[0.1.0]: https://github.com/u-gems/u-observers/releases/tag/v0.1.0
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Notes for AI assistants working in `u-observers`.
|
|
4
|
+
|
|
5
|
+
## Golden rule: no breaking API changes — ever
|
|
6
|
+
|
|
7
|
+
`u-observers` is a dependency-free gem that many projects rely on, directly or
|
|
8
|
+
transitively. **Its public API and runtime contracts won't break.** Every
|
|
9
|
+
change must keep existing code working.
|
|
10
|
+
|
|
11
|
+
Unlike `u-attributes`, this is *not* because it's a runtime dependency of
|
|
12
|
+
`u-case` (it isn't — `u-case` depends on `kind` and `u-attributes`). The
|
|
13
|
+
commitment stands on its own: the gem's role is to remain a stable,
|
|
14
|
+
backward-compatible foundation for everything that depends on it.
|
|
15
|
+
|
|
16
|
+
Major version bumps are reserved for dependency-floor changes (dropping a Ruby
|
|
17
|
+
or Rails version from the supported matrix) per SemVer. They do **not** signal
|
|
18
|
+
a behavior break.
|
|
19
|
+
|
|
20
|
+
If a task as stated would require a breaking change to honor it, stop and
|
|
21
|
+
surface that — propose a backward-compatible path, or flag that the request
|
|
22
|
+
can't be satisfied without violating this rule. Don't ship the break.
|
|
23
|
+
|
|
24
|
+
## How to work in this repo
|
|
25
|
+
|
|
26
|
+
### 1. Think before coding
|
|
27
|
+
|
|
28
|
+
**Don't assume. Don't hide confusion. Surface tradeoffs.**
|
|
29
|
+
|
|
30
|
+
- State assumptions explicitly. If uncertain, ask.
|
|
31
|
+
- If multiple interpretations exist, present them — don't pick silently.
|
|
32
|
+
- If a simpler approach exists, say so. Push back when warranted.
|
|
33
|
+
- If something is unclear, stop. Name what's confusing. Ask.
|
|
34
|
+
|
|
35
|
+
### 2. Simplicity first
|
|
36
|
+
|
|
37
|
+
**Minimum code that solves the problem. Nothing speculative.**
|
|
38
|
+
|
|
39
|
+
- No features beyond what was asked.
|
|
40
|
+
- No abstractions for single-use code.
|
|
41
|
+
- No "flexibility" or "configurability" that wasn't requested.
|
|
42
|
+
- No error handling for impossible scenarios.
|
|
43
|
+
- If you write 200 lines and it could be 50, rewrite it.
|
|
44
|
+
|
|
45
|
+
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes,
|
|
46
|
+
simplify.
|
|
47
|
+
|
|
48
|
+
### 3. Surgical changes
|
|
49
|
+
|
|
50
|
+
**Touch only what you must. Clean up only your own mess.**
|
|
51
|
+
|
|
52
|
+
- Don't "improve" adjacent code, comments, or formatting.
|
|
53
|
+
- Don't refactor things that aren't broken.
|
|
54
|
+
- Match existing style, even if you'd do it differently.
|
|
55
|
+
- If you notice unrelated dead code, mention it — don't delete it.
|
|
56
|
+
- Remove imports/variables/functions that _your_ changes orphaned. Don't
|
|
57
|
+
remove pre-existing dead code unless asked.
|
|
58
|
+
|
|
59
|
+
The test: every changed line should trace directly to the user's request.
|
|
60
|
+
|
|
61
|
+
### 4. Goal-driven execution
|
|
62
|
+
|
|
63
|
+
**Define success criteria. Loop until verified.**
|
|
64
|
+
|
|
65
|
+
Turn vague tasks into verifiable goals:
|
|
66
|
+
|
|
67
|
+
- "Add validation" → "Write tests for invalid inputs, then make them pass"
|
|
68
|
+
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
|
|
69
|
+
- "Refactor X" → "Ensure tests pass before and after"
|
|
70
|
+
|
|
71
|
+
For multi-step work, state a brief plan with a verification check per step.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## What this is
|
|
76
|
+
|
|
77
|
+
`u-observers` is a small, dependency-free implementation of the observer
|
|
78
|
+
pattern, organized under `lib/micro/observers/`. The core (`require
|
|
79
|
+
'u-observers'`) gives any object an `#observers` collection
|
|
80
|
+
(`Micro::Observers::Set`) for attaching/detaching subscribers and notifying
|
|
81
|
+
them of events — built from cohesive pieces: `Set`, `Event` (+ `Event::Names`),
|
|
82
|
+
`Broadcast`, `Subscribers`, and `Utils`. On top of that sit two **optional**
|
|
83
|
+
Rails integrations that are loaded only when explicitly required:
|
|
84
|
+
|
|
85
|
+
- `require 'u-observers/for/active_model'` → `Micro::Observers::For::ActiveModel`
|
|
86
|
+
- `require 'u-observers/for/active_record'` → `Micro::Observers::For::ActiveRecord`
|
|
87
|
+
|
|
88
|
+
ActiveRecord/ActiveModel are **not** runtime dependencies — they're brought in
|
|
89
|
+
only by the host app (and by the test appraisals). The public API is small and
|
|
90
|
+
widely used downstream, so behavior changes — especially anything affecting the
|
|
91
|
+
public API or the supported `ruby` / `activerecord` matrix — are highly visible.
|
|
92
|
+
|
|
93
|
+
## Running tests
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
bundle exec rake test # default suite, current bundle (no activerecord)
|
|
97
|
+
bundle exec appraisal <name> rake test # one Rails appraisal (see Appraisals)
|
|
98
|
+
bundle exec rake matrix # full local matrix for the active Ruby
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`bin/setup` reinstalls and refreshes appraisals; `bin/matrix` reinstalls then
|
|
102
|
+
runs `rake matrix`. CI runs the baseline suite plus the per-Rails appraisals
|
|
103
|
+
across the Ruby × ActiveRecord grid (`.github/workflows/ci.yml`). Tests are the
|
|
104
|
+
success criterion for any behavior change — write or update a test first, then
|
|
105
|
+
make it pass (rule 4).
|
|
106
|
+
|
|
107
|
+
How the suite picks up ActiveRecord (`test/test_helper.rb`):
|
|
108
|
+
|
|
109
|
+
- The baseline `rake test` run has **no** activerecord, so the integration
|
|
110
|
+
tests are skipped. Each Rails appraisal adds `activerecord` + `sqlite3`, which
|
|
111
|
+
flips `ACTIVERECORD_AVAILABLE` on and exercises the `For::ActiveRecord` /
|
|
112
|
+
`For::ActiveModel` tests.
|
|
113
|
+
- `test_helper` must `require 'logger'` **before** `require 'active_record'` —
|
|
114
|
+
ActiveSupport <= 6.1 references `::Logger` at load time and newer
|
|
115
|
+
`concurrent-ruby` no longer requires it first. Don't remove that line; the
|
|
116
|
+
Rails 6.x appraisals fail without it.
|
|
117
|
+
|
|
118
|
+
Running the matrix locally (multiple Rubies via mise, see `.tool-versions`):
|
|
119
|
+
|
|
120
|
+
- Clear `Gemfile.lock` / `gemfiles/*.lock` between Rubies — a stale `BUNDLED
|
|
121
|
+
WITH` from another Ruby breaks resolution.
|
|
122
|
+
- Pin a 2.x bundler per Ruby when needed: bare `bundle` can grab an incompatible
|
|
123
|
+
4.x on Ruby 3.1 (and 2.7/3.0 need bundler `2.4.22`, as CI does).
|
|
124
|
+
|
|
125
|
+
## CHANGELOG and READMEs are part of every change
|
|
126
|
+
|
|
127
|
+
These user-facing files must stay in sync with the code:
|
|
128
|
+
|
|
129
|
+
- **`CHANGELOG.md`**: follows [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/).
|
|
130
|
+
Every user-visible change (new API, behavior change, dep bump that shifts the
|
|
131
|
+
supported matrix, fix, security fix) gets a bullet under the appropriate
|
|
132
|
+
section (`Added` / `Changed` / `Deprecated` / `Removed` / `Fixed` /
|
|
133
|
+
`Security`) in `[Unreleased]`. Pure README/CI/internal-refactor changes
|
|
134
|
+
generally don't need an entry. The gemspec `changelog_uri` points here.
|
|
135
|
+
- **`README.md`** (English) and **`README.pt-BR.md`** (Portuguese) **must stay
|
|
136
|
+
in sync with each other** — any documented-API or compatibility change goes
|
|
137
|
+
into **both** in the same commit. The **Compatibility** table references the
|
|
138
|
+
supported Ruby × ActiveRecord bounds; update it when the matrix moves. If you
|
|
139
|
+
change a documented API, update the relevant Usage section (and its
|
|
140
|
+
table-of-contents entry) in both files.
|
|
141
|
+
|
|
142
|
+
## Bumping the version
|
|
143
|
+
|
|
144
|
+
1. Edit `lib/micro/observers/version.rb` — change `Micro::Observers::VERSION`.
|
|
145
|
+
Follow [SemVer](https://semver.org/): patch for fixes, minor for additive
|
|
146
|
+
user-visible changes, major for breaking changes.
|
|
147
|
+
2. In `CHANGELOG.md`, turn `[Unreleased]` into a new `## [X.Y.Z] - YYYY-MM-DD`
|
|
148
|
+
section and add a matching compare link at the bottom
|
|
149
|
+
(`[X.Y.Z]: …/compare/vPREV...vX.Y.Z`).
|
|
150
|
+
3. Update the **Compatibility** table in `README.md` and `README.pt-BR.md`: if
|
|
151
|
+
supported Ruby / ActiveRecord bounds changed, add a new row; otherwise bump
|
|
152
|
+
the existing row's version label.
|
|
153
|
+
4. If the supported matrix moved, double-check that the Compatibility table, the
|
|
154
|
+
CI matrix (`.github/workflows/ci.yml`), and the `Appraisals` file all reflect
|
|
155
|
+
the new bounds.
|
|
156
|
+
|
|
157
|
+
Don't tag, push, `gem release`, or draft the GitHub Release — humans do that.
|
data/Gemfile
CHANGED
|
@@ -1,40 +1,14 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
4
|
+
|
|
3
5
|
# Specify your gem's dependencies in u-observers.gemspec
|
|
4
6
|
gemspec
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
activerecord = case activerecord_version
|
|
9
|
-
when '3.2' then '3.2.22'
|
|
10
|
-
when '4.0' then '4.0.13'
|
|
11
|
-
when '4.1' then '4.1.16'
|
|
12
|
-
when '4.2' then '4.2.11'
|
|
13
|
-
when '5.0' then '5.0.7'
|
|
14
|
-
when '5.1' then '5.1.7'
|
|
15
|
-
when '5.2' then '5.2.3'
|
|
16
|
-
when '6.0' then '6.0.3'
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
simplecov_version =
|
|
20
|
-
case RUBY_VERSION
|
|
21
|
-
when /\A2.[23]/ then '~> 0.17.1'
|
|
22
|
-
when /\A2.4/ then '~> 0.18.5'
|
|
23
|
-
else '~> 0.19'
|
|
24
|
-
end
|
|
8
|
+
gem 'rake', '~> 13.0'
|
|
25
9
|
|
|
26
10
|
group :test do
|
|
27
|
-
gem 'minitest',
|
|
28
|
-
gem '
|
|
29
|
-
|
|
30
|
-
if activerecord
|
|
31
|
-
sqlite3 =
|
|
32
|
-
case activerecord
|
|
33
|
-
when /\A6\.0/, nil then '~> 1.4.0'
|
|
34
|
-
else '~> 1.3.0'
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
gem 'sqlite3', sqlite3
|
|
38
|
-
gem 'activerecord', activerecord, require: 'active_record'
|
|
39
|
-
end
|
|
11
|
+
gem 'minitest', '~> 5.0'
|
|
12
|
+
gem 'ostruct', '~> 0.6.3' if RUBY_VERSION >= '3.5'
|
|
13
|
+
gem 'simplecov', '~> 0.22.0', require: false
|
|
40
14
|
end
|