meilisearch-rails 0.6.0 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c0d3aeaf9f6e2549c11cdcd7cf5920fecb819fb1b2f03a25af11c19a5dd09444
4
- data.tar.gz: 0af07156e3e3ea69d492745f806751e2213ad7148553f57396528ad54fa3f02a
3
+ metadata.gz: affe6d35bf6c1c626570b32ae605e3b1e826c16c86e87d9ea4cc2e67cb4c1512
4
+ data.tar.gz: b950799c5e8296d5fcbc2e194480cbbc4fa5a60b704708db55859f7d0a6d8e4c
5
5
  SHA512:
6
- metadata.gz: a49c6d3b48de31033515e61c9fd182842d5d7d7ba90e140b6447339eeb6473139f3de4f1c3428f48a9176f3c36c5080ebc198897f4b53900f74e416bb817eaf1
7
- data.tar.gz: 63805d38ba88e0b020a0a147cce244ec35a0fb2a93715ff5b62df77ca87021b2b11581647626b2c76eaddc26ad15ab0a8e9d4e82c7e1895095829b7cce74965c
6
+ metadata.gz: 7a84a8fbbb00122c28c90c5573f1e5a93a3012a89f516ea35df68eba294aea20b7e169906400ad27b17d281359a2d3fb5933eda1338aecb2941e206b21b00002
7
+ data.tar.gz: c735267b627ef2100fc0cdd52bffa8d323d634b865c5ef5ba870d3839f8e2a0d03244e5478a056a26295fbd827c6ecbbd40a2994df8805fa194925add4c8533a
data/README.md CHANGED
@@ -30,6 +30,7 @@
30
30
  - [📖 Documentation](#-documentation)
31
31
  - [🤖 Compatibility with Meilisearch](#-compatibility-with-meilisearch)
32
32
  - [🚀 Getting Started](#-getting-started)
33
+ - [Compatibility](#-compatibility)
33
34
  - [⚙️ Settings](#️-settings)
34
35
  - [🔍 Custom search](#-custom-search)
35
36
  - [🪛 Options](#-options)
@@ -43,6 +44,7 @@
43
44
  - [Relations](#relations)
44
45
  - [Sanitize attributes](#sanitize-attributes)
45
46
  - [UTF-8 encoding](#utf-8-encoding)
47
+ - [Eager loading](#eager-loading)
46
48
  - [Manual operations](#manual-operations)
47
49
  - [Indexing & deletion](#indexing--deletion)
48
50
  - [Access the underlying index object](#access-the-underlying-index-object)
@@ -58,7 +60,7 @@ To learn more about Meilisearch, check out our [Documentation](https://docs.meil
58
60
 
59
61
  ## 🤖 Compatibility with Meilisearch
60
62
 
61
- This package only guarantees the compatibility with the [version v0.27.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.27.0).
63
+ This package only guarantees the compatibility with the [version v0.28.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.28.0).
62
64
 
63
65
  ## 🔧 Installation <!-- omit in toc -->
64
66
 
@@ -190,6 +192,10 @@ MeiliSearch::Rails.configuration = {
190
192
  }
191
193
  ```
192
194
 
195
+ ## Compatibility
196
+
197
+ If your model already has methods that meilisearch-rails defines such as `search` and `index`, they will not be redefined. You can target the meilisearch-rails-defined methods by prefixing with `ms_`, e.g. `Book.ms_search('harry potter')`.
198
+
193
199
  ## ⚙️ Settings
194
200
 
195
201
  You can configure the index settings by adding them inside the `meilisearch` block as shown below:
@@ -262,19 +268,7 @@ end
262
268
 
263
269
  #### Index UID according to the environment <!-- omit in toc -->
264
270
 
265
- You can suffix the index UID with the current Rails environment using one of the following options:
266
-
267
- By defining directly in your model:
268
-
269
- ```ruby
270
- class Book < ActiveRecord::Base
271
- include MeiliSearch::Rails
272
-
273
- meilisearch per_environment: true
274
- end
275
- ```
276
-
277
- Or setting it globally:
271
+ You can suffix the index UID with the current Rails environment by setting it globally:
278
272
 
279
273
  ```ruby
280
274
  MeiliSearch::Rails.configuration = {
@@ -284,7 +278,7 @@ MeiliSearch::Rails.configuration = {
284
278
  }
285
279
  ```
286
280
 
287
- Both options will make your index name look like this `"Book_#{Rails.env}"`.
281
+ This way your index UID will look like this `"Book_#{Rails.env}"`.
288
282
 
289
283
  ### Index configuration
290
284
 
@@ -324,15 +318,33 @@ end
324
318
 
325
319
  By default, the primary key is based on your record's id. You can change this behavior by specifying the `primary_key:` option.
326
320
 
327
- Note that the primary key must have a **unique value**.
321
+ Note that the primary key must return a **unique value** otherwise your data could be overwritten.
328
322
 
329
323
  ```ruby
330
324
  class Book < ActiveRecord::Base
331
325
  include MeiliSearch::Rails
332
326
 
333
- meilisearch primary_key: 'ISBN'
327
+ meilisearch primary_key: :isbn # isbn is a column in your table definition.
328
+ end
329
+ ```
330
+
331
+ You can also set the `primary_key` as a method, this method will be evaluated in runtime, and its return
332
+ will be used as the reference to the document when Meilisearch needs it.
333
+
334
+ ```rb
335
+ class Book < ActiveRecord::Base
336
+ include MeiliSearch::Rails
337
+
338
+ meilisearch primary_key: :my_custom_ms_id
339
+
340
+ private
341
+
342
+ def my_custom_ms_id
343
+ "isbn_#{primary_key}" # ensure this return is unique, otherwise you'll lose data.
344
+ end
334
345
  end
335
346
  ```
347
+
336
348
  #### Conditional indexing
337
349
 
338
350
  You can control if a record must be indexed by using the `if:` or `unless:` options.<br>
@@ -612,6 +624,20 @@ class Book < ActiveRecord::Base
612
624
  end
613
625
  ```
614
626
 
627
+ #### Eager loading
628
+
629
+ You can eager load associations using `meilisearch_import` scope.
630
+
631
+ ```ruby
632
+ class Author < ActiveRecord::Base
633
+ include MeiliSearch::Rails
634
+
635
+ has_many :books
636
+
637
+ scope :meilisearch_import, -> { includes(:books) }
638
+ end
639
+ ```
640
+
615
641
  ### Manual operations
616
642
 
617
643
  #### Indexing & deletion
@@ -16,6 +16,7 @@ module MeiliSearch
16
16
  configuration[:meilisearch_host] || 'http://localhost:7700',
17
17
  configuration[:meilisearch_api_key],
18
18
  configuration.slice(:timeout, :max_retries)
19
+ .merge(client_agents: MeiliSearch::Rails.qualified_version)
19
20
  )
20
21
  end
21
22
  end
@@ -2,6 +2,10 @@
2
2
 
3
3
  module MeiliSearch
4
4
  module Rails
5
- VERSION = '0.6.0'
5
+ VERSION = '0.7.2'
6
+
7
+ def self.qualified_version
8
+ "Meilisearch Rails (v#{VERSION})"
9
+ end
6
10
  end
7
11
  end
@@ -233,9 +233,13 @@ module MeiliSearch
233
233
  def initialize(index_uid, raise_on_failure, options)
234
234
  client = MeiliSearch::Rails.client
235
235
  primary_key = options[:primary_key] || MeiliSearch::Rails::IndexSettings::DEFAULT_PRIMARY_KEY
236
- client.create_index(index_uid, { primaryKey: primary_key })
237
- @index = client.index(index_uid)
238
236
  @raise_on_failure = raise_on_failure.nil? || raise_on_failure
237
+
238
+ SafeIndex.log_or_throw(nil, @raise_on_failure) do
239
+ client.create_index(index_uid, { primary_key: primary_key })
240
+ end
241
+
242
+ @index = client.index(index_uid)
239
243
  end
240
244
 
241
245
  ::MeiliSearch::Index.instance_methods(false).each do |m|
@@ -273,7 +277,7 @@ module MeiliSearch
273
277
 
274
278
  def self.log_or_throw(method, raise_on_failure, &block)
275
279
  yield
276
- rescue ::MeiliSearch::ApiError => e
280
+ rescue ::MeiliSearch::TimeoutError, ::MeiliSearch::ApiError => e
277
281
  raise e if raise_on_failure
278
282
 
279
283
  # log the error
@@ -282,7 +286,7 @@ module MeiliSearch
282
286
  case method.to_s
283
287
  when 'search'
284
288
  # some attributes are required
285
- { 'hits' => [], 'hitsPerPage' => 0, 'page' => 0, 'facetsDistribution' => {}, 'error' => e }
289
+ { 'hits' => [], 'hitsPerPage' => 0, 'page' => 0, 'facetDistribution' => {}, 'error' => e }
286
290
  else
287
291
  # empty answer
288
292
  { 'error' => e }
@@ -460,7 +464,7 @@ module MeiliSearch
460
464
  end
461
465
  last_task = index.add_documents(documents)
462
466
  end
463
- index.wait_for_task(last_task['uid']) if last_task && (synchronous || options[:synchronous])
467
+ index.wait_for_task(last_task['taskUid']) if last_task && (synchronous || options[:synchronous])
464
468
  end
465
469
  nil
466
470
  end
@@ -476,7 +480,7 @@ module MeiliSearch
476
480
 
477
481
  index = SafeIndex.new(ms_index_uid(options), true, options)
478
482
  task = index.update_settings(final_settings)
479
- index.wait_for_task(task['uid']) if synchronous
483
+ index.wait_for_task(task['taskUid']) if synchronous
480
484
  end
481
485
  end
482
486
 
@@ -486,7 +490,7 @@ module MeiliSearch
486
490
 
487
491
  index = ms_ensure_init(options, settings)
488
492
  task = index.add_documents(documents.map { |d| settings.get_attributes(d).merge ms_pk(options) => ms_primary_key_of(d, options) })
489
- index.wait_for_task(task['uid']) if synchronous || options[:synchronous]
493
+ index.wait_for_task(task['taskUid']) if synchronous || options[:synchronous]
490
494
  end
491
495
  end
492
496
 
@@ -583,7 +587,7 @@ module MeiliSearch
583
587
  end
584
588
 
585
589
  def ms_facets_distribution
586
- @ms_json['facetsDistribution']
590
+ @ms_json['facetDistribution']
587
591
  end
588
592
 
589
593
  private
@@ -595,23 +599,20 @@ module MeiliSearch
595
599
 
596
600
  def ms_search(query, params = {})
597
601
  if MeiliSearch::Rails.configuration[:pagination_backend]
598
-
599
602
  page = params[:page].nil? ? params[:page] : params[:page].to_i
600
603
  hits_per_page = params[:hitsPerPage].nil? ? params[:hitsPerPage] : params[:hitsPerPage].to_i
604
+ hits_per_page ||= params[:hits_per_page].nil? ? params[:hits_per_page] : params[:hits_per_page].to_i
605
+
606
+ %i[page hitsPerPage hits_per_page].each { |param| params.delete(param) }
601
607
 
602
- params.delete(:page)
603
- params.delete(:hitsPerPage)
604
608
  params[:limit] = 200
605
609
  end
606
610
 
607
611
  # Returns raw json hits as follows:
608
- # {"hits"=>[{"id"=>"13", "href"=>"apple", "name"=>"iphone"}], "offset"=>0, "limit"=>|| 20, "nbHits"=>1,
609
- # "exhaustiveNbHits"=>false, "processingTimeMs"=>0, "query"=>"iphone"}
612
+ # {"hits"=>[{"id"=>"13", "href"=>"apple", "name"=>"iphone"}], "offset"=>0, "limit"=>|| 20, "estimatedTotalHits"=>1,
613
+ # "processingTimeMs"=>0, "query"=>"iphone"}
610
614
  json = ms_raw_search(query, params)
611
615
 
612
- # Returns the ids of the hits: 13
613
- hit_ids = json['hits'].map { |hit| hit[ms_pk(meilisearch_options).to_s] }
614
-
615
616
  # condition_key gets the primary key of the document; looks for "id" on the options
616
617
  condition_key = if defined?(::Mongoid::Document) && include?(::Mongoid::Document)
617
618
  ms_primary_key_method.in
@@ -619,6 +620,23 @@ module MeiliSearch
619
620
  ms_primary_key_method
620
621
  end
621
622
 
623
+ # The condition_key must be a valid column otherwise, the `.where` below will not work
624
+ # Since we provide a way to customize the primary_key value, `ms_pk(meilisearch_options)` may not
625
+ # respond with a valid database column. The blocks below prevent that from happening.
626
+ has_virtual_column_as_pk = if defined?(::Sequel::Model) && self < Sequel::Model
627
+ meilisearch_options[:type].columns.map(&:to_s).exclude?(condition_key.to_s)
628
+ else
629
+ meilisearch_options[:type].columns.map(&:name).map(&:to_s).exclude?(condition_key.to_s)
630
+ end
631
+
632
+ condition_key = meilisearch_options[:type].primary_key if has_virtual_column_as_pk
633
+
634
+ hit_ids = if has_virtual_column_as_pk
635
+ json['hits'].map { |hit| hit[condition_key] }
636
+ else
637
+ json['hits'].map { |hit| hit[ms_pk(meilisearch_options).to_s] }
638
+ end
639
+
622
640
  # meilisearch_options[:type] refers to the Model name (e.g. Product)
623
641
  # results_by_id creates a hash with the primaryKey of the document (id) as the key and doc itself as the value
624
642
  # {"13"=>#<Product id: 13, name: "iphone", href: "apple", tags: nil, type: nil,
@@ -827,7 +845,8 @@ module MeiliSearch
827
845
 
828
846
  def ms_find_in_batches(batch_size, &block)
829
847
  if (defined?(::ActiveRecord) && ancestors.include?(::ActiveRecord::Base)) || respond_to?(:find_in_batches)
830
- find_in_batches(batch_size: batch_size, &block)
848
+ scope = respond_to?(:meilisearch_import) ? meilisearch_import : all
849
+ scope.find_in_batches(batch_size: batch_size, &block)
831
850
  elsif defined?(::Sequel::Model) && self < Sequel::Model
832
851
  dataset.extension(:pagination).each_page(batch_size, &block)
833
852
  else
@@ -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.18'
37
+ s.add_dependency 'meilisearch', '~> 0.19.2'
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.6.0
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Meili
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-29 00:00:00.000000000 Z
11
+ date: 2022-08-18 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.18'
19
+ version: 0.19.2
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.18'
26
+ version: 0.19.2
27
27
  description: Meilisearch integration for Ruby on Rails. See https://github.com/meilisearch/meilisearch
28
28
  email: bonjour@meilisearch.com
29
29
  executables: []