meilisearch-rails 0.10.2 → 0.14.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +56 -2
- data/lib/meilisearch/rails/ms_clean_up_job.rb +19 -0
- data/lib/meilisearch/rails/multi_search/result.rb +84 -0
- data/lib/meilisearch/rails/multi_search.rb +49 -0
- data/lib/meilisearch/rails/pagination.rb +1 -1
- data/lib/meilisearch/rails/utilities.rb +8 -0
- data/lib/meilisearch/rails/version.rb +1 -1
- data/lib/meilisearch-rails.rb +94 -52
- data/meilisearch-rails.gemspec +2 -2
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24559c8e70fcdaef7392de52e689ed37427c1e87a8981e693f123c8b7348d75a
|
4
|
+
data.tar.gz: 415f7739643c82925fa54dc3b6a3d2dcf182d66969010fc84d3cf64a9444fc37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce2015617e15a63f5d9fa39686b92272e83fb70c8ae66144847aa712ac51341ff1f56073006936fb568996105ee45142cedccfb5123befd79a033312efd37173
|
7
|
+
data.tar.gz: a906f6cc4bb10f6de8c38e19ab4225ffc7a1009517dedf0849972af3a6df50d6518371e66660477a8eb92291266bfea23e5ae135ebc3ca6f611e9e17828a4429
|
data/.rspec
CHANGED
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -38,6 +38,7 @@
|
|
38
38
|
- [Compatibility](#-compatibility)
|
39
39
|
- [⚙️ Settings](#️-settings)
|
40
40
|
- [🔍 Custom search](#-custom-search)
|
41
|
+
- [🔍🔍 Multi search](#-multi-search)
|
41
42
|
- [🪛 Options](#-options)
|
42
43
|
- [Meilisearch configuration & environment](#meilisearch-configuration--environment)
|
43
44
|
- [Pagination with `kaminari` or `will_paginate`](#backend-pagination-with-kaminari-or-will_paginate-)
|
@@ -75,7 +76,7 @@ This package guarantees compatibility with [version v1.x of Meilisearch](https:/
|
|
75
76
|
|
76
77
|
## 🔧 Installation <!-- omit in toc -->
|
77
78
|
|
78
|
-
This package requires Ruby version
|
79
|
+
This package requires Ruby version 3.0 or later and Rails 6.1 or later. It may work in older versions but it is not officially supported.
|
79
80
|
|
80
81
|
With `gem` in command line:
|
81
82
|
```bash
|
@@ -206,6 +207,7 @@ class Book < ApplicationRecord
|
|
206
207
|
crop_length 10
|
207
208
|
faceting max_values_per_facet: 2000
|
208
209
|
pagination max_total_hits: 1000
|
210
|
+
proximity_precision 'byWord'
|
209
211
|
end
|
210
212
|
end
|
211
213
|
```
|
@@ -229,7 +231,7 @@ harry_book.formatted # => {"id"=>"1", "name"=>"<em>Harry</em> Potter", "descript
|
|
229
231
|
👉 Don't forget that `attributes_to_highlight`, `attributes_to_crop`, and
|
230
232
|
`crop_length` can be set up in the `meilisearch` block of your model.
|
231
233
|
|
232
|
-
|
234
|
+
### 🔍 Sorted search
|
233
235
|
|
234
236
|
As an example of how to use the sort option, here is how you could achieve
|
235
237
|
returning all books sorted by title in ascending order:
|
@@ -240,6 +242,58 @@ Book.search('*', sort: ['title:asc'])
|
|
240
242
|
|
241
243
|
👉 Don't forget to set up the `sortable_attributes` option in the `meilisearch` block of your model.
|
242
244
|
|
245
|
+
## 🔍🔍 Multi search
|
246
|
+
|
247
|
+
Meilisearch supports searching multiple models at the same time (see [🔍 Custom search](#-custom-search) for search options):
|
248
|
+
|
249
|
+
```ruby
|
250
|
+
multi_search_results = MeiliSearch::Rails.multi_search(
|
251
|
+
Book => { q: 'Harry' },
|
252
|
+
Manga => { q: 'Attack' }
|
253
|
+
)
|
254
|
+
```
|
255
|
+
|
256
|
+
You can iterate through the results with `.each` or `.each_result`:
|
257
|
+
|
258
|
+
```erb
|
259
|
+
<% multi_search_results.each do |record| %>
|
260
|
+
<p><%= record.title %></p>
|
261
|
+
<p><%= record.author %></p>
|
262
|
+
<% end %>
|
263
|
+
|
264
|
+
<p>Harry Potter and the Philosopher's Stone</p>
|
265
|
+
<p>J. K. Rowling</p>
|
266
|
+
<p>Harry Potter and the Chamber of Secrets</p>
|
267
|
+
<p>J. K. Rowling</p>
|
268
|
+
<p>Attack on Titan</p>
|
269
|
+
<p>Iseyama</p>
|
270
|
+
```
|
271
|
+
|
272
|
+
```erb
|
273
|
+
<% multi_search_results.each_result do |klass, results| %>
|
274
|
+
<p><%= klass.name.pluralize %></p>
|
275
|
+
|
276
|
+
<ul>
|
277
|
+
<% results.each do |record| %>
|
278
|
+
<li><%= record.title %></li>
|
279
|
+
<% end %>
|
280
|
+
</ul>
|
281
|
+
<% end %>
|
282
|
+
|
283
|
+
|
284
|
+
<p>Books</p>
|
285
|
+
<ul>
|
286
|
+
<li>Harry Potter and the Philosopher's Stone</li>
|
287
|
+
<li>Harry Potter and the Chamber of Secrets</li>
|
288
|
+
</ul>
|
289
|
+
<p>Mangas</p>
|
290
|
+
<ul>
|
291
|
+
<li>Attack on Titan</li>
|
292
|
+
</ul>
|
293
|
+
```
|
294
|
+
|
295
|
+
See the [official multi search documentation](https://www.meilisearch.com/docs/reference/api/multi_search).
|
296
|
+
|
243
297
|
## 🪛 Options
|
244
298
|
|
245
299
|
### Meilisearch configuration & environment
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MeiliSearch
|
2
|
+
module Rails
|
3
|
+
class MSCleanUpJob < ::ActiveJob::Base
|
4
|
+
queue_as :meilisearch
|
5
|
+
|
6
|
+
def perform(documents)
|
7
|
+
documents.each do |document|
|
8
|
+
index = MeiliSearch::Rails.client.index(document[:index_uid])
|
9
|
+
|
10
|
+
if document[:synchronous]
|
11
|
+
index.delete_document(document[:primary_key]).await
|
12
|
+
else
|
13
|
+
index.delete_document(document[:primary_key])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module MeiliSearch
|
2
|
+
module Rails
|
3
|
+
class MultiSearchResult
|
4
|
+
attr_reader :metadata
|
5
|
+
|
6
|
+
def initialize(searches, raw_results)
|
7
|
+
@results = {}
|
8
|
+
@metadata = {}
|
9
|
+
|
10
|
+
searches.zip(raw_results['results']).each do |(index_target, search_options), result|
|
11
|
+
index_target = search_options[:class_name].constantize if search_options[:class_name]
|
12
|
+
|
13
|
+
@results[index_target] = case index_target
|
14
|
+
when String, Symbol
|
15
|
+
result['hits']
|
16
|
+
else
|
17
|
+
load_results(index_target, result)
|
18
|
+
end
|
19
|
+
|
20
|
+
@metadata[index_target] = result.except('hits')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
include Enumerable
|
25
|
+
|
26
|
+
def each_hit(&block)
|
27
|
+
@results.each do |_index_target, results|
|
28
|
+
results.each(&block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
alias each each_hit
|
32
|
+
|
33
|
+
def each_result(&block)
|
34
|
+
@results.each(&block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_a
|
38
|
+
@results.values.flatten(1)
|
39
|
+
end
|
40
|
+
alias to_ary to_a
|
41
|
+
|
42
|
+
def to_h
|
43
|
+
@results
|
44
|
+
end
|
45
|
+
alias to_hash to_h
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def load_results(klass, result)
|
50
|
+
pk_method = klass.ms_primary_key_method
|
51
|
+
pk_method = pk_method.in if Utilities.mongo_model?(klass)
|
52
|
+
|
53
|
+
condition_key = pk_is_virtual?(klass, pk_method) ? klass.primary_key : pk_method
|
54
|
+
|
55
|
+
hits_by_id =
|
56
|
+
result['hits'].index_by { |hit| hit[condition_key.to_s] }
|
57
|
+
|
58
|
+
records = klass.where(condition_key => hits_by_id.keys)
|
59
|
+
|
60
|
+
if records.respond_to? :in_order_of
|
61
|
+
records.in_order_of(condition_key, hits_by_id.keys).each do |record|
|
62
|
+
record.formatted = hits_by_id[record.send(condition_key).to_s]['_formatted']
|
63
|
+
end
|
64
|
+
else
|
65
|
+
results_by_id = records.index_by do |hit|
|
66
|
+
hit.send(condition_key).to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
result['hits'].filter_map do |hit|
|
70
|
+
record = results_by_id[hit[condition_key.to_s].to_s]
|
71
|
+
record&.formatted = hit['_formatted']
|
72
|
+
record
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def pk_is_virtual?(model_class, pk_method)
|
78
|
+
model_class.columns
|
79
|
+
.map(&(Utilities.sequel_model?(model_class) ? :to_s : :name))
|
80
|
+
.exclude?(pk_method.to_s)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'multi_search/result'
|
2
|
+
|
3
|
+
module MeiliSearch
|
4
|
+
module Rails
|
5
|
+
class << self
|
6
|
+
def multi_search(searches)
|
7
|
+
search_parameters = searches.map do |(index_target, options)|
|
8
|
+
paginate(options) if pagination_enabled?
|
9
|
+
normalize(options, index_target)
|
10
|
+
end
|
11
|
+
|
12
|
+
MultiSearchResult.new(searches, client.multi_search(search_parameters))
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def normalize(options, index_target)
|
18
|
+
options
|
19
|
+
.except(:class_name)
|
20
|
+
.merge!(index_uid: index_uid_from_target(index_target))
|
21
|
+
end
|
22
|
+
|
23
|
+
def index_uid_from_target(index_target)
|
24
|
+
case index_target
|
25
|
+
when String, Symbol
|
26
|
+
index_target
|
27
|
+
else
|
28
|
+
index_target.index.uid
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def paginate(options)
|
33
|
+
%w[page hitsPerPage hits_per_page].each do |key|
|
34
|
+
# Deletes hitsPerPage to avoid passing along a meilisearch-ruby warning/exception
|
35
|
+
value = options.delete(key) || options.delete(key.to_sym)
|
36
|
+
options[key.underscore.to_sym] = value.to_i if value
|
37
|
+
end
|
38
|
+
|
39
|
+
# It is required to activate the finite pagination in Meilisearch v0.30 (or newer),
|
40
|
+
# to have at least `hits_per_page` defined or `page` in the search request.
|
41
|
+
options[:page] ||= 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def pagination_enabled?
|
45
|
+
MeiliSearch::Rails.configuration[:pagination_backend]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -18,7 +18,7 @@ module MeiliSearch
|
|
18
18
|
|
19
19
|
def self.log_pagy_error
|
20
20
|
MeiliSearch::Rails.logger
|
21
|
-
.
|
21
|
+
.warn('[meilisearch-rails] Remove `pagination_backend: :pagy` from your initializer, `pagy` it is not required for `pagy`')
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.load_pagination!(pagination_backend, results, total_hits, options)
|
@@ -48,6 +48,14 @@ module MeiliSearch
|
|
48
48
|
true
|
49
49
|
end
|
50
50
|
|
51
|
+
def mongo_model?(model_class)
|
52
|
+
defined?(::Mongoid::Document) && model_class.include?(::Mongoid::Document)
|
53
|
+
end
|
54
|
+
|
55
|
+
def sequel_model?(model_class)
|
56
|
+
defined?(::Sequel::Model) && model_class < Sequel::Model
|
57
|
+
end
|
58
|
+
|
51
59
|
private
|
52
60
|
|
53
61
|
def constraint_passes?(record, constraint)
|
data/lib/meilisearch-rails.rb
CHANGED
@@ -3,6 +3,7 @@ require 'meilisearch/rails/null_object'
|
|
3
3
|
require 'meilisearch/rails/version'
|
4
4
|
require 'meilisearch/rails/utilities'
|
5
5
|
require 'meilisearch/rails/errors'
|
6
|
+
require 'meilisearch/rails/multi_search'
|
6
7
|
|
7
8
|
if defined? Rails
|
8
9
|
begin
|
@@ -66,6 +67,7 @@ module MeiliSearch
|
|
66
67
|
pagination
|
67
68
|
faceting
|
68
69
|
typo_tolerance
|
70
|
+
proximity_precision
|
69
71
|
].freeze
|
70
72
|
|
71
73
|
CAMELIZE_OPTIONS = %i[pagination faceting typo_tolerance].freeze
|
@@ -82,6 +84,22 @@ module MeiliSearch
|
|
82
84
|
def initialize(options, &block)
|
83
85
|
@options = options
|
84
86
|
instance_exec(&block) if block_given?
|
87
|
+
warn_searchable_missing_attributes
|
88
|
+
end
|
89
|
+
|
90
|
+
def warn_searchable_missing_attributes
|
91
|
+
searchables = get_setting(:searchable_attributes)&.map { |searchable| searchable.to_s.split('.').first }
|
92
|
+
attrs = get_setting(:attributes)&.map { |k, _| k.to_s }
|
93
|
+
|
94
|
+
if searchables.present? && attrs.present?
|
95
|
+
(searchables - attrs).each do |missing_searchable|
|
96
|
+
warning = <<~WARNING
|
97
|
+
[meilisearch-rails] #{missing_searchable} declared in searchable_attributes but not in attributes. \
|
98
|
+
Please add it to attributes if it should be searchable.
|
99
|
+
WARNING
|
100
|
+
MeiliSearch::Rails.logger.warn(warning)
|
101
|
+
end
|
102
|
+
end
|
85
103
|
end
|
86
104
|
|
87
105
|
def use_serializer(serializer)
|
@@ -249,6 +267,7 @@ module MeiliSearch
|
|
249
267
|
# lazy load the ActiveJob class to ensure the
|
250
268
|
# queue is initialized before using it
|
251
269
|
autoload :MSJob, 'meilisearch/rails/ms_job'
|
270
|
+
autoload :MSCleanUpJob, 'meilisearch/rails/ms_clean_up_job'
|
252
271
|
end
|
253
272
|
|
254
273
|
# this class wraps an MeiliSearch::Index document ensuring all raised exceptions
|
@@ -282,6 +301,15 @@ module MeiliSearch
|
|
282
301
|
end
|
283
302
|
end
|
284
303
|
|
304
|
+
# Maually define facet_search due to complications with **opts in ruby 2.*
|
305
|
+
def facet_search(*args, **opts)
|
306
|
+
SafeIndex.log_or_throw(:facet_search, @raise_on_failure) do
|
307
|
+
return MeiliSearch::Rails.black_hole unless MeiliSearch::Rails.active?
|
308
|
+
|
309
|
+
@index.facet_search(*args, **opts)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
285
313
|
# special handling of wait_for_task to handle null task_id
|
286
314
|
def wait_for_task(task_uid)
|
287
315
|
return if task_uid.nil? && !@raise_on_failure # ok
|
@@ -296,7 +324,7 @@ module MeiliSearch
|
|
296
324
|
SafeIndex.log_or_throw(:settings, @raise_on_failure) do
|
297
325
|
@index.settings(*args)
|
298
326
|
rescue ::MeiliSearch::ApiError => e
|
299
|
-
return {} if e.code ==
|
327
|
+
return {} if e.code == 'index_not_found' # not fatal
|
300
328
|
|
301
329
|
raise e
|
302
330
|
end
|
@@ -373,7 +401,11 @@ module MeiliSearch
|
|
373
401
|
|
374
402
|
proc = if options[:enqueue] == true
|
375
403
|
proc do |record, remove|
|
376
|
-
|
404
|
+
if remove
|
405
|
+
MSCleanUpJob.perform_later(record.ms_entries)
|
406
|
+
else
|
407
|
+
MSJob.perform_later(record, 'ms_index!')
|
408
|
+
end
|
377
409
|
end
|
378
410
|
elsif options[:enqueue].respond_to?(:call)
|
379
411
|
options[:enqueue]
|
@@ -445,11 +477,9 @@ module MeiliSearch
|
|
445
477
|
end
|
446
478
|
end
|
447
479
|
elsif respond_to?(:after_destroy)
|
448
|
-
|
480
|
+
after_destroy_commit { |searchable| searchable.ms_enqueue_remove_from_index!(ms_synchronous?) }
|
449
481
|
end
|
450
482
|
end
|
451
|
-
|
452
|
-
warn_searchable_missing_attributes
|
453
483
|
end
|
454
484
|
|
455
485
|
def ms_without_auto_index(&block)
|
@@ -526,7 +556,8 @@ module MeiliSearch
|
|
526
556
|
def ms_index!(document, synchronous = false)
|
527
557
|
return if ms_without_auto_index_scope
|
528
558
|
|
529
|
-
|
559
|
+
# MS tasks to be returned
|
560
|
+
ms_configurations.map do |options, settings|
|
530
561
|
next if ms_indexing_disabled?(options)
|
531
562
|
|
532
563
|
primary_key = ms_primary_key_of(document, options)
|
@@ -538,20 +569,32 @@ module MeiliSearch
|
|
538
569
|
doc = doc.merge ms_pk(options) => primary_key
|
539
570
|
|
540
571
|
if synchronous || options[:synchronous]
|
541
|
-
index.add_documents
|
572
|
+
index.add_documents(doc).await
|
542
573
|
else
|
543
574
|
index.add_documents(doc)
|
544
575
|
end
|
545
576
|
elsif ms_conditional_index?(options) && primary_key.present?
|
546
577
|
# remove non-indexable documents
|
547
578
|
if synchronous || options[:synchronous]
|
548
|
-
index.delete_document
|
579
|
+
index.delete_document(primary_key).await
|
549
580
|
else
|
550
581
|
index.delete_document(primary_key)
|
551
582
|
end
|
552
583
|
end
|
584
|
+
end.compact
|
585
|
+
end
|
586
|
+
|
587
|
+
def ms_entries_for(document:, synchronous:)
|
588
|
+
primary_key = ms_primary_key_of(document)
|
589
|
+
raise ArgumentError, 'Cannot index a record without a primary key' if primary_key.blank?
|
590
|
+
|
591
|
+
ms_configurations.filter_map do |options, settings|
|
592
|
+
{
|
593
|
+
synchronous: synchronous || options[:synchronous],
|
594
|
+
index_uid: ms_index_uid(options),
|
595
|
+
primary_key: primary_key
|
596
|
+
}.with_indifferent_access unless ms_indexing_disabled?(options)
|
553
597
|
end
|
554
|
-
nil
|
555
598
|
end
|
556
599
|
|
557
600
|
def ms_remove_from_index!(document, synchronous = false)
|
@@ -565,7 +608,7 @@ module MeiliSearch
|
|
565
608
|
|
566
609
|
index = ms_ensure_init(options, settings)
|
567
610
|
if synchronous || options[:synchronous]
|
568
|
-
index.delete_document
|
611
|
+
index.delete_document(primary_key).await
|
569
612
|
else
|
570
613
|
index.delete_document(primary_key)
|
571
614
|
end
|
@@ -578,7 +621,7 @@ module MeiliSearch
|
|
578
621
|
next if ms_indexing_disabled?(options)
|
579
622
|
|
580
623
|
index = ms_ensure_init(options, settings)
|
581
|
-
synchronous || options[:synchronous] ? index.delete_all_documents
|
624
|
+
synchronous || options[:synchronous] ? index.delete_all_documents.await : index.delete_all_documents
|
582
625
|
@ms_indexes[MeiliSearch::Rails.active?][settings] = nil
|
583
626
|
end
|
584
627
|
nil
|
@@ -733,35 +776,45 @@ module MeiliSearch
|
|
733
776
|
false
|
734
777
|
end
|
735
778
|
|
779
|
+
def ms_primary_key_method(options = nil)
|
780
|
+
options ||= meilisearch_options
|
781
|
+
options[:primary_key] || options[:id] || :id
|
782
|
+
end
|
783
|
+
|
736
784
|
protected
|
737
785
|
|
738
|
-
def ms_ensure_init(options =
|
786
|
+
def ms_ensure_init(options = meilisearch_options, settings = meilisearch_settings, user_configuration = settings.to_settings)
|
739
787
|
raise ArgumentError, 'No `meilisearch` block found in your model.' if meilisearch_settings.nil?
|
740
788
|
|
741
789
|
@ms_indexes ||= { true => {}, false => {} }
|
742
790
|
|
743
|
-
|
744
|
-
settings ||= meilisearch_settings
|
791
|
+
@ms_indexes[MeiliSearch::Rails.active?][settings] ||= SafeIndex.new(ms_index_uid(options), meilisearch_options[:raise_on_failure], meilisearch_options)
|
745
792
|
|
746
|
-
|
793
|
+
update_settings_if_changed(@ms_indexes[MeiliSearch::Rails.active?][settings], options, user_configuration)
|
747
794
|
|
748
|
-
@ms_indexes[MeiliSearch::Rails.active?][settings]
|
795
|
+
@ms_indexes[MeiliSearch::Rails.active?][settings]
|
796
|
+
end
|
749
797
|
|
750
|
-
|
798
|
+
private
|
751
799
|
|
752
|
-
|
753
|
-
|
800
|
+
def update_settings_if_changed(index, options, user_configuration)
|
801
|
+
server_state = index.settings
|
802
|
+
user_configuration = options[:primary_settings].to_settings.merge(user_configuration) if options[:inherit]
|
754
803
|
|
755
|
-
|
804
|
+
config = user_configuration.except(:attributes_to_highlight, :attributes_to_crop, :crop_length)
|
756
805
|
|
757
|
-
if !
|
758
|
-
|
806
|
+
if !skip_checking_settings?(options) && meilisearch_settings_changed?(server_state, config)
|
807
|
+
index.update_settings(user_configuration)
|
759
808
|
end
|
809
|
+
end
|
760
810
|
|
761
|
-
|
811
|
+
def skip_checking_settings?(options)
|
812
|
+
ms_indexing_disabled?(options) || ms_checking_disabled?(options)
|
762
813
|
end
|
763
814
|
|
764
|
-
|
815
|
+
def ms_checking_disabled?(options)
|
816
|
+
options[:check_settings] == false
|
817
|
+
end
|
765
818
|
|
766
819
|
def ms_configurations
|
767
820
|
raise ArgumentError, 'No `meilisearch` block found in your model.' if meilisearch_settings.nil?
|
@@ -782,11 +835,6 @@ module MeiliSearch
|
|
782
835
|
@configurations
|
783
836
|
end
|
784
837
|
|
785
|
-
def ms_primary_key_method(options = nil)
|
786
|
-
options ||= meilisearch_options
|
787
|
-
options[:primary_key] || options[:id] || :id
|
788
|
-
end
|
789
|
-
|
790
838
|
def ms_primary_key_of(doc, options = nil)
|
791
839
|
doc.send(ms_primary_key_method(options)).to_s
|
792
840
|
end
|
@@ -800,19 +848,22 @@ module MeiliSearch
|
|
800
848
|
options[:primary_key] || MeiliSearch::Rails::IndexSettings::DEFAULT_PRIMARY_KEY
|
801
849
|
end
|
802
850
|
|
803
|
-
def meilisearch_settings_changed?(
|
804
|
-
return true if
|
851
|
+
def meilisearch_settings_changed?(server_state, user_configuration)
|
852
|
+
return true if server_state.nil?
|
805
853
|
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
854
|
+
user_configuration.transform_keys! { |key| key.to_s.camelize(:lower) }
|
855
|
+
|
856
|
+
user_configuration.any? do |key, user|
|
857
|
+
server = server_state[key]
|
858
|
+
|
859
|
+
if user.is_a?(Hash) && server.is_a?(Hash)
|
860
|
+
meilisearch_settings_changed?(server, user)
|
861
|
+
elsif user.is_a?(Array) && server.is_a?(Array)
|
862
|
+
user.map(&:to_s).sort! != server.map(&:to_s).sort!
|
863
|
+
else
|
864
|
+
user.to_s != server.to_s
|
813
865
|
end
|
814
866
|
end
|
815
|
-
false
|
816
867
|
end
|
817
868
|
|
818
869
|
def ms_conditional_index?(options = nil)
|
@@ -864,19 +915,6 @@ module MeiliSearch
|
|
864
915
|
# We don't know if the attribute has changed, so conservatively assume it has
|
865
916
|
true
|
866
917
|
end
|
867
|
-
|
868
|
-
def warn_searchable_missing_attributes
|
869
|
-
searchables = meilisearch_settings.get_setting(:searchable_attributes)
|
870
|
-
attrs = meilisearch_settings.get_setting(:attributes)&.keys
|
871
|
-
|
872
|
-
if searchables.present? && attrs.present?
|
873
|
-
(searchables.map(&:to_s) - attrs.map(&:to_s)).each do |missing_searchable|
|
874
|
-
MeiliSearch::Rails.logger.warn(
|
875
|
-
"[meilisearch-rails] #{name}##{missing_searchable} declared in searchable_attributes but not in attributes. Please add it to attributes if it should be searchable."
|
876
|
-
)
|
877
|
-
end
|
878
|
-
end
|
879
|
-
end
|
880
918
|
end
|
881
919
|
|
882
920
|
# these are the instance methods included
|
@@ -923,6 +961,10 @@ module MeiliSearch
|
|
923
961
|
@ms_synchronous
|
924
962
|
end
|
925
963
|
|
964
|
+
def ms_entries(synchronous = false)
|
965
|
+
self.class.ms_entries_for(document: self, synchronous: synchronous || ms_synchronous?)
|
966
|
+
end
|
967
|
+
|
926
968
|
private
|
927
969
|
|
928
970
|
def ms_mark_synchronous
|
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.14.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Meili
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-09-25 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.28'
|
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.28'
|
27
27
|
description: Meilisearch integration for Ruby on Rails. See https://github.com/meilisearch/meilisearch
|
28
28
|
email: bonjour@meilisearch.com
|
29
29
|
executables: []
|
@@ -40,7 +40,10 @@ files:
|
|
40
40
|
- lib/meilisearch-rails.rb
|
41
41
|
- lib/meilisearch/rails/configuration.rb
|
42
42
|
- lib/meilisearch/rails/errors.rb
|
43
|
+
- lib/meilisearch/rails/ms_clean_up_job.rb
|
43
44
|
- lib/meilisearch/rails/ms_job.rb
|
45
|
+
- lib/meilisearch/rails/multi_search.rb
|
46
|
+
- lib/meilisearch/rails/multi_search/result.rb
|
44
47
|
- lib/meilisearch/rails/null_object.rb
|
45
48
|
- lib/meilisearch/rails/pagination.rb
|
46
49
|
- lib/meilisearch/rails/pagination/kaminari.rb
|
@@ -63,14 +66,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
66
|
requirements:
|
64
67
|
- - ">="
|
65
68
|
- !ruby/object:Gem::Version
|
66
|
-
version:
|
69
|
+
version: 3.0.0
|
67
70
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
71
|
requirements:
|
69
72
|
- - ">="
|
70
73
|
- !ruby/object:Gem::Version
|
71
74
|
version: '0'
|
72
75
|
requirements: []
|
73
|
-
rubygems_version: 3.
|
76
|
+
rubygems_version: 3.4.19
|
74
77
|
signing_key:
|
75
78
|
specification_version: 4
|
76
79
|
summary: Meilisearch integration for Ruby on Rails.
|