meilisearch-rails 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +75 -52
- data/lib/meilisearch-rails.rb +18 -19
- data/lib/meilisearch/pagination/kaminari.rb +2 -2
- data/lib/meilisearch/version.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/utilities_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1562941b9f5cf4cb5a13085147f5b9b9ba1b3ea04587f6d1c520239ae5362236
|
4
|
+
data.tar.gz: 57106ef19a839131d89e45bbb3d01f6aeef6fca623f3d803ade4f63282c2221d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d33ff75ad9c5dc9eeab0c602bdfc5fa8f80b1d14d3a025105cf04c7c2e644a1309e68cbff56452eeea5c1801e13fc58d11f8dd529b02bd6ac14e3baf4c30d20
|
7
|
+
data.tar.gz: 02720ef33a1a0da9cc309f04c24129c87b9f1d885e9d8ff4386ba0873f1aec14e88373bbabe8eae279627a76e573046d4ae445ac1837efffda39b7a458e33fa3
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -126,6 +126,8 @@ class Book < ActiveRecord::Base
|
|
126
126
|
end
|
127
127
|
```
|
128
128
|
|
129
|
+
⚠️ Note that even if you want to use all the default options, you must declare an empty `meilisearch` block in your model.
|
130
|
+
|
129
131
|
#### Basic Backend Search <!-- omit in toc -->
|
130
132
|
|
131
133
|
We **strongly recommend the use of front-end search** through our [JavaScript API Client](https://github.com/meilisearch/meilisearch-js/) or [Instant Meilisearch plugin](https://github.com/meilisearch/instant-meilisearch)
|
@@ -143,15 +145,18 @@ end
|
|
143
145
|
|
144
146
|
#### Backend Pagination <!-- omit in toc -->
|
145
147
|
|
146
|
-
|
148
|
+
This gem supports:
|
149
|
+
- [kaminari](https://github.com/amatsuda/kaminari)
|
150
|
+
- [pagy](https://github.com/ddnexus/pagy)
|
151
|
+
- [will_paginate](https://github.com/mislav/will_paginate).
|
147
152
|
|
148
153
|
Specify the `:pagination_backend` in the configuration file:
|
149
154
|
|
150
155
|
```ruby
|
151
156
|
MeiliSearch.configuration = {
|
152
|
-
|
153
|
-
|
154
|
-
|
157
|
+
meilisearch_host: 'YourMeiliSearchHost',
|
158
|
+
meilisearch_api_key: 'YourMeiliSearchAPIKey',
|
159
|
+
pagination_backend: :kaminari #:will_paginate
|
155
160
|
}
|
156
161
|
```
|
157
162
|
|
@@ -187,22 +192,23 @@ class Book < ApplicationRecord
|
|
187
192
|
include MeiliSearch
|
188
193
|
|
189
194
|
meilisearch do
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
195
|
+
searchable_attributes [:title, :author, :publisher, :description]
|
196
|
+
attributes_for_faceting [:genre]
|
197
|
+
ranking_rules [
|
198
|
+
'proximity',
|
199
|
+
'typo',
|
200
|
+
'words',
|
201
|
+
'attribute',
|
202
|
+
'wordsPosition',
|
203
|
+
'exactness',
|
204
|
+
'desc(publication_year)'
|
200
205
|
]
|
201
206
|
synonyms nyc: ['new york']
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
207
|
+
|
208
|
+
# The following parameters are applied when calling the search() method:
|
209
|
+
attributes_to_highlight ['*']
|
210
|
+
attributes_to_crop [:description]
|
211
|
+
crop_length 10
|
206
212
|
end
|
207
213
|
end
|
208
214
|
```
|
@@ -214,9 +220,10 @@ Check the dedicated section of the documentation, for more information on the [s
|
|
214
220
|
All the supported options are described in the [search parameters](https://docs.meilisearch.com/reference/features/search_parameters.html) section of the documentation.
|
215
221
|
|
216
222
|
```ruby
|
217
|
-
Book.search('Harry',
|
223
|
+
Book.search('Harry', filters: 'author = J. K. Rowling')
|
218
224
|
```
|
219
|
-
👉 Don't forget that `
|
225
|
+
👉 Don't forget that `attributes_to_highlight`, `attributes_to_crop`, and
|
226
|
+
`crop_length` can be set up in the `meilisearch` block of your model.
|
220
227
|
|
221
228
|
## 🪛 Options
|
222
229
|
|
@@ -224,12 +231,13 @@ Book.search('Harry', { filters: 'author = J. K. Rowling' })
|
|
224
231
|
|
225
232
|
#### Custom index_uid
|
226
233
|
|
227
|
-
By default, the **index_uid** will be the class name, e.g. `Book`. You can customize the index_uid by using the `index_uid
|
234
|
+
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.
|
228
235
|
|
229
236
|
```ruby
|
230
237
|
class Book < ActiveRecord::Base
|
231
238
|
include MeiliSearch
|
232
|
-
|
239
|
+
|
240
|
+
meilisearch index_uid: 'MyCustomUID' do
|
233
241
|
end
|
234
242
|
end
|
235
243
|
```
|
@@ -241,6 +249,7 @@ You can suffix the index UID with the current Rails environment using the follow
|
|
241
249
|
```ruby
|
242
250
|
class Book < ActiveRecord::Base
|
243
251
|
include MeiliSearch
|
252
|
+
|
244
253
|
meilisearch per_environment: true do # The index UID will be "Book_#{Rails.env}"
|
245
254
|
end
|
246
255
|
end
|
@@ -282,27 +291,28 @@ end
|
|
282
291
|
|
283
292
|
#### Custom primary key
|
284
293
|
|
285
|
-
By default, the
|
294
|
+
By default, the primary key is based on your record's id. You can change this behavior by specifying the `primary_key:` option.
|
286
295
|
|
287
296
|
Note that the primary key must have a **unique value**.
|
288
297
|
|
289
298
|
```ruby
|
290
299
|
class Book < ActiveRecord::Base
|
291
300
|
include MeiliSearch
|
292
|
-
|
301
|
+
|
302
|
+
meilisearch primary_key: 'ISBN' do
|
293
303
|
end
|
294
304
|
end
|
295
305
|
```
|
296
306
|
#### Conditional indexing
|
297
307
|
|
298
|
-
You can control if a record must be indexed by using the
|
308
|
+
You can control if a record must be indexed by using the `if:` or `unless:` options.<br>
|
299
309
|
As soon as you use those constraints, `add_documents` and `delete_documents` calls will be performed in order to keep the index synced with the DB. To prevent this behavior, you can create a `will_save_change_to_#{attr_name}?` method.
|
300
310
|
|
301
311
|
```ruby
|
302
312
|
class Book < ActiveRecord::Base
|
303
313
|
include MeiliSearch
|
304
314
|
|
305
|
-
meilisearch :
|
315
|
+
meilisearch if: :published?, unless: :premium? do
|
306
316
|
end
|
307
317
|
|
308
318
|
def published?
|
@@ -314,7 +324,7 @@ class Book < ActiveRecord::Base
|
|
314
324
|
end
|
315
325
|
|
316
326
|
def will_save_change_to_published?
|
317
|
-
|
327
|
+
# return true only if you know that the 'published' state changed
|
318
328
|
end
|
319
329
|
end
|
320
330
|
```
|
@@ -324,7 +334,6 @@ You can index a record in several indexes using the `add_index` option:
|
|
324
334
|
|
325
335
|
```ruby
|
326
336
|
class Book < ActiveRecord::Base
|
327
|
-
|
328
337
|
include MeiliSearch
|
329
338
|
|
330
339
|
PUBLIC_INDEX_UID = 'Books'
|
@@ -332,17 +341,17 @@ class Book < ActiveRecord::Base
|
|
332
341
|
|
333
342
|
# store all books in index 'SECURED_INDEX_UID'
|
334
343
|
meilisearch index_uid: SECURED_INDEX_UID do
|
335
|
-
|
344
|
+
searchable_attributes [:title, :author]
|
336
345
|
|
337
346
|
# store all 'public' (released and not premium) books in index 'PUBLIC_INDEX_UID'
|
338
347
|
add_index PUBLIC_INDEX_UID, if: :public? do
|
339
|
-
|
348
|
+
searchable_attributes [:title, :author]
|
340
349
|
end
|
341
350
|
end
|
342
351
|
|
343
352
|
private
|
344
353
|
def public?
|
345
|
-
released && !premium
|
354
|
+
released? && !premium?
|
346
355
|
end
|
347
356
|
end
|
348
357
|
```
|
@@ -394,18 +403,31 @@ end
|
|
394
403
|
|
395
404
|
In this case you can bypass loading the record from **ActiveRecord** and just communicate with the index directly.
|
396
405
|
|
406
|
+
With **ActiveJob**:
|
407
|
+
|
397
408
|
```ruby
|
409
|
+
class Book < ActiveRecord::Base
|
410
|
+
include MeiliSearch
|
411
|
+
|
412
|
+
meilisearch enqueue: :trigger_job do
|
413
|
+
attribute :title, :author, :description
|
414
|
+
end
|
415
|
+
|
416
|
+
def self.trigger_job(record, remove)
|
417
|
+
MyActiveJob.perform_later(record.id, remove)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
398
421
|
class MyActiveJob < ApplicationJob
|
399
422
|
def perform(id, remove)
|
400
423
|
if remove
|
401
|
-
#
|
402
|
-
# use ActiveRecord#find to load it
|
403
|
-
# We access the underlying MeiliSearch index object
|
424
|
+
# The record has likely already been removed from your database so we cannot
|
425
|
+
# use ActiveRecord#find to load it.
|
426
|
+
# We access the underlying MeiliSearch index object.
|
404
427
|
Book.index.delete_document(id)
|
405
428
|
else
|
406
|
-
#
|
407
|
-
|
408
|
-
c.index!
|
429
|
+
# The record should be present.
|
430
|
+
Book.find(id).index!
|
409
431
|
end
|
410
432
|
end
|
411
433
|
end
|
@@ -429,14 +451,13 @@ end
|
|
429
451
|
class MySidekiqWorker
|
430
452
|
def perform(id, remove)
|
431
453
|
if remove
|
432
|
-
#
|
433
|
-
# use ActiveRecord#find to load it
|
434
|
-
# We access the underlying MeiliSearch index object
|
435
|
-
|
454
|
+
# The record has likely already been removed from your database so we cannot
|
455
|
+
# use ActiveRecord#find to load it.
|
456
|
+
# We access the underlying MeiliSearch index object.
|
457
|
+
Book.index.delete_document(id)
|
436
458
|
else
|
437
|
-
#
|
438
|
-
|
439
|
-
c.index!
|
459
|
+
# The record should be present.
|
460
|
+
Book.find(id).index!
|
440
461
|
end
|
441
462
|
end
|
442
463
|
end
|
@@ -466,7 +487,7 @@ end
|
|
466
487
|
|
467
488
|
Extend a change to a related record.
|
468
489
|
|
469
|
-
**With
|
490
|
+
**With ActiveRecord**, you'll need to use `touch` and `after_touch`.
|
470
491
|
|
471
492
|
```ruby
|
472
493
|
class Author < ActiveRecord::Base
|
@@ -546,7 +567,7 @@ You can strip all HTML tags from your attributes with the `sanitize` option.
|
|
546
567
|
class Book < ActiveRecord::Base
|
547
568
|
include MeiliSearch
|
548
569
|
|
549
|
-
meilisearch :
|
570
|
+
meilisearch sanitize: true do
|
550
571
|
end
|
551
572
|
end
|
552
573
|
```
|
@@ -559,7 +580,7 @@ You can force the UTF-8 encoding of all your attributes using the `force_utf8_en
|
|
559
580
|
class Book < ActiveRecord::Base
|
560
581
|
include MeiliSearch
|
561
582
|
|
562
|
-
meilisearch :
|
583
|
+
meilisearch force_utf8_encoding: true do
|
563
584
|
end
|
564
585
|
end
|
565
586
|
```
|
@@ -568,7 +589,7 @@ end
|
|
568
589
|
|
569
590
|
#### Indexing & deletion
|
570
591
|
|
571
|
-
You can manually index a record by using the `index!` instance method and remove it by using the `remove_from_index!` instance method
|
592
|
+
You can manually index a record by using the `index!` instance method and remove it by using the `remove_from_index!` instance method.
|
572
593
|
|
573
594
|
```ruby
|
574
595
|
book = Book.create!(title: 'The Little Prince', author: 'Antoine de Saint-Exupéry')
|
@@ -603,7 +624,6 @@ index = Book.index
|
|
603
624
|
|
604
625
|
### Development & testing
|
605
626
|
|
606
|
-
|
607
627
|
#### Exceptions
|
608
628
|
|
609
629
|
You can disable exceptions that could be raised while trying to reach MeiliSearch's API by using the `raise_on_failure` option:
|
@@ -612,14 +632,16 @@ You can disable exceptions that could be raised while trying to reach MeiliSearc
|
|
612
632
|
class Book < ActiveRecord::Base
|
613
633
|
include MeiliSearch
|
614
634
|
|
615
|
-
#
|
616
|
-
meilisearch :
|
635
|
+
# Only raise exceptions in development environment.
|
636
|
+
meilisearch raise_on_failure: Rails.env.development? do
|
617
637
|
end
|
618
638
|
end
|
619
639
|
```
|
620
640
|
|
621
641
|
#### Testing
|
642
|
+
|
622
643
|
##### Synchronous testing
|
644
|
+
|
623
645
|
You can force indexing and removing to be synchronous by setting the following option:
|
624
646
|
|
625
647
|
```ruby
|
@@ -649,7 +671,8 @@ You can temporarily disable auto-indexing using the without_auto_index scope:
|
|
649
671
|
|
650
672
|
```ruby
|
651
673
|
Book.without_auto_index do
|
652
|
-
|
674
|
+
# Inside this block, auto indexing task will not run.
|
675
|
+
1.upto(10000) { Book.create! attributes }
|
653
676
|
end
|
654
677
|
```
|
655
678
|
|
data/lib/meilisearch-rails.rb
CHANGED
@@ -52,16 +52,25 @@ module MeiliSearch
|
|
52
52
|
|
53
53
|
# MeiliSearch settings
|
54
54
|
OPTIONS = [
|
55
|
-
:searchableAttributes,
|
56
|
-
:
|
55
|
+
:searchableAttributes,
|
56
|
+
:attributesForFaceting,
|
57
|
+
:displayedAttributes,
|
58
|
+
:distinctAttribute,
|
59
|
+
:synonyms,
|
60
|
+
:stopWords,
|
61
|
+
:rankingRules,
|
57
62
|
:attributesToHighlight,
|
58
|
-
:attributesToCrop,
|
63
|
+
:attributesToCrop,
|
64
|
+
:cropLength,
|
59
65
|
]
|
60
66
|
|
61
|
-
OPTIONS.each do |
|
62
|
-
define_method
|
63
|
-
instance_variable_set("@#{
|
67
|
+
OPTIONS.each do |option|
|
68
|
+
define_method option do |value|
|
69
|
+
instance_variable_set("@#{option}", value)
|
64
70
|
end
|
71
|
+
|
72
|
+
underscored_name = option.to_s.gsub(/(.)([A-Z])/, '\1_\2').downcase
|
73
|
+
alias_method underscored_name, option if underscored_name != option
|
65
74
|
end
|
66
75
|
|
67
76
|
def initialize(options, &block)
|
@@ -315,7 +324,7 @@ module MeiliSearch
|
|
315
324
|
|
316
325
|
def meilisearch(options = {}, &block)
|
317
326
|
self.meilisearch_settings = IndexSettings.new(options, &block)
|
318
|
-
self.meilisearch_options = { :
|
327
|
+
self.meilisearch_options = { type: ms_full_const_get(model_name.to_s), per_page: meilisearch_settings.get_setting(:hitsPerPage) || 20, page: 1 }.merge(options)
|
319
328
|
|
320
329
|
attr_accessor :formatted
|
321
330
|
|
@@ -552,8 +561,6 @@ module MeiliSearch
|
|
552
561
|
params[:cropLength] = meilisearch_settings.get_setting(:cropLength) if !meilisearch_settings.get_setting(:cropLength).nil?
|
553
562
|
end
|
554
563
|
index = ms_index(index_uid)
|
555
|
-
# index = ms_index(ms_index_uid)
|
556
|
-
# index.search(q, Hash[params.map { |k,v| [k.to_s, v.to_s] }])
|
557
564
|
index.search(q, Hash[params.map { |k,v| [k, v] }])
|
558
565
|
end
|
559
566
|
|
@@ -590,14 +597,6 @@ module MeiliSearch
|
|
590
597
|
params[:limit] = 200
|
591
598
|
end
|
592
599
|
|
593
|
-
if !meilisearch_settings.get_setting(:attributesToHighlight).nil?
|
594
|
-
params[:attributesToHighlight] = meilisearch_settings.get_setting(:attributesToHighlight)
|
595
|
-
end
|
596
|
-
|
597
|
-
if !meilisearch_settings.get_setting(:attributesToCrop).nil?
|
598
|
-
params[:attributesToCrop] = meilisearch_settings.get_setting(:attributesToCrop)
|
599
|
-
params[:cropLength] = meilisearch_settings.get_setting(:cropLength) if !meilisearch_settings.get_setting(:cropLength).nil?
|
600
|
-
end
|
601
600
|
# Returns raw json hits as follows:
|
602
601
|
# {"hits"=>[{"id"=>"13", "href"=>"apple", "name"=>"iphone"}], "offset"=>0, "limit"=>|| 20, "nbHits"=>1, "exhaustiveNbHits"=>false, "processingTimeMs"=>0, "query"=>"iphone"}
|
603
602
|
json = ms_raw_search(q, params)
|
@@ -632,7 +631,7 @@ module MeiliSearch
|
|
632
631
|
hits_per_page ||= 20
|
633
632
|
page ||= 1
|
634
633
|
|
635
|
-
res = MeiliSearch::Pagination.create(results, total_hits, meilisearch_options.merge({ :
|
634
|
+
res = MeiliSearch::Pagination.create(results, total_hits, meilisearch_options.merge({ page: page , per_page: hits_per_page }))
|
636
635
|
res.extend(AdditionalMethods)
|
637
636
|
res.send(:ms_init_raw_answer, json)
|
638
637
|
res
|
@@ -823,7 +822,7 @@ module MeiliSearch
|
|
823
822
|
|
824
823
|
def ms_find_in_batches(batch_size, &block)
|
825
824
|
if (defined?(::ActiveRecord) && ancestors.include?(::ActiveRecord::Base)) || respond_to?(:find_in_batches)
|
826
|
-
find_in_batches(:
|
825
|
+
find_in_batches(batch_size: batch_size, &block)
|
827
826
|
elsif defined?(::Sequel) && self < Sequel::Model
|
828
827
|
dataset.extension(:pagination).each_page(batch_size, &block)
|
829
828
|
else
|
@@ -25,12 +25,12 @@ module MeiliSearch
|
|
25
25
|
class << self
|
26
26
|
def create(results, total_hits, options = {})
|
27
27
|
offset = ((options[:page] - 1) * options[:per_page])
|
28
|
-
array = new results, :
|
28
|
+
array = new results, limit: options[:per_page], offset: offset, total_count: total_hits
|
29
29
|
if array.empty? and !results.empty?
|
30
30
|
# since Kaminari 0.16.0, you need to pad the results with nil values so it matches the offset param
|
31
31
|
# otherwise you'll get an empty array: https://github.com/amatsuda/kaminari/commit/29fdcfa8865f2021f710adaedb41b7a7b081e34d
|
32
32
|
results = ([nil] * offset) + results
|
33
|
-
array = new results, :
|
33
|
+
array = new results, offset: offset, limit: options[:per_page], total_count: total_hits
|
34
34
|
end
|
35
35
|
array
|
36
36
|
end
|
data/lib/meilisearch/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/spec/utilities_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
2
2
|
|
3
|
-
MeiliSearch.configuration = { :
|
3
|
+
MeiliSearch.configuration = { meilisearch_host: ENV['MEILISEARCH_HOST'], meilisearch_api_key: ENV['MEILISEARCH_API_KEY'] }
|
4
4
|
|
5
5
|
describe MeiliSearch::Utilities do
|
6
6
|
|
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.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Meili
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-06-
|
11
|
+
date: 2021-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|