hidden_hooks 1.1.2 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +66 -1
- data/lib/hidden_hooks/at_least_one_hook_required.rb +4 -0
- data/lib/hidden_hooks/sole_hook_exceeded.rb +4 -0
- data/lib/hidden_hooks/version.rb +1 -1
- data/lib/hidden_hooks.rb +38 -10
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0738dd3eb4b4db1b211e7cf2f93837ae8b5e23e47dd1b5108b8590fc8eea870c'
|
4
|
+
data.tar.gz: 4c208ee06f8e57a049daaf990727ccd9d6cba79c422ec2efa3ec7340443d08b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 107ba5f389928174c5fbd28a402224b639c45ba52f9bec7e619cbba5c61c78a8088d55c4430bac076abd68383c932b225b1891b7f3f8774806eebef58ec5bc9b
|
7
|
+
data.tar.gz: 443fe108faca6c89796b5dcb5772ffad28e87c9c457b8f109b8077f3cf3a73911063059703e26401b037d1d15b3f03c6bfae253b3103b8f39a1e8e79b29f23f5
|
data/CHANGELOG.md
CHANGED
@@ -8,6 +8,19 @@
|
|
8
8
|
### Bug fixes
|
9
9
|
)-->
|
10
10
|
|
11
|
+
## 1.3.0 2025-03-03
|
12
|
+
|
13
|
+
### New features
|
14
|
+
|
15
|
+
- Added `sole` and `present` keyword parameter for hook invocation.
|
16
|
+
- Made hook invocation return the result values.
|
17
|
+
|
18
|
+
## 1.2.0 2025-02-04
|
19
|
+
|
20
|
+
### New features
|
21
|
+
|
22
|
+
- Added the `context` keyword parameter for hooks.
|
23
|
+
|
11
24
|
## 1.1.2 2025-01-28
|
12
25
|
|
13
26
|
### Bug fixes
|
data/README.md
CHANGED
@@ -120,12 +120,77 @@ end
|
|
120
120
|
|
121
121
|
#### Interface Declaration
|
122
122
|
|
123
|
-
A class `C` declares the interface through `HiddenHooks[C]`. Calling a method on the returned proxy will call every hook that someone else defined, forwarding any argument.
|
123
|
+
A class `C` declares the interface through `HiddenHooks[C]`. Calling a method on the returned proxy will call every hook that someone else defined, forwarding any argument.
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
class User
|
127
|
+
def confirm!
|
128
|
+
HiddenHooks[User].before_confirmation self
|
129
|
+
@confirmed = true
|
130
|
+
HiddenHooks[User].after_confirmation self
|
131
|
+
end
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
The results are returned as an array:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
def valid_password? password
|
139
|
+
HiddenHooks[User].valid_password?(self, password).all?
|
140
|
+
end
|
141
|
+
```
|
142
|
+
|
143
|
+
You can enforce that at least one hook be present passing `present: true` to `HiddenHooks.[]`:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
HiddenHooks[User, present: true].valid_password?(self, password).all?
|
147
|
+
# => There must be at least one hook `valid_password?` defined for class `User` (HiddenHooks::AtLeastOneHookRequired)
|
148
|
+
```
|
149
|
+
|
150
|
+
You can also enforce that no more than one hook be present passing `sole: true`:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
HiddenHooks[User, sole: true].valid_password?(self, password).all?
|
154
|
+
# => There must be at most one hook `valid_password?` defined for class `User` (HiddenHooks::SoleHookExceeded)
|
155
|
+
```
|
156
|
+
|
157
|
+
`sole:` defaults to `false`, and `present` defaults to whatever value `sole` has, so by default nothing is checked, and if you pass `sole: true` both checks are performed.
|
158
|
+
|
159
|
+
If both `sole:` and `present:` are true, then we can be certain that there is one and only one hook, so the single result value is unwrapped:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
HiddenHooks[URI].signature_code(uri)
|
163
|
+
# => ["1234"]
|
164
|
+
HiddenHooks[URI, sole: true].signature_code(uri)
|
165
|
+
# => "1234"
|
166
|
+
```
|
124
167
|
|
125
168
|
#### Hook Definition
|
126
169
|
|
127
170
|
Whenever you want to define a hook, you simply call `HiddenHooks.hook_up`. Inside the block, you can call any method and pass it a class and a block: the block will become a hook for that class.
|
128
171
|
|
172
|
+
```ruby
|
173
|
+
class Admin
|
174
|
+
HiddenHooks.hook_up do
|
175
|
+
before_confirmation User do |user|
|
176
|
+
Admin.first.notify! "#{user.name} is being confirmed."
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
```
|
181
|
+
|
182
|
+
You can provide a callable `context`, which will be invoked with the same parameters as the hook. Its result will be bound to `self` inside the hook.
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
class Admin
|
186
|
+
HiddenHooks.hook_up do
|
187
|
+
before_confirmation User, context: proc { Admin.first } do |user|
|
188
|
+
notify! "#{user.name} is being confirmed."
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
129
194
|
#### Rails Callbacks
|
130
195
|
|
131
196
|
Thanks to the [callback objects](https://guides.rubyonrails.org/active_record_callbacks.html#callback-objects) system, in Rails you can simply pass the proxy to the callback methods:
|
data/lib/hidden_hooks/version.rb
CHANGED
data/lib/hidden_hooks.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require_relative 'hidden_hooks/version'
|
2
2
|
|
3
|
+
require_relative 'hidden_hooks/at_least_one_hook_required'
|
4
|
+
require_relative 'hidden_hooks/sole_hook_exceeded'
|
5
|
+
|
3
6
|
require 'active_support/core_ext/module/attribute_accessors'
|
4
7
|
|
5
8
|
module HiddenHooks
|
@@ -9,10 +12,18 @@ module HiddenHooks
|
|
9
12
|
instance_reader: false
|
10
13
|
|
11
14
|
class SetUpProxy
|
12
|
-
|
15
|
+
private
|
13
16
|
|
14
|
-
def method_missing hook, klass, &block
|
15
|
-
::HiddenHooks.hooks[klass][hook] <<
|
17
|
+
def method_missing hook, klass=nil, context: nil, &block
|
18
|
+
::HiddenHooks.hooks[klass][hook] << if context.nil?
|
19
|
+
block
|
20
|
+
else
|
21
|
+
proc do |*args, **kwargs, &hook_block|
|
22
|
+
context
|
23
|
+
.call(*args, **kwargs, &hook_block)
|
24
|
+
.instance_exec(*args, hook_block, **kwargs, &block)
|
25
|
+
end
|
26
|
+
end
|
16
27
|
end
|
17
28
|
|
18
29
|
def respond_to_missing? _, _=false
|
@@ -21,14 +32,31 @@ module HiddenHooks
|
|
21
32
|
end
|
22
33
|
|
23
34
|
class LookUpProxy
|
24
|
-
def initialize klass
|
35
|
+
def initialize klass=nil, sole: false, present: sole
|
36
|
+
@klass = klass
|
25
37
|
@hooks = ::HiddenHooks.hooks[klass]
|
38
|
+
@sole = sole
|
39
|
+
@present = present
|
26
40
|
end
|
27
41
|
|
28
|
-
|
42
|
+
private
|
43
|
+
|
44
|
+
def method_missing(hook_name, *args, **kwargs, &block)
|
45
|
+
hooks = @hooks[hook_name]
|
46
|
+
|
47
|
+
if @present && hooks.empty?
|
48
|
+
raise HiddenHooks::AtLeastOneHookRequired,
|
49
|
+
"There must be at least one hook `#{hook_name}` defined for class `#{@klass}`"
|
50
|
+
end
|
51
|
+
|
52
|
+
if @sole && hooks.size > 1
|
53
|
+
raise HiddenHooks::SoleHookExceeded,
|
54
|
+
"There must be at most one hook `#{hook_name}` defined for class `#{@klass}`"
|
55
|
+
end
|
29
56
|
|
30
|
-
|
31
|
-
|
57
|
+
hooks
|
58
|
+
.map { |hook| hook.call(*args, **kwargs, &block) }
|
59
|
+
.then { |results| (@sole && @present) ? results.first : results }
|
32
60
|
end
|
33
61
|
|
34
62
|
def respond_to_missing? _, _=false
|
@@ -36,12 +64,12 @@ module HiddenHooks
|
|
36
64
|
end
|
37
65
|
end
|
38
66
|
|
39
|
-
def self.hook_up
|
67
|
+
def self.hook_up &block
|
40
68
|
SetUpProxy.new.instance_exec(&block)
|
41
69
|
end
|
42
70
|
|
43
|
-
def self.[]
|
44
|
-
LookUpProxy.new
|
71
|
+
def self.[](...)
|
72
|
+
LookUpProxy.new(...)
|
45
73
|
end
|
46
74
|
end
|
47
75
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hidden_hooks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Moku S.r.l.
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-
|
12
|
+
date: 2025-03-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -42,6 +42,8 @@ files:
|
|
42
42
|
- hidden_hooks.gemspec
|
43
43
|
- lib/hidden_hooks.rb
|
44
44
|
- lib/hidden_hooks/active_record.rb
|
45
|
+
- lib/hidden_hooks/at_least_one_hook_required.rb
|
46
|
+
- lib/hidden_hooks/sole_hook_exceeded.rb
|
45
47
|
- lib/hidden_hooks/version.rb
|
46
48
|
homepage: https://github.com/moku-io/hidden_hooks
|
47
49
|
licenses:
|