meilisearch-rails 0.10.1 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5533b797c2c1df4ba52eee7e73d68c81b8a329353b896d7e5d6b17560f2b9c6d
4
- data.tar.gz: c65d9fc11a89d2d054392b44c8858b59429e84fc707f569ba7d3888c4685c0df
3
+ metadata.gz: 215428bdb5e437c3a906e1246444dc7e2afce9d2b52646790de1d55d0490783f
4
+ data.tar.gz: 412f8d56c952a330a9b3473602aca9ac0fee6789a3a3632f65340c7c85524637
5
5
  SHA512:
6
- metadata.gz: f86c37174ef35dce271cc4dbd0ef51355828e9c1bb16c266b019883afc7fb1856f73b4d6dd61982c74e41c716122684d7307a31ee86d0015b3538bbc3c3f6616
7
- data.tar.gz: 88038b5cae1f6611e4793cf5051f03f88e9c01683bde793c38134340eb68126b38d3784b3e73bf7b79b07e0bbdf9d44d08c08938abee35b7a950728f6fc4c43b
6
+ metadata.gz: ad8f9e4489c11dd3b2a522b134921232fbe2b66946f57ebf6be0c18ccd0643490379fb483d0a2ecf3371a427ff442809801130308e8f11fdedc7d6869a8d14c5
7
+ data.tar.gz: 5473ca9c267a3dfada14258db095d86c2e3618d356afc29ecf60c6975b067078cac91d8cc84c3e0b0bf8b5f227496d95830d77ed41923d0deeb313165b0b37df
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021-2022 Meili SAS
3
+ Copyright (c) 2021-2024 Meili SAS
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -29,7 +29,7 @@
29
29
 
