stretchy-model 0.1.0 → 0.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/README.md +48 -3
- data/lib/rails/instrumentation/publishers.rb +1 -1
- data/lib/rails/instrumentation/railtie.rb +13 -19
- data/lib/stretchy/delegation/gateway_delegation.rb +1 -1
- data/lib/stretchy/open_search_compatibility.rb +86 -0
- data/lib/stretchy/scoping/scope_registry.rb +7 -7
- data/lib/stretchy/scoping.rb +4 -4
- data/lib/stretchy/version.rb +1 -1
- data/lib/stretchy.rb +37 -3
- data/stretchy-model/lib/stretchy-model.rb +1 -0
- metadata +25 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a85f7bffcc11c54366d4cae7fec47b91341425e06b7f1c8a6269e0b23d4e649b
|
4
|
+
data.tar.gz: cd0b9314fa734aa7af7179f12ed00626a17bc869186f82088158bfca87c8d915
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e193c837695100177eac9888841b14243596dfc9694515696ab1a9934174287c821cf52b2ca165e3f3eda04de9ba16c7c7330cb187641d71229d322c06674977
|
7
|
+
data.tar.gz: 21ace7b64f85d505a05b61b89b5b85d9d2af34941b57672da45f70e6c8736e8b9451c59891fef7d0795f8b54076cffd88bfc141fcd4da1c1f8ffaddcf8276697
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
stretchy
|
1
|
+
stretchy-model
|
2
2
|
===
|
3
3
|
|
4
4
|
<p>
|
@@ -112,11 +112,37 @@ Blanket (6.322ms) curl -X GET 'http://localhost:9200/blankets/_search?size=1' -d
|
|
112
112
|
|
113
113
|
Install the gem and add to the application's Gemfile by executing:
|
114
114
|
|
115
|
-
$ bundle add stretchy
|
115
|
+
$ bundle add stretchy-model
|
116
116
|
|
117
117
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
118
118
|
|
119
|
-
$ gem install stretchy
|
119
|
+
$ gem install stretchy-model
|
120
|
+
|
121
|
+
<details>
|
122
|
+
<summary>Rails Configuration</summary>
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
```sh
|
127
|
+
rails credentials:edit
|
128
|
+
```
|
129
|
+
|
130
|
+
#### Add elasticsearch credentials
|
131
|
+
```yaml
|
132
|
+
elasticsearch:
|
133
|
+
url: localhost:9200
|
134
|
+
```
|
135
|
+
|
136
|
+
#### Create an initializer
|
137
|
+
<p><sub><em>config/initializers/stretchy.rb</em></sub></p>
|
138
|
+
|
139
|
+
```ruby {file=config/initializers/stretchy.rb}
|
140
|
+
Stretchy.configure do |config|
|
141
|
+
config.client = Elasticsearch::Client.new url: Rails.application.credentials.elasticsearch.url, log: true
|
142
|
+
end
|
143
|
+
```
|
144
|
+
</details>
|
145
|
+
|
120
146
|
|
121
147
|
## Development
|
122
148
|
|
@@ -128,6 +154,10 @@ After checking out the repo, run `bin/setup` to install dependencies. You can al
|
|
128
154
|
> Full documentation on [Elasticsearch Query DSL and Aggregation options](https://github.com/elastic/elasticsearch-rails/tree/main/elasticsearch-persistence)
|
129
155
|
|
130
156
|
## Testing
|
157
|
+
<details>
|
158
|
+
<summary>Elasticsearch</summary>
|
159
|
+
|
160
|
+
|
131
161
|
```
|
132
162
|
docker-compose up elasticsearch
|
133
163
|
```
|
@@ -136,6 +166,21 @@ docker-compose up elasticsearch
|
|
136
166
|
bundle exec rspec
|
137
167
|
```
|
138
168
|
|
169
|
+
</details>
|
170
|
+
|
171
|
+
<details>
|
172
|
+
<summary>Opensearch</summary>
|
173
|
+
|
174
|
+
|
175
|
+
```
|
176
|
+
docker-compose up opensearch
|
177
|
+
```
|
178
|
+
|
179
|
+
```
|
180
|
+
ENV['BACKEND']=opensearch bundle rspec
|
181
|
+
```
|
182
|
+
</details>
|
183
|
+
|
139
184
|
## Contributing
|
140
185
|
|
141
186
|
Bug reports and pull requests are welcome on GitHub at https://github.com/theablefew/stretchy. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/theablefew/stretchy/blob/master/CODE_OF_CONDUCT.md).
|
@@ -14,7 +14,7 @@ module Rails
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def search_with_instrumentation!(query_or_definition, options={})
|
17
|
-
ActiveSupport::Notifications.instrument "search.
|
17
|
+
ActiveSupport::Notifications.instrument "search.stretchy",
|
18
18
|
name: "Search",
|
19
19
|
klass: self.base_class.to_s,
|
20
20
|
search: {index: self.index_name, body: query_or_definition }.merge(options) do
|
@@ -2,27 +2,21 @@ module Stretchy
|
|
2
2
|
module Instrumentation
|
3
3
|
|
4
4
|
class Railtie < ::Rails::Railtie
|
5
|
-
include ActionView::Helpers::NumberHelper
|
6
|
-
def time_diff(start, finish)
|
7
|
-
begin
|
8
|
-
((finish.to_time - start.to_time) * 1000).to_s(:rounded, precision: 5, strip_insignificant_zeros: true)
|
9
|
-
rescue
|
10
|
-
number_with_precision((finish.to_time - start.to_time) * 1000, precision: 5, strip_insignificant_zeros: true)
|
11
|
-
end
|
12
|
-
end
|
13
5
|
|
14
|
-
|
15
|
-
|
16
|
-
|
6
|
+
require 'rails/instrumentation/publishers'
|
7
|
+
ActiveSupport::Notifications.subscribe 'search.stretchy' do |name, start, finish, id, payload|
|
8
|
+
message = [
|
9
|
+
Rainbow(" #{payload[:klass]}").bright,
|
10
|
+
"(#{(finish.to_time - start.to_time).round(2)}ms)",
|
11
|
+
Stretchy::Utils.to_curl(payload[:klass].constantize, payload[:search])
|
12
|
+
].join(" ")
|
13
|
+
::Rails.logger.debug(Rainbow(message).color(:yellow))
|
14
|
+
end
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
initializer 'stretchy.set_defaults' do
|
23
|
-
config.elasticsearch_cache_store = :redis_store
|
24
|
-
config.elasticsearch_expire_cache_in = 15.minutes
|
25
|
-
end
|
16
|
+
# initializer 'stretchy.set_defaults' do
|
17
|
+
# config.elasticsearch_cache_store = :redis_store
|
18
|
+
# config.elasticsearch_expire_cache_in = 15.minutes
|
19
|
+
# end
|
26
20
|
|
27
21
|
end
|
28
22
|
end
|
@@ -33,7 +33,7 @@ module Stretchy
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def gateway(&block)
|
36
|
-
@gateway ||= Stretchy::Repository.create(index_name: index_name, klass: base_class)
|
36
|
+
@gateway ||= Stretchy::Repository.create(client: Stretchy.configuration.client, index_name: index_name, klass: base_class)
|
37
37
|
block.arity < 1 ? @gateway.instance_eval(&block) : block.call(@gateway) if block_given?
|
38
38
|
@gateway
|
39
39
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module OpenSearchCompatibility
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
# Patches the Elasticsearch::Persistence::Repository::Search module to remove the
|
6
|
+
# document type from the request for compatability with OpenSearch
|
7
|
+
def self.opensearch_patch!
|
8
|
+
patch = Module.new do
|
9
|
+
def search(query_or_definition, options={})
|
10
|
+
request = { index: index_name }
|
11
|
+
|
12
|
+
if query_or_definition.respond_to?(:to_hash)
|
13
|
+
request[:body] = query_or_definition.to_hash
|
14
|
+
elsif query_or_definition.is_a?(String)
|
15
|
+
request[:q] = query_or_definition
|
16
|
+
else
|
17
|
+
raise ArgumentError, "[!] Pass the search definition as a Hash-like object or pass the query as a String" +
|
18
|
+
" -- #{query_or_definition.class} given."
|
19
|
+
end
|
20
|
+
|
21
|
+
Elasticsearch::Persistence::Repository::Response::Results.new(self, client.search(request.merge(options)))
|
22
|
+
end
|
23
|
+
|
24
|
+
def count(query_or_definition=nil, options={})
|
25
|
+
query_or_definition ||= { query: { match_all: {} } }
|
26
|
+
request = { index: index_name}
|
27
|
+
|
28
|
+
if query_or_definition.respond_to?(:to_hash)
|
29
|
+
request[:body] = query_or_definition.to_hash
|
30
|
+
elsif query_or_definition.is_a?(String)
|
31
|
+
request[:q] = query_or_definition
|
32
|
+
else
|
33
|
+
raise ArgumentError, "[!] Pass the search definition as a Hash-like object or pass the query as a String" +
|
34
|
+
" -- #{query_or_definition.class} given."
|
35
|
+
end
|
36
|
+
|
37
|
+
client.count(request.merge(options))['count']
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
store = Module.new do
|
42
|
+
def save(document, options={})
|
43
|
+
serialized = serialize(document)
|
44
|
+
id = __get_id_from_document(serialized)
|
45
|
+
request = { index: index_name,
|
46
|
+
id: id,
|
47
|
+
body: serialized }
|
48
|
+
client.index(request.merge(options))
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def update(document_or_id, options = {})
|
53
|
+
if document_or_id.is_a?(String) || document_or_id.is_a?(Integer)
|
54
|
+
id = document_or_id
|
55
|
+
body = options
|
56
|
+
else
|
57
|
+
document = serialize(document_or_id)
|
58
|
+
id = __extract_id_from_document(document)
|
59
|
+
if options[:script]
|
60
|
+
body = options
|
61
|
+
else
|
62
|
+
body = { doc: document }.merge(options)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
client.update(index: index_name, id: id, body: body)
|
66
|
+
end
|
67
|
+
|
68
|
+
def delete(document_or_id, options = {})
|
69
|
+
if document_or_id.is_a?(String) || document_or_id.is_a?(Integer)
|
70
|
+
id = document_or_id
|
71
|
+
else
|
72
|
+
serialized = serialize(document_or_id)
|
73
|
+
id = __get_id_from_document(serialized)
|
74
|
+
end
|
75
|
+
client.delete({ index: index_name, id: id }.merge(options))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
::Elasticsearch::Persistence::Repository.send(:include, patch)
|
81
|
+
::Elasticsearch::Persistence::Repository.send(:include, store)
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -6,20 +6,20 @@ module Stretchy
|
|
6
6
|
|
7
7
|
VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope]
|
8
8
|
|
9
|
-
def initialize
|
10
|
-
|
11
|
-
end
|
9
|
+
# def initialize
|
10
|
+
self.registry = Hash.new { |hash, key| hash[key] = {} }
|
11
|
+
# end
|
12
12
|
|
13
13
|
# Obtains the value for a given +scope_name+ and +variable_name+.
|
14
|
-
def value_for(scope_type, variable_name)
|
14
|
+
def self.value_for(scope_type, variable_name)
|
15
15
|
raise_invalid_scope_type!(scope_type)
|
16
|
-
|
16
|
+
self.registry[scope_type][variable_name]
|
17
17
|
end
|
18
18
|
|
19
19
|
# Sets the +value+ for a given +scope_type+ and +variable_name+.
|
20
|
-
def set_value_for(scope_type, variable_name, value)
|
20
|
+
def self.set_value_for(scope_type, variable_name, value)
|
21
21
|
raise_invalid_scope_type!(scope_type)
|
22
|
-
|
22
|
+
self.registry[scope_type][variable_name] = value
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
data/lib/stretchy/scoping.rb
CHANGED
@@ -13,13 +13,13 @@ module Stretchy
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def current_scope
|
16
|
-
|
17
|
-
ScopeRegistry.
|
16
|
+
ScopeRegistry.new.registry[:current_scope][base_class.to_s]
|
17
|
+
# ScopeRegistry.value_for(:current_scope, base_class.to_s)
|
18
18
|
end
|
19
19
|
|
20
20
|
def current_scope=(scope) #:nodoc:
|
21
|
-
|
22
|
-
ScopeRegistry.
|
21
|
+
ScopeRegistry.new.registry[:current_scope][base_class.to_s] = scope
|
22
|
+
# ScopeRegistry.set_value_for(:current_scope, base_class.to_s, scope)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
data/lib/stretchy/version.rb
CHANGED
data/lib/stretchy.rb
CHANGED
@@ -3,10 +3,8 @@ require 'zeitwerk'
|
|
3
3
|
require 'amazing_print'
|
4
4
|
require 'rainbow'
|
5
5
|
require 'jbuilder'
|
6
|
-
# require 'elasticsearch/rails'
|
7
6
|
require 'elasticsearch/model'
|
8
7
|
require 'elasticsearch/persistence'
|
9
|
-
# require 'active_support/concern'
|
10
8
|
require 'active_model'
|
11
9
|
require 'active_support/all'
|
12
10
|
require 'active_model/type/array'
|
@@ -16,21 +14,57 @@ ActiveModel::Type.register(:array, ActiveModel::Type::Array)
|
|
16
14
|
ActiveModel::Type.register(:hash, ActiveModel::Type::Hash)
|
17
15
|
|
18
16
|
require_relative "stretchy/version"
|
19
|
-
require_relative "
|
17
|
+
require_relative "rails/instrumentation/railtie" if defined?(Rails)
|
20
18
|
|
21
19
|
module Stretchy
|
22
20
|
module Errors
|
23
21
|
class QueryOptionMissing < StandardError; end
|
24
22
|
end
|
25
23
|
|
24
|
+
class Configuration
|
25
|
+
|
26
|
+
attr_accessor :client
|
27
|
+
attr_accessor :opensearch
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@client = Elasticsearch::Client.new url: 'http://localhost:9200'
|
31
|
+
@opensearch = false
|
32
|
+
end
|
33
|
+
|
34
|
+
def client=(client)
|
35
|
+
@client = client
|
36
|
+
self.opensearch = true if @client.class.name =~ /OpenSearch/
|
37
|
+
end
|
38
|
+
|
39
|
+
def opensearch=(bool)
|
40
|
+
@opensearch = bool
|
41
|
+
OpenSearchCompatibility.opensearch_patch! if bool
|
42
|
+
end
|
43
|
+
|
44
|
+
def opensearch?
|
45
|
+
@opensearch
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
26
50
|
class << self
|
27
51
|
def logger
|
28
52
|
@logger ||= Logger.new(STDOUT)
|
29
53
|
end
|
54
|
+
|
55
|
+
def configuration
|
56
|
+
@configuration ||= Configuration.new
|
57
|
+
end
|
58
|
+
|
59
|
+
def configure
|
60
|
+
yield configuration
|
61
|
+
end
|
30
62
|
end
|
31
63
|
|
32
64
|
end
|
33
65
|
|
66
|
+
|
67
|
+
|
34
68
|
loader = Zeitwerk::Loader.new
|
35
69
|
loader.tag = File.basename(__FILE__, ".rb")
|
36
70
|
loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "../../lib/stretchy"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stretchy-model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Spencer Markowski
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-03-
|
11
|
+
date: 2024-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -28,42 +28,42 @@ dependencies:
|
|
28
28
|
name: elasticsearch-rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '7.1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '7.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: elasticsearch-persistence
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '7.1'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '7.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: elasticsearch-model
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '7.1'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '7.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: 0.9.36
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: opensearch-ruby
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '3.0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '3.0'
|
167
181
|
description: Provides a familiar ActiveRecord-like interface for working with Elasticsearch
|
168
182
|
email:
|
169
183
|
- spencer.markowski@theablefew.com
|
@@ -197,6 +211,7 @@ files:
|
|
197
211
|
- lib/stretchy/model/callbacks.rb
|
198
212
|
- lib/stretchy/model/serialization.rb
|
199
213
|
- lib/stretchy/null_relation.rb
|
214
|
+
- lib/stretchy/open_search_compatibility.rb
|
200
215
|
- lib/stretchy/persistence.rb
|
201
216
|
- lib/stretchy/querying.rb
|
202
217
|
- lib/stretchy/record.rb
|
@@ -217,6 +232,7 @@ files:
|
|
217
232
|
- lib/stretchy/utils.rb
|
218
233
|
- lib/stretchy/version.rb
|
219
234
|
- sig/stretchy.rbs
|
235
|
+
- stretchy-model/lib/stretchy-model.rb
|
220
236
|
- stretchy.logo.png
|
221
237
|
homepage: https://github.com/theablefew/stretchy
|
222
238
|
licenses:
|
@@ -229,6 +245,7 @@ post_install_message:
|
|
229
245
|
rdoc_options: []
|
230
246
|
require_paths:
|
231
247
|
- lib
|
248
|
+
- stretchy-model/lib
|
232
249
|
required_ruby_version: !ruby/object:Gem::Requirement
|
233
250
|
requirements:
|
234
251
|
- - ">="
|