meilisearch-rails 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|