esse-hooks 0.0.1.beta1
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 +7 -0
- data/.rubocop.yml +35 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +131 -0
- data/LICENSE.txt +21 -0
- data/README.md +81 -0
- data/Rakefile +4 -0
- data/lib/esse/hooks/mixin.rb +257 -0
- data/lib/esse/hooks/primitives/string.rb +55 -0
- data/lib/esse/hooks/version.rb +7 -0
- data/lib/esse/hooks.rb +62 -0
- data/mise.toml +2 -0
- metadata +73 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b702dd473e90d0f68a109b65f5a561051f7b2778c467eb438d0ef88f09ef9211
|
4
|
+
data.tar.gz: 5387dee13603073cfb9fb30af8cfdf855f09f76902040d512cf6554f0446c7d8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 01d4d906bda088c82b28c011fdb07e0a74b98cd9255564ff7d7058d96218233935d5011ce9267452b13c3e61aa98ed9bd236e5d5ffea2b39973bf758df1b60bc
|
7
|
+
data.tar.gz: 783f2bca4c6ab24e9f667deb2da4086a66fe593a5d35867332eb25f66c946b82b0ce599fea56fe24bb8831e2eb6143ea6b22a74f27582de8768add22e139ce51
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
inherit_mode:
|
2
|
+
merge:
|
3
|
+
- Exclude
|
4
|
+
|
5
|
+
require:
|
6
|
+
- rubocop-performance
|
7
|
+
- rubocop-rspec
|
8
|
+
- standard/cop/block_single_line_braces
|
9
|
+
|
10
|
+
inherit_gem:
|
11
|
+
standard: config/base.yml
|
12
|
+
|
13
|
+
AllCops:
|
14
|
+
TargetRubyVersion: 2.6
|
15
|
+
SuggestExtensions: false
|
16
|
+
Exclude:
|
17
|
+
- "db/**/*"
|
18
|
+
- "tmp/**/*"
|
19
|
+
- "vendor/**/*"
|
20
|
+
NewCops: enable
|
21
|
+
|
22
|
+
RSpec/MultipleExpectations:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
RSpec/ExampleLength:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
RSpec/MultipleMemoizedHelpers:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
RSpec/MessageSpies:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
RSpec/StubbedMock:
|
35
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,9 @@
|
|
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.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## 0.0.1.beta1
|
8
|
+
The first release of the esse-hooks gem.
|
9
|
+
* Added: Initial implementation of the hooks extension.
|
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
6
|
+
|
7
|
+
gem "esse"
|
8
|
+
gem "esse-rspec"
|
9
|
+
gem "pry"
|
10
|
+
gem "dotenv"
|
11
|
+
gem "rubocop"
|
12
|
+
gem "rubocop-performance"
|
13
|
+
gem "rubocop-rspec"
|
14
|
+
gem "standard"
|
15
|
+
gem "elasticsearch", "~> 7.17", ">= 7.17.10"
|
16
|
+
gem "webmock"
|
17
|
+
|
18
|
+
# Specify your gem"s dependencies in esse-hooks.gemspec
|
19
|
+
gemspec
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
esse-hooks (0.0.1.beta1)
|
5
|
+
esse (>= 0.3.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
addressable (2.8.7)
|
11
|
+
public_suffix (>= 2.0.2, < 7.0)
|
12
|
+
ast (2.4.2)
|
13
|
+
base64 (0.2.0)
|
14
|
+
bigdecimal (3.1.9)
|
15
|
+
coderay (1.1.3)
|
16
|
+
crack (1.0.0)
|
17
|
+
bigdecimal
|
18
|
+
rexml
|
19
|
+
diff-lcs (1.5.1)
|
20
|
+
dotenv (2.8.1)
|
21
|
+
elasticsearch (7.17.11)
|
22
|
+
elasticsearch-api (= 7.17.11)
|
23
|
+
elasticsearch-transport (= 7.17.11)
|
24
|
+
elasticsearch-api (7.17.11)
|
25
|
+
multi_json
|
26
|
+
elasticsearch-transport (7.17.11)
|
27
|
+
base64
|
28
|
+
faraday (>= 1, < 3)
|
29
|
+
multi_json
|
30
|
+
esse (0.3.5)
|
31
|
+
multi_json
|
32
|
+
thor (>= 0.19)
|
33
|
+
esse-rspec (0.0.6)
|
34
|
+
esse (>= 0.2.4)
|
35
|
+
rspec (>= 3)
|
36
|
+
faraday (2.8.1)
|
37
|
+
base64
|
38
|
+
faraday-net_http (>= 2.0, < 3.1)
|
39
|
+
ruby2_keywords (>= 0.0.4)
|
40
|
+
faraday-net_http (3.0.2)
|
41
|
+
hashdiff (1.1.0)
|
42
|
+
json (2.9.1)
|
43
|
+
language_server-protocol (3.17.0.3)
|
44
|
+
lint_roller (1.1.0)
|
45
|
+
method_source (1.1.0)
|
46
|
+
multi_json (1.15.0)
|
47
|
+
parallel (1.26.3)
|
48
|
+
parser (3.3.7.0)
|
49
|
+
ast (~> 2.4.1)
|
50
|
+
racc
|
51
|
+
pry (0.15.2)
|
52
|
+
coderay (~> 1.1)
|
53
|
+
method_source (~> 1.0)
|
54
|
+
public_suffix (5.1.1)
|
55
|
+
racc (1.8.1)
|
56
|
+
rainbow (3.1.1)
|
57
|
+
regexp_parser (2.10.0)
|
58
|
+
rexml (3.3.1)
|
59
|
+
strscan
|
60
|
+
rspec (3.13.0)
|
61
|
+
rspec-core (~> 3.13.0)
|
62
|
+
rspec-expectations (~> 3.13.0)
|
63
|
+
rspec-mocks (~> 3.13.0)
|
64
|
+
rspec-core (3.13.2)
|
65
|
+
rspec-support (~> 3.13.0)
|
66
|
+
rspec-expectations (3.13.3)
|
67
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
68
|
+
rspec-support (~> 3.13.0)
|
69
|
+
rspec-mocks (3.13.2)
|
70
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
71
|
+
rspec-support (~> 3.13.0)
|
72
|
+
rspec-support (3.13.2)
|
73
|
+
rubocop (1.70.0)
|
74
|
+
json (~> 2.3)
|
75
|
+
language_server-protocol (>= 3.17.0)
|
76
|
+
parallel (~> 1.10)
|
77
|
+
parser (>= 3.3.0.2)
|
78
|
+
rainbow (>= 2.2.2, < 4.0)
|
79
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
80
|
+
rubocop-ast (>= 1.36.2, < 2.0)
|
81
|
+
ruby-progressbar (~> 1.7)
|
82
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
83
|
+
rubocop-ast (1.37.0)
|
84
|
+
parser (>= 3.3.1.0)
|
85
|
+
rubocop-performance (1.21.1)
|
86
|
+
rubocop (>= 1.48.1, < 2.0)
|
87
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
88
|
+
rubocop-rspec (3.4.0)
|
89
|
+
rubocop (~> 1.61)
|
90
|
+
ruby-progressbar (1.13.0)
|
91
|
+
ruby2_keywords (0.0.5)
|
92
|
+
standard (1.35.0.1)
|
93
|
+
language_server-protocol (~> 3.17.0.2)
|
94
|
+
lint_roller (~> 1.0)
|
95
|
+
rubocop (~> 1.62)
|
96
|
+
standard-custom (~> 1.0.0)
|
97
|
+
standard-performance (~> 1.3)
|
98
|
+
standard-custom (1.0.2)
|
99
|
+
lint_roller (~> 1.0)
|
100
|
+
rubocop (~> 1.50)
|
101
|
+
standard-performance (1.4.0)
|
102
|
+
lint_roller (~> 1.1)
|
103
|
+
rubocop-performance (~> 1.21.0)
|
104
|
+
strscan (3.1.0)
|
105
|
+
thor (1.3.2)
|
106
|
+
unicode-display_width (3.1.4)
|
107
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
108
|
+
unicode-emoji (4.0.4)
|
109
|
+
webmock (3.23.1)
|
110
|
+
addressable (>= 2.8.0)
|
111
|
+
crack (>= 0.3.2)
|
112
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
113
|
+
|
114
|
+
PLATFORMS
|
115
|
+
x86_64-linux
|
116
|
+
|
117
|
+
DEPENDENCIES
|
118
|
+
dotenv
|
119
|
+
elasticsearch (~> 7.17, >= 7.17.10)
|
120
|
+
esse
|
121
|
+
esse-hooks!
|
122
|
+
esse-rspec
|
123
|
+
pry
|
124
|
+
rubocop
|
125
|
+
rubocop-performance
|
126
|
+
rubocop-rspec
|
127
|
+
standard
|
128
|
+
webmock
|
129
|
+
|
130
|
+
BUNDLED WITH
|
131
|
+
2.3.26
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2022 Marcos G. Zimmermann
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Esse Hooks Extension
|
2
|
+
|
3
|
+
This gem is an internal component for the [esse](https://github.com/marcosgz/esse) project. It provides a plugin to add hooks to the [esse-active_record](https://github.com/marcosgz/esse-active_record) and [esse-sequel](https://github.com/marcosgz/esse-sequel) plugins.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'esse-hooks'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install esse-hooks
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Using the `esse-active_record` as example. It adds hooks to the `Esse::ActiveRecord::Hooks` module.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
module Esse::ActiveRecord::Hooks
|
27
|
+
include Esse::Hooks[store_key: :esse_active_record_hooks]
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
and then you can use the hooks to change activeness of the indexing process.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Esse::ActiveRecord::Hooks.disable!
|
35
|
+
Esse::ActiveRecord::Hooks.with_indexing do
|
36
|
+
10.times { User.create! }
|
37
|
+
end
|
38
|
+
|
39
|
+
Esse::ActiveRecord::Hooks.enable!
|
40
|
+
Esse::ActiveRecord::Hooks.without_indexing do
|
41
|
+
10.times { User.create! }
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
or by some specific list of index or index's repository
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
Esse::ActiveRecord::Hooks.disable!(UsersIndex.repo)
|
49
|
+
Esse::ActiveRecord::Hooks.with_indexing(AccountsIndex, UsersIndex.repo) do
|
50
|
+
10.times { User.create! }
|
51
|
+
end
|
52
|
+
Esse::ActiveRecord::Hooks.enable!(UsersIndex.repo)
|
53
|
+
Esse::ActiveRecord::Hooks.without_indexing(AccountsIndex, UsersIndex.repo) do
|
54
|
+
10.times { User.create! }
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
In case you are using both `esse-active_record` and `esse-sequel` plugins, you can use the `Esse::Hooks` module directly to interact with both hooks at the same time.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
Esse::Hooks.disable!
|
62
|
+
Esse::Hooks.with_indexing do
|
63
|
+
10.times { User.create! }
|
64
|
+
end
|
65
|
+
Esse::Hooks.enable!
|
66
|
+
```
|
67
|
+
|
68
|
+
|
69
|
+
## Development
|
70
|
+
|
71
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake none` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
72
|
+
|
73
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
74
|
+
|
75
|
+
## Contributing
|
76
|
+
|
77
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/marcosgz/esse-hooks.
|
78
|
+
|
79
|
+
## License
|
80
|
+
|
81
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Esse::Hooks::Mixin < Module
|
4
|
+
attr_reader :store_key
|
5
|
+
|
6
|
+
def initialize(store_key:)
|
7
|
+
@store_key = store_key
|
8
|
+
end
|
9
|
+
|
10
|
+
def included(base)
|
11
|
+
store_store_key = store_key # closure
|
12
|
+
base.define_singleton_method(:store_key) { store_store_key }
|
13
|
+
base.extend(ClassMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def register_model(model_class)
|
18
|
+
unless model_class.respond_to?(:esse_callbacks)
|
19
|
+
raise ArgumentError, "Model class #{model_class} should have a `esse_callbacks' method"
|
20
|
+
end
|
21
|
+
|
22
|
+
@models ||= []
|
23
|
+
@models |= [model_class]
|
24
|
+
end
|
25
|
+
|
26
|
+
def models
|
27
|
+
@models || []
|
28
|
+
end
|
29
|
+
|
30
|
+
def model_names
|
31
|
+
models.map(&:to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Global enable indexing callbacks. If no repository is specified, all repositories will be enabled.
|
35
|
+
# @param repos [Array<String, Esse::Index, Esse::Repo>]
|
36
|
+
# @return [void]
|
37
|
+
def enable!(*repos)
|
38
|
+
filter_repositories(*repos).each do |repo|
|
39
|
+
state[:repos][repo] = true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Global disable indexing callbacks. If no repository is specified, all repositories will be disabled.
|
44
|
+
# @param repos [Array<String, Esse::Index, Esse::Repo>]
|
45
|
+
# @return [void]
|
46
|
+
def disable!(*repos)
|
47
|
+
filter_repositories(*repos).each do |repo|
|
48
|
+
state[:repos][repo] = false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Check if the given repository is enabled for indexing. If no repository is specified, all repositories will be checked.
|
53
|
+
#
|
54
|
+
# @param repos [Array<String, Esse::Index, Esse::Repo>]
|
55
|
+
# @return [Boolean]
|
56
|
+
def disabled?(*repos)
|
57
|
+
filter_repositories(*repos).all? { |repo| !state[:repos][repo] }
|
58
|
+
end
|
59
|
+
|
60
|
+
# Check if the given repository is enabled for indexing. If no repository is specified, all repositories will be checked.
|
61
|
+
#
|
62
|
+
# @param repos [Array<String, Esse::Index, Esse::Repo>]
|
63
|
+
# @return [Boolean]
|
64
|
+
def enabled?(*repos)
|
65
|
+
filter_repositories(*repos).all? { |repo| state[:repos][repo] }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Enable model indexing callbacks for the given model. If no repository is specified, all repositories will be enabled.
|
69
|
+
#
|
70
|
+
# @param model_class [Class]
|
71
|
+
# @param repos [Array<String, Esse::Index, Esse::Repo>]
|
72
|
+
# @raise [ArgumentError] if model repository is not registered for the given model
|
73
|
+
# @return [void]
|
74
|
+
def enable_model!(model_class, *repos)
|
75
|
+
ensure_registered_model_class!(model_class)
|
76
|
+
filter_model_repositories(model_class, *repos).each do |repo|
|
77
|
+
state[:models][model_class][repo] = true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Disable model indexing callbacks for the given model. If no repository is specified, all repositories will be disabled.
|
82
|
+
#
|
83
|
+
# @param model_class [Class]
|
84
|
+
# @param repos [Array<String, Esse::Index, Esse::Repo>]
|
85
|
+
# @raise [ArgumentError] if model repository is not registered for the given model
|
86
|
+
# @return [void]
|
87
|
+
def disable_model!(model_class, *repos)
|
88
|
+
ensure_registered_model_class!(model_class)
|
89
|
+
filter_model_repositories(model_class, *repos).each do |repo|
|
90
|
+
state[:models][model_class][repo] = false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def ensure_registered_model_class!(model_class)
|
95
|
+
return if registered_model_class?(model_class)
|
96
|
+
|
97
|
+
raise ArgumentError, "Model class #{model_class} is not registered. The model should inherit from Esse::ActiveRecord::Model and have a `index_callback' callback defined"
|
98
|
+
end
|
99
|
+
|
100
|
+
# Check if the given model is enabled for indexing. If no repository is specified, all repositories will be checked.
|
101
|
+
#
|
102
|
+
# @param model_class [Class]
|
103
|
+
# @param repos [Array<String, Esse::Index, Esse::Repo>]
|
104
|
+
# @return [Boolean]
|
105
|
+
def enabled_for_model?(model_class, *repos)
|
106
|
+
return false unless registered_model_class?(model_class)
|
107
|
+
|
108
|
+
filter_model_repositories(model_class, *repos).all? do |repo|
|
109
|
+
state.dig(:models, model_class, repo) != false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Disable indexing callbacks execution for the block execution.
|
114
|
+
# Example:
|
115
|
+
# Esse::ActiveRecord::Hooks.without_indexing { User.create! }
|
116
|
+
# Esse::ActiveRecord::Hooks.without_indexing(UsersIndex, AccountsIndex.repo(:user)) { User.create! }
|
117
|
+
def without_indexing(*repos)
|
118
|
+
state_before_disable = state[:repos].dup
|
119
|
+
disable!(*repos)
|
120
|
+
|
121
|
+
yield
|
122
|
+
ensure
|
123
|
+
state[:repos] = state_before_disable
|
124
|
+
end
|
125
|
+
|
126
|
+
# Enable the indexing callbacks execution for the block execution.
|
127
|
+
# Example:
|
128
|
+
# Esse::ActiveRecord::Hooks.with_indexing { User.create! }
|
129
|
+
# Esse::ActiveRecord::Hooks.with_indexing(UsersIndex, AccountsIndex.repo(:user)) { User.create! }
|
130
|
+
def with_indexing(*repos)
|
131
|
+
state_before_enable = state[:repos].dup
|
132
|
+
enable!(*repos)
|
133
|
+
|
134
|
+
yield
|
135
|
+
ensure
|
136
|
+
state[:repos] = state_before_enable
|
137
|
+
end
|
138
|
+
|
139
|
+
# Disable model indexing callbacks execution for the block execution for the given model.
|
140
|
+
# Example:
|
141
|
+
# BroadcastChanges.without_indexing_for_model(User) { }
|
142
|
+
# BroadcastChanges.without_indexing_for_model(User, :datasync, :other) { }
|
143
|
+
def without_indexing_for_model(model_class, *repos)
|
144
|
+
state_before_disable = state[:models].dig(model_class).dup
|
145
|
+
disable_model!(model_class, *repos)
|
146
|
+
yield
|
147
|
+
ensure
|
148
|
+
if state_before_disable.nil?
|
149
|
+
state[:models].delete(model_class)
|
150
|
+
else
|
151
|
+
state[:models][model_class] = state_before_disable
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Enable model indexing callbacks execution for the block execution for the given model.
|
156
|
+
# Example:
|
157
|
+
# BroadcastChanges.with_indexing_for_model(User) { }
|
158
|
+
# BroadcastChanges.with_indexing_for_model(User, :datasync, :other) { }
|
159
|
+
def with_indexing_for_model(model_class, *repos)
|
160
|
+
state_before_enable = state[:models].dig(model_class).dup
|
161
|
+
enable_model!(model_class, *repos)
|
162
|
+
yield
|
163
|
+
ensure
|
164
|
+
if state_before_enable.nil?
|
165
|
+
state[:models].delete(model_class)
|
166
|
+
else
|
167
|
+
state[:models][model_class] = state_before_enable
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def resolve_index_repository(name)
|
172
|
+
index_name, repo_name = Esse::Hooks::Primitives::String.new(name).underscore.split("::").join("/").split(":", 2)
|
173
|
+
if index_name !~ /(I|_i)ndex$/ && index_name !~ /_index\/([\w_]+)$/
|
174
|
+
index_name = format("%<index_name>s_index", index_name: index_name)
|
175
|
+
end
|
176
|
+
klass = Esse::Hooks::Primitives::String.new(index_name).classify.constantize
|
177
|
+
return klass if klass <= Esse::Repository
|
178
|
+
|
179
|
+
repo_name ? klass.repo(repo_name) : klass.repo
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def all_repos
|
185
|
+
models.flat_map { |model_class| model_repos(model_class) }.uniq
|
186
|
+
end
|
187
|
+
|
188
|
+
# Returns a list of all repositories for the given model
|
189
|
+
# @return [Array<Symbol>]
|
190
|
+
def model_repos(model_class)
|
191
|
+
expand_index_repos(*model_class.esse_callbacks.keys)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns a list of all repositories for the given model
|
195
|
+
# If no repository is specified, all repositories will be returned.
|
196
|
+
# @return [Array<*Esse::Repository>] List of repositories
|
197
|
+
def filter_repositories(*repos)
|
198
|
+
filtered_repos = expand_index_repos(*repos) & all_repos
|
199
|
+
filtered_repos.empty? ? all_repos : filtered_repos
|
200
|
+
end
|
201
|
+
|
202
|
+
# Return repositorys for the given model. If no repository is specified, all repositories will be returned.
|
203
|
+
#
|
204
|
+
# @param model_class [Class]
|
205
|
+
# @param repos [Array<*Esse::Repository>] List of repositories to check for the given model
|
206
|
+
# @return [Array<*Esse::Repository>] List of repositories
|
207
|
+
def filter_model_repositories(model_class, *repos)
|
208
|
+
model_repos = model_repos(model_class) & all_repos
|
209
|
+
filtered_repos = expand_index_repos(*repos) & model_repos
|
210
|
+
filtered_repos.empty? ? model_repos : filtered_repos
|
211
|
+
end
|
212
|
+
|
213
|
+
def expand_index_repos(*repos)
|
214
|
+
repos.flat_map do |repo_name|
|
215
|
+
case repo_name
|
216
|
+
when Class
|
217
|
+
(repo_name <= Esse::Index) ? repo_name.repo_hash.values : repo_name
|
218
|
+
when String, Symbol
|
219
|
+
resolve_index_repository(repo_name)
|
220
|
+
else
|
221
|
+
raise ArgumentError, "Invalid index or repository name: #{repo_name.inspect}"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# Check if model class is registered
|
227
|
+
# @return [Boolean] true if model class is registered
|
228
|
+
def registered_model_class?(model_class)
|
229
|
+
models.include?(model_class)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Data Structure:
|
233
|
+
#
|
234
|
+
# repos: { <Esse::Repository class> => <true|false>, ... }
|
235
|
+
# models: {
|
236
|
+
# <ActiveRecord::Base class> => {
|
237
|
+
# <Esse::Repository class> => <true|false>
|
238
|
+
# }
|
239
|
+
# }
|
240
|
+
def state
|
241
|
+
global_store[store_key] ||= {
|
242
|
+
repos: all_repos.map { |k| [k, true] }.to_h, # Control global state of the index repository level
|
243
|
+
models: Hash.new { |h, k| h[k] = {} } # Control the state of the model & index repository level
|
244
|
+
}
|
245
|
+
end
|
246
|
+
|
247
|
+
def global_store
|
248
|
+
Thread.current
|
249
|
+
end
|
250
|
+
|
251
|
+
private
|
252
|
+
|
253
|
+
def store_key
|
254
|
+
raise NotImplementedError, "You must implement the `store_key` method"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "dry/inflector"
|
5
|
+
rescue LoadError
|
6
|
+
# noop
|
7
|
+
end
|
8
|
+
|
9
|
+
begin
|
10
|
+
require "active_support/inflector"
|
11
|
+
rescue LoadError
|
12
|
+
# noop
|
13
|
+
end
|
14
|
+
|
15
|
+
module Esse::Hooks::Primitives
|
16
|
+
class String < ::String
|
17
|
+
def classify
|
18
|
+
new_str = if defined?(Dry::Inflector)
|
19
|
+
Dry::Inflector.new.classify(self)
|
20
|
+
elsif defined?(ActiveSupport::Inflector)
|
21
|
+
ActiveSupport::Inflector.classify(self)
|
22
|
+
else
|
23
|
+
split("/").collect do |c|
|
24
|
+
c.split("_").collect(&:capitalize).join
|
25
|
+
end.join("::")
|
26
|
+
end
|
27
|
+
|
28
|
+
self.class.new(new_str)
|
29
|
+
end
|
30
|
+
|
31
|
+
def constantize
|
32
|
+
if defined?(Dry::Inflector)
|
33
|
+
Dry::Inflector.new.constantize(self)
|
34
|
+
elsif defined?(ActiveSupport::Inflector)
|
35
|
+
ActiveSupport::Inflector.constantize(self)
|
36
|
+
else
|
37
|
+
Object.const_get(self)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def underscore
|
42
|
+
new_str = sub(/^::/, "")
|
43
|
+
.gsub("::", "/")
|
44
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
45
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
46
|
+
.tr("-", "_")
|
47
|
+
.tr(".", "_")
|
48
|
+
.gsub(/\s/, "_")
|
49
|
+
.gsub(/__+/, "_")
|
50
|
+
.downcase
|
51
|
+
|
52
|
+
self.class.new(new_str)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/esse/hooks.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "esse"
|
4
|
+
require_relative "hooks/version"
|
5
|
+
require_relative "hooks/mixin"
|
6
|
+
require_relative "hooks/primitives/string"
|
7
|
+
|
8
|
+
module Esse
|
9
|
+
# Esse::Hooks is a module that extends Esse with hooks capabilities.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# module Esse::ActiveRecord::Hooks
|
13
|
+
# include Esse::Hooks[store_key: :esse_active_record_hooks]
|
14
|
+
module Hooks
|
15
|
+
@@hooks = {}.freeze
|
16
|
+
|
17
|
+
module_function
|
18
|
+
|
19
|
+
# Global variable with list of hooks.
|
20
|
+
#
|
21
|
+
# @return [Hash{Symbol => Module}]
|
22
|
+
def hooks
|
23
|
+
@@hooks
|
24
|
+
end
|
25
|
+
|
26
|
+
# Register a hook.
|
27
|
+
#
|
28
|
+
# @param [Symbol] name The hook name.
|
29
|
+
# @param [Module] hook The hook module.
|
30
|
+
def [](store_key:)
|
31
|
+
mixin = Mixin.new(store_key: store_key)
|
32
|
+
dup = @@hooks.dup
|
33
|
+
dup[mixin.store_key] = mixin
|
34
|
+
@@hooks = dup.freeze
|
35
|
+
mixin
|
36
|
+
end
|
37
|
+
|
38
|
+
%i[
|
39
|
+
enable!
|
40
|
+
disable!
|
41
|
+
with_indexing
|
42
|
+
with_indexing_for_model
|
43
|
+
without_indexing
|
44
|
+
without_indexing_for_model
|
45
|
+
].each do |method_name|
|
46
|
+
define_method(method_name) do |*args, &block|
|
47
|
+
hooks.each_value do |mixin|
|
48
|
+
mixin.public_send(method_name, *args, &block)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
%i[
|
54
|
+
disabled?
|
55
|
+
enabled?
|
56
|
+
].each do |method_name|
|
57
|
+
define_method(method_name) do
|
58
|
+
hooks.values.all?(&method_name)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/mise.toml
ADDED
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: esse-hooks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.beta1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marcos G. Zimmermann
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-01-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: esse
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.0
|
27
|
+
description: A set of hooks extensions for Esse, the Ruby ElasticSearch and OpenSearch
|
28
|
+
client.
|
29
|
+
email:
|
30
|
+
- mgzmaster@gmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".rubocop.yml"
|
36
|
+
- CHANGELOG.md
|
37
|
+
- Gemfile
|
38
|
+
- Gemfile.lock
|
39
|
+
- LICENSE.txt
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- lib/esse/hooks.rb
|
43
|
+
- lib/esse/hooks/mixin.rb
|
44
|
+
- lib/esse/hooks/primitives/string.rb
|
45
|
+
- lib/esse/hooks/version.rb
|
46
|
+
- mise.toml
|
47
|
+
homepage: https://github.com/marcosgz/esse-hooks
|
48
|
+
licenses:
|
49
|
+
- MIT
|
50
|
+
metadata:
|
51
|
+
homepage_uri: https://github.com/marcosgz/esse-hooks
|
52
|
+
source_code_uri: https://github.com/marcosgz/esse-hooks
|
53
|
+
changelog_uri: https://github.com/marcosgz/esse-hooks/blob/main/CHANGELOG.md
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 2.4.0
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.3.1
|
68
|
+
requirements: []
|
69
|
+
rubygems_version: 3.1.6
|
70
|
+
signing_key:
|
71
|
+
specification_version: 4
|
72
|
+
summary: Hooks extensions for Esse
|
73
|
+
test_files: []
|