meilisearch-rails 0.7.2 → 0.8.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/Gemfile +3 -0
- data/README.md +129 -47
- data/lib/meilisearch/rails/configuration.rb +33 -1
- data/lib/meilisearch/rails/errors.rb +1 -1
- data/lib/meilisearch/rails/null_object.rb +25 -0
- data/lib/meilisearch/rails/pagination/kaminari.rb +10 -22
- data/lib/meilisearch/rails/pagination/will_paginate.rb +1 -3
- data/lib/meilisearch/rails/pagination.rb +19 -6
- data/lib/meilisearch/rails/utilities.rb +25 -0
- data/lib/meilisearch/rails/version.rb +1 -1
- data/lib/meilisearch-rails.rb +35 -53
- data/meilisearch-rails.gemspec +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd9b1257d27f252b6dc5caf4dcc3316d6b8e2a026b6266e4aec67eb05106ace0
|
4
|
+
data.tar.gz: 356acde3b6a894b8a3e8c2e2206c04527b5927968a33030a6f73e0d807f709af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a813264676828158494dd04f5192ab902fd735e3ef0bbc17960b9a8f54fdc581139ec528cd87c0883be6bc96becdce8d455c0055d31b0464f9ba0d53cfbf0751
|
7
|
+
data.tar.gz: 0b5c4276212a365b038de5492a606be125902bac3bb9417a7cdf279c6e8bccdc146eb84b991b3c8e55928ee99c99510934da0cbbe958813709b6af6725fd7922
|
data/Gemfile
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
+
# gem 'meilisearch', path: '../meilisearch-ruby'
|
4
|
+
|
3
5
|
gemspec
|
4
6
|
|
5
7
|
gem 'rubysl', '~> 2.0', platform: :rbx if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
@@ -29,6 +31,7 @@ group :test do
|
|
29
31
|
gem 'jdbc-sqlite3', platform: :jruby
|
30
32
|
gem 'rspec', '~> 3.0'
|
31
33
|
gem 'simplecov', require: 'false'
|
34
|
+
gem 'threads'
|
32
35
|
|
33
36
|
gem 'byebug'
|
34
37
|
gem 'dotenv', '~> 2.7', '>= 2.7.6'
|
data/README.md
CHANGED
@@ -23,18 +23,20 @@
|
|
23
23
|
|
24
24
|
**Meilisearch Rails** is the Meilisearch integration for Ruby on Rails developers.
|
25
25
|
|
26
|
-
**Meilisearch** is an open-source search engine. [
|
26
|
+
**Meilisearch** is an open-source search engine. [Learn more about Meilisearch.](https://github.com/meilisearch/meilisearch)
|
27
27
|
|
28
28
|
## Table of Contents <!-- omit in toc -->
|
29
29
|
|
30
30
|
- [📖 Documentation](#-documentation)
|
31
31
|
- [🤖 Compatibility with Meilisearch](#-compatibility-with-meilisearch)
|
32
|
-
- [🚀 Getting
|
32
|
+
- [🚀 Getting started](#-getting-started)
|
33
33
|
- [Compatibility](#-compatibility)
|
34
34
|
- [⚙️ Settings](#️-settings)
|
35
35
|
- [🔍 Custom search](#-custom-search)
|
36
36
|
- [🪛 Options](#-options)
|
37
37
|
- [Meilisearch configuration & environment](#meilisearch-configuration--environment)
|
38
|
+
- [Pagination with `kaminari` or `will_paginate`](#backend-pagination-with-kaminari-or-will_paginate-)
|
39
|
+
- [Pagination with `pagy`](#backend-pagination-with-pagy-)
|
38
40
|
- [Index configuration](#index-configuration)
|
39
41
|
- [Custom attribute definition](#custom-attribute-definition)
|
40
42
|
- [Custom primary key](#custom-primary-key)
|
@@ -60,7 +62,7 @@ To learn more about Meilisearch, check out our [Documentation](https://docs.meil
|
|
60
62
|
|
61
63
|
## 🤖 Compatibility with Meilisearch
|
62
64
|
|
63
|
-
This package only guarantees the compatibility with the [version v0.
|
65
|
+
This package only guarantees the compatibility with the [version v0.30.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.30.0).
|
64
66
|
|
65
67
|
## 🔧 Installation <!-- omit in toc -->
|
66
68
|
|
@@ -91,7 +93,7 @@ docker run -it --rm -p 7700:7700 getmeili/meilisearch:latest meilisearch --maste
|
|
91
93
|
|
92
94
|
NB: you can also download Meilisearch from **Homebrew** or **APT**.
|
93
95
|
|
94
|
-
## 🚀 Getting
|
96
|
+
## 🚀 Getting started
|
95
97
|
|
96
98
|
#### Configuration <!-- omit in toc -->
|
97
99
|
|
@@ -99,7 +101,7 @@ Create a new file `config/initializers/meilisearch.rb` to setup your `MEILISEARC
|
|
99
101
|
|
100
102
|
```ruby
|
101
103
|
MeiliSearch::Rails.configuration = {
|
102
|
-
|
104
|
+
meilisearch_url: 'YourMeilisearchUrl', # example: http://localhost:7700
|
103
105
|
meilisearch_api_key: 'YourMeilisearchAPIKey',
|
104
106
|
}
|
105
107
|
```
|
@@ -138,46 +140,6 @@ hits.each do |hit|
|
|
138
140
|
end
|
139
141
|
```
|
140
142
|
|
141
|
-
#### Backend Pagination <!-- omit in toc -->
|
142
|
-
|
143
|
-
This gem supports:
|
144
|
-
- [kaminari](https://github.com/amatsuda/kaminari)
|
145
|
-
- [pagy](https://github.com/ddnexus/pagy)
|
146
|
-
- [will_paginate](https://github.com/mislav/will_paginate).
|
147
|
-
|
148
|
-
Specify the `:pagination_backend` in the configuration file:
|
149
|
-
|
150
|
-
```ruby
|
151
|
-
MeiliSearch::Rails.configuration = {
|
152
|
-
meilisearch_host: 'YourMeilisearchHost',
|
153
|
-
meilisearch_api_key: 'YourMeilisearchAPIKey',
|
154
|
-
pagination_backend: :kaminari #:will_paginate
|
155
|
-
}
|
156
|
-
```
|
157
|
-
|
158
|
-
Then, as soon as you use the `search` method, the returning results will be paginated:
|
159
|
-
|
160
|
-
```ruby
|
161
|
-
# controller
|
162
|
-
@hits = Book.search('harry potter')
|
163
|
-
|
164
|
-
# views
|
165
|
-
<% @hits.each do |hit| %>
|
166
|
-
<%= hit.title %>
|
167
|
-
<%= hit.author %>
|
168
|
-
<% end %>
|
169
|
-
|
170
|
-
<%= paginate @hits %> # if using kaminari
|
171
|
-
|
172
|
-
<%= will_paginate @hits %> # if using will_paginate
|
173
|
-
```
|
174
|
-
|
175
|
-
The **number of hits per page defaults to 20**, you can customize it by adding the `hits_per_page` parameter to your search:
|
176
|
-
|
177
|
-
```ruby
|
178
|
-
Book.search('harry potter', hits_per_page: 10)
|
179
|
-
```
|
180
|
-
|
181
143
|
#### Extra Configuration <!-- omit in toc -->
|
182
144
|
|
183
145
|
Requests made to Meilisearch may timeout and retry. To adapt the behavior to
|
@@ -185,7 +147,7 @@ your needs, you can change the parameters during configuration:
|
|
185
147
|
|
186
148
|
```ruby
|
187
149
|
MeiliSearch::Rails.configuration = {
|
188
|
-
|
150
|
+
meilisearch_url: 'YourMeilisearchUrl',
|
189
151
|
meilisearch_api_key: 'YourMeilisearchAPIKey',
|
190
152
|
timeout: 2,
|
191
153
|
max_retries: 1,
|
@@ -223,6 +185,7 @@ class Book < ApplicationRecord
|
|
223
185
|
attributes_to_highlight ['*']
|
224
186
|
attributes_to_crop [:description]
|
225
187
|
crop_length 10
|
188
|
+
pagination max_total_hits: 1000
|
226
189
|
end
|
227
190
|
end
|
228
191
|
```
|
@@ -254,6 +217,125 @@ Book.search('*', sort: ['title:asc'])
|
|
254
217
|
|
255
218
|
### Meilisearch configuration & environment
|
256
219
|
|
220
|
+
### Backend Pagination with `kaminari` or `will_paginate` <!-- omit in toc -->
|
221
|
+
|
222
|
+
This gem supports:
|
223
|
+
- [kaminari](https://github.com/amatsuda/kaminari)
|
224
|
+
- [will_paginate](https://github.com/mislav/will_paginate)
|
225
|
+
|
226
|
+
Specify the `:pagination_backend` in the configuration file:
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
MeiliSearch::Rails.configuration = {
|
230
|
+
meilisearch_url: 'YourMeilisearchUrl',
|
231
|
+
meilisearch_api_key: 'YourMeilisearchAPIKey',
|
232
|
+
pagination_backend: :kaminari # :will_paginate
|
233
|
+
}
|
234
|
+
```
|
235
|
+
|
236
|
+
Then, as soon as you use the `search` method, the returning results will be paginated:
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
# controller
|
240
|
+
@hits = Book.search('harry potter')
|
241
|
+
|
242
|
+
# views
|
243
|
+
<% @hits.each do |hit| %>
|
244
|
+
<%= hit.title %>
|
245
|
+
<%= hit.author %>
|
246
|
+
<% end %>
|
247
|
+
|
248
|
+
<%= paginate @hits %> # if using kaminari
|
249
|
+
|
250
|
+
<%= will_paginate @hits %> # if using will_paginate
|
251
|
+
```
|
252
|
+
|
253
|
+
The **number of hits per page defaults to 20**, you can customize it by adding the `hits_per_page` parameter to your search:
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
Book.search('harry potter', hits_per_page: 10)
|
257
|
+
```
|
258
|
+
|
259
|
+
### Backend Pagination with `pagy` <!-- omit in toc -->
|
260
|
+
|
261
|
+
This gem supports [pagy](https://github.com/ddnexus/pagy) to paginate your search results.
|
262
|
+
|
263
|
+
To use `pagy` with your `meilisearch-rails` you need to:
|
264
|
+
|
265
|
+
Add the `pagy` gem to your Gemfile.
|
266
|
+
Create a new initializer `pagy.rb` with this:
|
267
|
+
|
268
|
+
```rb
|
269
|
+
# config/initializers/pagy.rb
|
270
|
+
|
271
|
+
require 'pagy/extras/meilisearch'
|
272
|
+
```
|
273
|
+
|
274
|
+
Then in your model you must extend `Pagy::Meilisearch`:
|
275
|
+
|
276
|
+
```rb
|
277
|
+
class Book < ApplicationRecord
|
278
|
+
include MeiliSearch::Rails
|
279
|
+
extend Pagy::Meilisearch
|
280
|
+
|
281
|
+
meilisearch # ...
|
282
|
+
end
|
283
|
+
```
|
284
|
+
|
285
|
+
And in your controller and view:
|
286
|
+
|
287
|
+
```rb
|
288
|
+
# controllers/books_controller.rb
|
289
|
+
def search
|
290
|
+
hits = Book.pagy_search(params[:query])
|
291
|
+
@pagy, @hits = pagy_meilisearch(hits, items: 25)
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
# views/books/search.html.rb
|
296
|
+
<%== pagy_nav(@pagy) %>
|
297
|
+
```
|
298
|
+
|
299
|
+
:warning: There is no need to set `pagination_backend` in the configuration block `MeiliSearch::Rails.configuration` for `pagy`.
|
300
|
+
|
301
|
+
Check [`ddnexus/pagy`](https://ddnexus.github.io/pagy/extras/meilisearch) for more information.
|
302
|
+
|
303
|
+
#### Deactivate Meilisearch in certain moments
|
304
|
+
|
305
|
+
By default HTTP connections to the Meilisearch URL is always active, but sometimes you want to disable the HTTP requests in a particular moment or environment.<br>
|
306
|
+
you have multiple ways to achieve this.
|
307
|
+
|
308
|
+
By adding `active: false` in the configuration initializer:
|
309
|
+
|
310
|
+
```ruby
|
311
|
+
MeiliSearch::Rails.configuration = {
|
312
|
+
meilisearch_url: 'YourMeilisearchUrl',
|
313
|
+
meilisearch_api_key: 'YourMeilisearchAPIKey',
|
314
|
+
active: false
|
315
|
+
}
|
316
|
+
```
|
317
|
+
|
318
|
+
Or you can disable programmatically:
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
MeiliSearch::Rails.deactivate! # all the following HTTP calls will be dismissed.
|
322
|
+
|
323
|
+
# or you can pass a block to it:
|
324
|
+
|
325
|
+
MeiliSearch::Rails.deactivate! do
|
326
|
+
# every Meilisearch call here will be dismissed, no error will be raised.
|
327
|
+
# after the block, Meilisearch state will be active.
|
328
|
+
end
|
329
|
+
```
|
330
|
+
|
331
|
+
You can also activate if you deactivated earlier:
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
MeiliSearch::Rails.activate!
|
335
|
+
```
|
336
|
+
|
337
|
+
:warning: These calls are persistent, so prefer to use the method with the block. This way, you will not forget to activate it afterward.
|
338
|
+
|
257
339
|
#### Custom index_uid <!-- omit in toc -->
|
258
340
|
|
259
341
|
By default, the **index_uid** will be the class name, e.g. `Book`. You can customize the index_uid by using the `index_uid:` option.
|
@@ -272,7 +354,7 @@ You can suffix the index UID with the current Rails environment by setting it gl
|
|
272
354
|
|
273
355
|
```ruby
|
274
356
|
MeiliSearch::Rails.configuration = {
|
275
|
-
|
357
|
+
meilisearch_url: 'YourMeilisearchUrl',
|
276
358
|
meilisearch_api_key: 'YourMeilisearchAPIKey',
|
277
359
|
per_environment: true
|
278
360
|
}
|
@@ -11,9 +11,41 @@ module MeiliSearch
|
|
11
11
|
@_config = configuration
|
12
12
|
end
|
13
13
|
|
14
|
+
def deactivate!
|
15
|
+
semaphore.synchronize do
|
16
|
+
@_config.merge!(active: false)
|
17
|
+
|
18
|
+
return unless block_given?
|
19
|
+
|
20
|
+
yield
|
21
|
+
|
22
|
+
@_config.merge!(active: true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def activate!
|
27
|
+
semaphore.synchronize do
|
28
|
+
@_config.merge!(active: true)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def active?
|
33
|
+
configuration.fetch(:active, true)
|
34
|
+
end
|
35
|
+
|
36
|
+
def black_hole
|
37
|
+
@black_hole ||= NullObject.instance
|
38
|
+
end
|
39
|
+
|
40
|
+
def semaphore
|
41
|
+
@semaphore ||= Mutex.new
|
42
|
+
end
|
43
|
+
|
14
44
|
def client
|
45
|
+
return black_hole unless active?
|
46
|
+
|
15
47
|
::MeiliSearch::Client.new(
|
16
|
-
configuration[:
|
48
|
+
configuration[:meilisearch_url] || 'http://localhost:7700',
|
17
49
|
configuration[:meilisearch_api_key],
|
18
50
|
configuration.slice(:timeout, :max_retries)
|
19
51
|
.merge(client_agents: MeiliSearch::Rails.qualified_version)
|
@@ -7,7 +7,7 @@ module MeiliSearch
|
|
7
7
|
class NotConfigured < StandardError
|
8
8
|
def message
|
9
9
|
'Please configure Meilisearch. Set MeiliSearch::Rails.configuration = ' \
|
10
|
-
"{
|
10
|
+
"{meilisearch_url: 'YOUR_MEILISEARCH_URL', meilisearch_api_key: 'YOUR_API_KEY'}"
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module MeiliSearch
|
4
|
+
module Rails
|
5
|
+
class NullObject
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def map
|
9
|
+
[]
|
10
|
+
end
|
11
|
+
|
12
|
+
def nil?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(_method, *_args, &_block)
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def respond_to_missing?(_method_name, _include_private = false)
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -17,30 +17,18 @@ module MeiliSearch
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
def offset(_num)
|
26
|
-
# noop
|
27
|
-
self
|
28
|
-
end
|
20
|
+
def self.create(results, total_hits, options = {})
|
21
|
+
offset = ((options[:page] - 1) * options[:per_page])
|
22
|
+
array = new results, limit: options[:per_page], offset: offset, total_count: total_hits
|
29
23
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
if array.empty? && !results.empty?
|
36
|
-
# since Kaminari 0.16.0, you need to pad the results with nil values so it matches the offset param
|
37
|
-
# otherwise you'll get an empty array: https://github.com/amatsuda/kaminari/commit/29fdcfa8865f2021f710adaedb41b7a7b081e34d
|
38
|
-
results = ([nil] * offset) + results
|
39
|
-
array = new results, offset: offset, limit: options[:per_page], total_count: total_hits
|
40
|
-
end
|
41
|
-
|
42
|
-
array
|
24
|
+
if array.empty? && !results.empty?
|
25
|
+
# since Kaminari 0.16.0, you need to pad the results with nil values so it matches the offset param
|
26
|
+
# otherwise you'll get an empty array: https://github.com/amatsuda/kaminari/commit/29fdcfa8865f2021f710adaedb41b7a7b081e34d
|
27
|
+
results = Array.new(offset) + results
|
28
|
+
array = new results, offset: offset, limit: options[:per_page], total_count: total_hits
|
43
29
|
end
|
30
|
+
|
31
|
+
array
|
44
32
|
end
|
45
33
|
end
|
46
34
|
end
|
@@ -11,9 +11,7 @@ module MeiliSearch
|
|
11
11
|
class WillPaginate
|
12
12
|
def self.create(results, total_hits, options = {})
|
13
13
|
::WillPaginate::Collection.create(options[:page], options[:per_page], total_hits) do |pager|
|
14
|
-
|
15
|
-
paginated_results = results[start, options[:per_page]]
|
16
|
-
pager.replace paginated_results
|
14
|
+
pager.replace results
|
17
15
|
end
|
18
16
|
end
|
19
17
|
end
|
@@ -5,15 +5,28 @@ module MeiliSearch
|
|
5
5
|
autoload :Kaminari, 'meilisearch/rails/pagination/kaminari'
|
6
6
|
|
7
7
|
def self.create(results, total_hits, options = {})
|
8
|
-
|
8
|
+
pagination_backend = MeiliSearch::Rails.configuration[:pagination_backend]
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
if pagination_backend.nil? || (is_pagy = pagination_backend.to_s == 'pagy')
|
11
|
+
log_pagy_error if is_pagy
|
12
12
|
|
13
|
-
|
14
|
-
rescue NameError
|
15
|
-
raise(BadConfiguration, 'Unknown pagination backend')
|
13
|
+
return results
|
16
14
|
end
|
15
|
+
|
16
|
+
load_pagination!(pagination_backend, results, total_hits, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.log_pagy_error
|
20
|
+
(::Rails.logger || Logger.new($stdout))
|
21
|
+
.warning('[meilisearch-rails] Remove `pagination_backend: :pagy` from your initializer, `pagy` it is not required for `pagy`')
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.load_pagination!(pagination_backend, results, total_hits, options)
|
25
|
+
::MeiliSearch::Rails::Pagination
|
26
|
+
.const_get(pagination_backend.to_s.classify)
|
27
|
+
.create(results, total_hits, options)
|
28
|
+
rescue NameError
|
29
|
+
raise(BadConfiguration, 'Invalid `pagination_backend:` configuration, check your initializer.')
|
17
30
|
end
|
18
31
|
end
|
19
32
|
end
|
@@ -40,6 +40,31 @@ module MeiliSearch
|
|
40
40
|
klass.ms_set_settings
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
def indexable?(record, options)
|
45
|
+
return false unless options[:if].blank? || constraint_passes?(record, options[:if])
|
46
|
+
return false unless options[:unless].blank? || !constraint_passes?(record, options[:unless])
|
47
|
+
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def constraint_passes?(record, constraint)
|
54
|
+
case constraint
|
55
|
+
when Symbol
|
56
|
+
record.send(constraint)
|
57
|
+
when String
|
58
|
+
record.send(constraint.to_sym)
|
59
|
+
when Enumerable
|
60
|
+
# All constraints must pass
|
61
|
+
constraint.all? { |inner_constraint| constraint_passes?(record, inner_constraint) }
|
62
|
+
else
|
63
|
+
raise ArgumentError, "Unknown constraint type: #{constraint} (#{constraint.class})" unless constraint.respond_to?(:call)
|
64
|
+
|
65
|
+
constraint.call(record)
|
66
|
+
end
|
67
|
+
end
|
43
68
|
end
|
44
69
|
end
|
45
70
|
end
|
data/lib/meilisearch-rails.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'meilisearch'
|
2
|
-
|
2
|
+
require 'meilisearch/rails/null_object'
|
3
3
|
require 'meilisearch/rails/version'
|
4
4
|
require 'meilisearch/rails/utilities'
|
5
5
|
require 'meilisearch/rails/errors'
|
@@ -59,8 +59,11 @@ module MeiliSearch
|
|
59
59
|
attributesToHighlight
|
60
60
|
attributesToCrop
|
61
61
|
cropLength
|
62
|
+
pagination
|
62
63
|
].freeze
|
63
64
|
|
65
|
+
CAMELIZE_OPTIONS = %i[pagination].freeze
|
66
|
+
|
64
67
|
OPTIONS.each do |option|
|
65
68
|
define_method option do |value|
|
66
69
|
instance_variable_set("@#{option}", value)
|
@@ -199,7 +202,13 @@ module MeiliSearch
|
|
199
202
|
settings = {}
|
200
203
|
OPTIONS.each do |k|
|
201
204
|
v = get_setting(k)
|
202
|
-
|
205
|
+
next if v.nil?
|
206
|
+
|
207
|
+
settings[k] = if CAMELIZE_OPTIONS.include?(k) && v.is_a?(Hash)
|
208
|
+
v.transform_keys { |key| key.to_s.camelize(:lower) }
|
209
|
+
else
|
210
|
+
v
|
211
|
+
end
|
203
212
|
end
|
204
213
|
settings
|
205
214
|
end
|
@@ -249,7 +258,10 @@ module MeiliSearch
|
|
249
258
|
args[0].delete(:attributesToCrop) if args[0][:attributesToCrop]
|
250
259
|
args[0].delete(:cropLength) if args[0][:cropLength]
|
251
260
|
end
|
261
|
+
|
252
262
|
SafeIndex.log_or_throw(m, @raise_on_failure) do
|
263
|
+
return MeiliSearch::Rails.black_hole unless MeiliSearch::Rails.active?
|
264
|
+
|
253
265
|
@index.send(m, *args, &block)
|
254
266
|
end
|
255
267
|
end
|
@@ -281,7 +293,7 @@ module MeiliSearch
|
|
281
293
|
raise e if raise_on_failure
|
282
294
|
|
283
295
|
# log the error
|
284
|
-
(::Rails.logger || Logger.new($stdout)).
|
296
|
+
(::Rails.logger || Logger.new($stdout)).info("[meilisearch-rails] #{e.message}")
|
285
297
|
# return something
|
286
298
|
case method.to_s
|
287
299
|
when 'search'
|
@@ -342,7 +354,7 @@ module MeiliSearch
|
|
342
354
|
end
|
343
355
|
end
|
344
356
|
if options[:enqueue]
|
345
|
-
raise ArgumentError, 'Cannot use a enqueue if the `synchronous` option
|
357
|
+
raise ArgumentError, 'Cannot use a enqueue if the `synchronous` option is set' if options[:synchronous]
|
346
358
|
|
347
359
|
proc = if options[:enqueue] == true
|
348
360
|
proc do |record, remove|
|
@@ -452,10 +464,10 @@ module MeiliSearch
|
|
452
464
|
ms_find_in_batches(batch_size) do |group|
|
453
465
|
if ms_conditional_index?(options)
|
454
466
|
# delete non-indexable documents
|
455
|
-
ids = group.select { |d| !
|
467
|
+
ids = group.select { |d| !Utilities.indexable?(d, options) }.map { |d| ms_primary_key_of(d, options) }
|
456
468
|
index.delete_documents(ids.select(&:present?))
|
457
469
|
# select only indexable documents
|
458
|
-
group = group.select { |d|
|
470
|
+
group = group.select { |d| Utilities.indexable?(d, options) }
|
459
471
|
end
|
460
472
|
documents = group.map do |d|
|
461
473
|
attributes = settings.get_attributes(d)
|
@@ -502,7 +514,7 @@ module MeiliSearch
|
|
502
514
|
|
503
515
|
primary_key = ms_primary_key_of(document, options)
|
504
516
|
index = ms_ensure_init(options, settings)
|
505
|
-
if
|
517
|
+
if Utilities.indexable?(document, options)
|
506
518
|
raise ArgumentError, 'Cannot index a record without a primary key' if primary_key.blank?
|
507
519
|
|
508
520
|
doc = settings.get_attributes(document)
|
@@ -550,7 +562,7 @@ module MeiliSearch
|
|
550
562
|
|
551
563
|
index = ms_ensure_init(options, settings)
|
552
564
|
synchronous || options[:synchronous] ? index.delete_all_documents! : index.delete_all_documents
|
553
|
-
@ms_indexes[settings] = nil
|
565
|
+
@ms_indexes[MeiliSearch::Rails.active?][settings] = nil
|
554
566
|
end
|
555
567
|
nil
|
556
568
|
end
|
@@ -599,18 +611,15 @@ module MeiliSearch
|
|
599
611
|
|
600
612
|
def ms_search(query, params = {})
|
601
613
|
if MeiliSearch::Rails.configuration[:pagination_backend]
|
602
|
-
page
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
%i[page hitsPerPage hits_per_page].each { |param| params.delete(param) }
|
614
|
+
%i[page hitsPerPage hits_per_page].each do |key|
|
615
|
+
params[key.to_s.underscore.to_sym] = params[key].to_i if params.key?(key)
|
616
|
+
end
|
607
617
|
|
608
|
-
|
618
|
+
# It is required to activate the finite pagination in Meilisearch v0.30 (or newer),
|
619
|
+
# to have at least `hits_per_page` defined or `page` in the search request.
|
620
|
+
params[:page] ||= 1
|
609
621
|
end
|
610
622
|
|
611
|
-
# Returns raw json hits as follows:
|
612
|
-
# {"hits"=>[{"id"=>"13", "href"=>"apple", "name"=>"iphone"}], "offset"=>0, "limit"=>|| 20, "estimatedTotalHits"=>1,
|
613
|
-
# "processingTimeMs"=>0, "query"=>"iphone"}
|
614
623
|
json = ms_raw_search(query, params)
|
615
624
|
|
616
625
|
# condition_key gets the primary key of the document; looks for "id" on the options
|
@@ -653,11 +662,7 @@ module MeiliSearch
|
|
653
662
|
end
|
654
663
|
end.compact
|
655
664
|
|
656
|
-
|
657
|
-
hits_per_page ||= 20
|
658
|
-
page ||= 1
|
659
|
-
|
660
|
-
res = MeiliSearch::Rails::Pagination.create(results, total_hits, meilisearch_options.merge(page: page, per_page: hits_per_page))
|
665
|
+
res = Pagination.create(results, json['totalHits'], meilisearch_options.merge(page: json['page'], per_page: json['hitsPerPage']))
|
661
666
|
res.extend(AdditionalMethods)
|
662
667
|
res.send(:ms_init_raw_answer, json)
|
663
668
|
res
|
@@ -720,16 +725,16 @@ module MeiliSearch
|
|
720
725
|
def ms_ensure_init(options = nil, settings = nil, index_settings = nil)
|
721
726
|
raise ArgumentError, 'No `meilisearch` block found in your model.' if meilisearch_settings.nil?
|
722
727
|
|
723
|
-
@ms_indexes ||= {}
|
728
|
+
@ms_indexes ||= { true => {}, false => {} }
|
724
729
|
|
725
730
|
options ||= meilisearch_options
|
726
731
|
settings ||= meilisearch_settings
|
727
732
|
|
728
|
-
return @ms_indexes[settings] if @ms_indexes[settings]
|
733
|
+
return @ms_indexes[MeiliSearch::Rails.active?][settings] if @ms_indexes[MeiliSearch::Rails.active?][settings]
|
729
734
|
|
730
|
-
@ms_indexes[settings] = SafeIndex.new(ms_index_uid(options), meilisearch_options[:raise_on_failure], meilisearch_options)
|
735
|
+
@ms_indexes[MeiliSearch::Rails.active?][settings] = SafeIndex.new(ms_index_uid(options), meilisearch_options[:raise_on_failure], meilisearch_options)
|
731
736
|
|
732
|
-
current_settings = @ms_indexes[settings].settings(getVersion: 1) rescue nil # if the index doesn't exist
|
737
|
+
current_settings = @ms_indexes[MeiliSearch::Rails.active?][settings].settings(getVersion: 1) rescue nil # if the index doesn't exist
|
733
738
|
|
734
739
|
index_settings ||= settings.to_settings
|
735
740
|
index_settings = options[:primary_settings].to_settings.merge(index_settings) if options[:inherit]
|
@@ -737,10 +742,10 @@ module MeiliSearch
|
|
737
742
|
options[:check_settings] = true if options[:check_settings].nil?
|
738
743
|
|
739
744
|
if !ms_indexing_disabled?(options) && options[:check_settings] && meilisearch_settings_changed?(current_settings, index_settings)
|
740
|
-
@ms_indexes[settings].update_settings(index_settings)
|
745
|
+
@ms_indexes[MeiliSearch::Rails.active?][settings].update_settings(index_settings)
|
741
746
|
end
|
742
747
|
|
743
|
-
@ms_indexes[settings]
|
748
|
+
@ms_indexes[MeiliSearch::Rails.active?][settings]
|
744
749
|
end
|
745
750
|
|
746
751
|
private
|
@@ -802,31 +807,6 @@ module MeiliSearch
|
|
802
807
|
options[:if].present? || options[:unless].present?
|
803
808
|
end
|
804
809
|
|
805
|
-
def ms_indexable?(document, options = nil)
|
806
|
-
options ||= meilisearch_options
|
807
|
-
if_passes = options[:if].blank? || ms_constraint_passes?(document, options[:if])
|
808
|
-
unless_passes = options[:unless].blank? || !ms_constraint_passes?(document, options[:unless])
|
809
|
-
if_passes && unless_passes
|
810
|
-
end
|
811
|
-
|
812
|
-
def ms_constraint_passes?(document, constraint)
|
813
|
-
case constraint
|
814
|
-
when Symbol
|
815
|
-
document.send(constraint)
|
816
|
-
when String
|
817
|
-
document.send(constraint.to_sym)
|
818
|
-
when Enumerable
|
819
|
-
# All constraints must pass
|
820
|
-
constraint.all? { |inner_constraint| ms_constraint_passes?(document, inner_constraint) }
|
821
|
-
else
|
822
|
-
unless constraint.respond_to?(:call)
|
823
|
-
raise ArgumentError, "Unknown constraint type: #{constraint} (#{constraint.class})"
|
824
|
-
end
|
825
|
-
|
826
|
-
constraint.call(document)
|
827
|
-
end
|
828
|
-
end
|
829
|
-
|
830
810
|
def ms_indexing_disabled?(options = nil)
|
831
811
|
options ||= meilisearch_options
|
832
812
|
constraint = options[:disable_indexing] || options['disable_indexing']
|
@@ -902,6 +882,8 @@ module MeiliSearch
|
|
902
882
|
end
|
903
883
|
|
904
884
|
def ms_enqueue_index!(synchronous)
|
885
|
+
return unless Utilities.indexable?(self, meilisearch_options)
|
886
|
+
|
905
887
|
if meilisearch_options[:enqueue]
|
906
888
|
unless self.class.send(:ms_indexing_disabled?, meilisearch_options)
|
907
889
|
meilisearch_options[:enqueue].call(self, false)
|
data/meilisearch-rails.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: meilisearch-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Meili
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: meilisearch
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.21.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.21.0
|
27
27
|
description: Meilisearch integration for Ruby on Rails. See https://github.com/meilisearch/meilisearch
|
28
28
|
email: bonjour@meilisearch.com
|
29
29
|
executables: []
|
@@ -41,6 +41,7 @@ files:
|
|
41
41
|
- lib/meilisearch/rails/configuration.rb
|
42
42
|
- lib/meilisearch/rails/errors.rb
|
43
43
|
- lib/meilisearch/rails/ms_job.rb
|
44
|
+
- lib/meilisearch/rails/null_object.rb
|
44
45
|
- lib/meilisearch/rails/pagination.rb
|
45
46
|
- lib/meilisearch/rails/pagination/kaminari.rb
|
46
47
|
- lib/meilisearch/rails/pagination/will_paginate.rb
|