30
30
  **Meilisearch** is an open-source search engine. [Learn more about Meilisearch.](https://github.com/meilisearch/meilisearch)
31
31
 
32
- ## Table of Contents <!-- omit in toc -->
32
+ ## Table of Contents <!-- omit in TOC -->
33
33
 
34
34
  - [📖 Documentation](#-documentation)
35
35
  - [⚡ Supercharge your Meilisearch experience](#-supercharge-your-meilisearch-experience)
@@ -329,7 +329,7 @@ Check [`ddnexus/pagy`](https://ddnexus.github.io/pagy/extras/meilisearch) for mo
329
329
 
330
330
  #### Deactivate Meilisearch in certain moments
331
331
 
332
- 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>
332
+ By default, HTTP connections to the Meilisearch URL are always active, but sometimes you want to disable the HTTP requests in a particular moment or environment.<br>
333
333
  you have multiple ways to achieve this.
334
334
 
335
335
  By adding `active: false` in the configuration initializer:
@@ -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])
12
+ else
13
+ index.delete_document(document[:primary_key])
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -17,8 +17,8 @@ module MeiliSearch
17
17
  end
18
18
 
19
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`')
20
+ MeiliSearch::Rails.logger
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)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module MeiliSearch
4
4
  module Rails
5
- VERSION = '0.10.1'
5
+ VERSION = '0.11.0'
6
6
 
7
7
  def self.qualified_version
8
8
  "Meilisearch Rails (v#{VERSION})"
@@ -39,6 +39,10 @@ module MeiliSearch
39
39
  include InstanceMethods
40
40
  end
41
41
  end
42
+
43
+ def logger
44
+ @logger ||= (::Rails.logger || Logger.new($stdout))
45
+ end
42
46
  end
43
47
 
44
48
  class IndexSettings
@@ -245,6 +249,7 @@ module MeiliSearch
245
249
  # lazy load the ActiveJob class to ensure the
246
250
  # queue is initialized before using it
247
251
  autoload :MSJob, 'meilisearch/rails/ms_job'
252
+ autoload :MSCleanUpJob, 'meilisearch/rails/ms_clean_up_job'
248
253
  end
249
254
 
250
255
  # this class wraps an MeiliSearch::Index document ensuring all raised exceptions
@@ -256,7 +261,7 @@ module MeiliSearch
256
261
  @raise_on_failure = raise_on_failure.nil? || raise_on_failure
257
262
 
258
263
  SafeIndex.log_or_throw(nil, @raise_on_failure) do
259
- client.create_index(index_uid, { primary_key: primary_key })
264
+ client.create_index!(index_uid, { primary_key: primary_key })
260
265
  end
261
266
 
262
267
  @index = client.index(index_uid)
@@ -278,6 +283,15 @@ module MeiliSearch
278
283
  end
279
284
  end
280
285
 
286
+ # Maually define facet_search due to complications with **opts in ruby 2.*
287
+ def facet_search(*args, **opts)
288
+ SafeIndex.log_or_throw(:facet_search, @raise_on_failure) do
289
+ return MeiliSearch::Rails.black_hole unless MeiliSearch::Rails.active?
290
+
291
+ @index.facet_search(*args, **opts)
292
+ end
293
+ end
294
+
281
295
  # special handling of wait_for_task to handle null task_id
282
296
  def wait_for_task(task_uid)
283
297
  return if task_uid.nil? && !@raise_on_failure # ok
@@ -304,7 +318,7 @@ module MeiliSearch
304
318
  raise e if raise_on_failure
305
319
 
306
320
  # log the error
307
- (::Rails.logger || Logger.new($stdout)).info("[meilisearch-rails] #{e.message}")
321
+ MeiliSearch::Rails.logger.info("[meilisearch-rails] #{e.message}")
308
322
  # return something
309
323
  case method.to_s
310
324
  when 'search'
@@ -369,7 +383,11 @@ module MeiliSearch
369
383
 
370
384
  proc = if options[:enqueue] == true
371
385
  proc do |record, remove|
372
- MSJob.perform_later(record, remove ? 'ms_remove_from_index!' : 'ms_index!')
386
+ if remove
387
+ MSCleanUpJob.perform_later(record.ms_entries)
388
+ else
389
+ MSJob.perform_later(record, 'ms_index!')
390
+ end
373
391
  end
374
392
  elsif options[:enqueue].respond_to?(:call)
375
393
  options[:enqueue]
@@ -441,9 +459,11 @@ module MeiliSearch
441
459
  end
442
460
  end
443
461
  elsif respond_to?(:after_destroy)
444
- after_destroy { |searchable| searchable.ms_enqueue_remove_from_index!(ms_synchronous?) }
462
+ after_destroy_commit { |searchable| searchable.ms_enqueue_remove_from_index!(ms_synchronous?) }
445
463
  end
446
464
  end
465
+
466
+ warn_searchable_missing_attributes
447
467
  end
448
468
 
449
469
  def ms_without_auto_index(&block)
@@ -520,7 +540,8 @@ module MeiliSearch
520
540
  def ms_index!(document, synchronous = false)
521
541
  return if ms_without_auto_index_scope
522
542
 
523
- ms_configurations.each do |options, settings|
543
+ # MS tasks to be returned
544
+ ms_configurations.map do |options, settings|
524
545
  next if ms_indexing_disabled?(options)
525
546
 
526
547
  primary_key = ms_primary_key_of(document, options)
@@ -544,8 +565,20 @@ module MeiliSearch
544
565
  index.delete_document(primary_key)
545
566
  end
546
567
  end
568
+ end.compact
569
+ end
570
+
571
+ def ms_entries_for(document:, synchronous:)
572
+ primary_key = ms_primary_key_of(document)
573
+ raise ArgumentError, 'Cannot index a record without a primary key' if primary_key.blank?
574
+
575
+ ms_configurations.filter_map do |options, settings|
576
+ {
577
+ synchronous: synchronous || options[:synchronous],
578
+ index_uid: options[:index_uid],
579
+ primary_key: primary_key
580
+ }.with_indifferent_access unless ms_indexing_disabled?(options)
547
581
  end
548
- nil
549
582
  end
550
583
 
551
584
  def ms_remove_from_index!(document, synchronous = false)
@@ -729,33 +762,38 @@ module MeiliSearch
729
762
 
730
763
  protected
731
764
 
732
- def ms_ensure_init(options = nil, settings = nil, index_settings = nil)
765
+ def ms_ensure_init(options = meilisearch_options, settings = meilisearch_settings, user_configuration = settings.to_settings)
733
766
  raise ArgumentError, 'No `meilisearch` block found in your model.' if meilisearch_settings.nil?
734
767
 
735
768
  @ms_indexes ||= { true => {}, false => {} }
736
769
 
737
- options ||= meilisearch_options
738
- settings ||= meilisearch_settings
770
+ @ms_indexes[MeiliSearch::Rails.active?][settings] ||= SafeIndex.new(ms_index_uid(options), meilisearch_options[:raise_on_failure], meilisearch_options)
739
771
 
740
- return @ms_indexes[MeiliSearch::Rails.active?][settings] if @ms_indexes[MeiliSearch::Rails.active?][settings]
772
+ update_settings_if_changed(@ms_indexes[MeiliSearch::Rails.active?][settings], options, user_configuration)
741
773
 
742
- @ms_indexes[MeiliSearch::Rails.active?][settings] = SafeIndex.new(ms_index_uid(options), meilisearch_options[:raise_on_failure], meilisearch_options)
774
+ @ms_indexes[MeiliSearch::Rails.active?][settings]
775
+ end
743
776
 
744
- current_settings = @ms_indexes[MeiliSearch::Rails.active?][settings].settings(getVersion: 1) rescue nil # if the index doesn't exist
777
+ private
745
778
 
746
- index_settings ||= settings.to_settings
747
- index_settings = options[:primary_settings].to_settings.merge(index_settings) if options[:inherit]
779
+ def update_settings_if_changed(index, options, user_configuration)
780
+ server_state = index.settings
781
+ user_configuration = options[:primary_settings].to_settings.merge(user_configuration) if options[:inherit]
748
782
 
749
- options[:check_settings] = true if options[:check_settings].nil?
783
+ config = user_configuration.except(:attributes_to_highlight, :attributes_to_crop, :crop_length)
750
784
 
751
- if !ms_indexing_disabled?(options) && options[:check_settings] && meilisearch_settings_changed?(current_settings, index_settings)
752
- @ms_indexes[MeiliSearch::Rails.active?][settings].update_settings(index_settings)
785
+ if !skip_checking_settings?(options) && meilisearch_settings_changed?(server_state, config)
786
+ index.update_settings(user_configuration)
753
787
  end
788
+ end
754
789
 
755
- @ms_indexes[MeiliSearch::Rails.active?][settings]
790
+ def skip_checking_settings?(options)
791
+ ms_indexing_disabled?(options) || ms_checking_disabled?(options)
756
792
  end
757
793
 
758
- private
794
+ def ms_checking_disabled?(options)
795
+ options[:check_settings] == false
796
+ end
759
797
 
760
798
  def ms_configurations
761
799
  raise ArgumentError, 'No `meilisearch` block found in your model.' if meilisearch_settings.nil?
@@ -794,19 +832,22 @@ module MeiliSearch
794
832
  options[:primary_key] || MeiliSearch::Rails::IndexSettings::DEFAULT_PRIMARY_KEY
795
833
  end
796
834
 
797
- def meilisearch_settings_changed?(prev, current)
798
- return true if prev.nil?
835
+ def meilisearch_settings_changed?(server_state, user_configuration)
836
+ return true if server_state.nil?
837
+
838
+ user_configuration.transform_keys! { |key| key.to_s.camelize(:lower) }
799
839
 
800
- current.each do |k, v|
801
- prev_v = prev[k.to_s]
802
- if v.is_a?(Array) && prev_v.is_a?(Array)
803
- # compare array of strings, avoiding symbols VS strings comparison
804
- return true if v.map(&:to_s) != prev_v.map(&:to_s)
805
- elsif prev_v != v
806
- return true
840
+ user_configuration.any? do |key, user|
841
+ server = server_state[key]
842
+
843
+ if user.is_a?(Hash) && server.is_a?(Hash)
844
+ meilisearch_settings_changed?(server, user)
845
+ elsif user.is_a?(Array) && server.is_a?(Array)
846
+ user.map(&:to_s) != server.map(&:to_s)
847
+ else
848
+ user.to_s != server.to_s
807
849
  end
808
850
  end
809
- false
810
851
  end
811
852
 
812
853
  def ms_conditional_index?(options = nil)
@@ -858,6 +899,19 @@ module MeiliSearch
858
899
  # We don't know if the attribute has changed, so conservatively assume it has
859
900
  true
860
901
  end
902
+
903
+ def warn_searchable_missing_attributes
904
+ searchables = meilisearch_settings.get_setting(:searchable_attributes)
905
+ attrs = meilisearch_settings.get_setting(:attributes)&.keys
906
+
907
+ if searchables.present? && attrs.present?
908
+ (searchables.map(&:to_s) - attrs.map(&:to_s)).each do |missing_searchable|
909
+ MeiliSearch::Rails.logger.warn(
910
+ "[meilisearch-rails] #{name}##{missing_searchable} declared in searchable_attributes but not in attributes. Please add it to attributes if it should be searchable."
911
+ )
912
+ end
913
+ end
914
+ end
861
915
  end
862
916
 
863
917
  # these are the instance methods included
@@ -904,6 +958,10 @@ module MeiliSearch
904
958
  @ms_synchronous
905
959
  end
906
960
 
961
+ def ms_entries(synchronous = false)
962
+ self.class.ms_entries_for(document: self, synchronous: synchronous || ms_synchronous?)
963
+ end
964
+
907
965
  private
908
966
 
909
967
  def ms_mark_synchronous
@@ -34,5 +34,5 @@ Gem::Specification.new do |s|
34
34
 
35
35
  s.required_ruby_version = '>= 2.6.0'
36
36
 
37
- s.add_dependency 'meilisearch', '~> 0.25.0'
37
+ s.add_dependency 'meilisearch', '~> 0.26.0'
38
38
  end
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.10.1
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Meili
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-14 00:00:00.000000000 Z
11
+ date: 2024-02-12 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.25.0
19
+ version: 0.26.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.25.0
26
+ version: 0.26.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: []
@@ -40,6 +40,7 @@ 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
44
45
  - lib/meilisearch/rails/null_object.rb
45
46
  - lib/meilisearch/rails/pagination.rb
@@ -70,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
71
  - !ruby/object:Gem::Version
71
72
  version: '0'
72
73
  requirements: []
73
- rubygems_version: 3.0.3.1
74
+ rubygems_version: 3.1.6
74
75
  signing_key:
75
76
  specification_version: 4
76
77
  summary: Meilisearch integration for Ruby on Rails.