stretchy-model 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
- - ">="
|