diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index cff25599..1684e7ba 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -94,7 +94,7 @@ Metrics/MethodLength: # Offense count: 1 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 437 + Max: 446 # Offense count: 8 # Configuration parameters: IgnoredMethods. diff --git a/Gemfile b/Gemfile index d0188678..dad4ab94 100644 --- a/Gemfile +++ b/Gemfile @@ -30,11 +30,11 @@ group :test do gem 'activerecord-jdbc-adapter', platform: :jruby gem 'activerecord-jdbcsqlite3-adapter', platform: :jruby gem 'jdbc-sqlite3', platform: :jruby + gem 'logger' gem 'rspec', '~> 3.0' gem 'simplecov', require: 'false' gem 'simplecov-cobertura', require: 'false' gem 'threads' - gem 'logger' gem 'byebug' gem 'dotenv', '~> 2.7', '>= 2.7.6' diff --git a/README.md b/README.md index 3558b540..3cdabb16 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,21 @@ end Check [`ddnexus/pagy`](https://ddnexus.github.io/pagy/extras/meilisearch) for more information. + +### Integer primary keys + +By default, meilisearch-rails will stringify primary keys before sending them to MeiliSearch. + +If you would like primary keys to remain as integers, set the `:stringify_primary_keys` to `false` in the configuration file: + +```ruby +MeiliSearch::Rails.configuration = { + meilisearch_url: 'YourMeilisearchUrl', + meilisearch_api_key: 'YourMeilisearchAPIKey', + stringify_primary_keys: false +} +``` + #### Deactivate Meilisearch in certain moments 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.
diff --git a/lib/meilisearch-rails.rb b/lib/meilisearch-rails.rb index a27b03a8..ed1751e5 100644 --- a/lib/meilisearch-rails.rb +++ b/lib/meilisearch-rails.rb @@ -711,7 +711,12 @@ def ms_search(query, params = {}) end results = json['hits'].map do |hit| - o = results_by_id[hit[ms_pk(meilisearch_options).to_s].to_s] + hit_id = if MeiliSearch::Rails.configuration[:stringify_primary_keys] + hit[ms_pk(meilisearch_options).to_s].to_s + else + hit[ms_pk(meilisearch_options).to_s] + end + o = results_by_id[hit_id] if o o.formatted = hit['_formatted'] o @@ -836,7 +841,11 @@ def ms_configurations end def ms_primary_key_of(doc, options = nil) - doc.send(ms_primary_key_method(options)).to_s + if MeiliSearch::Rails.configuration[:stringify_primary_keys] + doc.send(ms_primary_key_method(options)).to_s + else + doc.send(ms_primary_key_method(options)) + end end def ms_primary_key_changed?(doc, options = nil) diff --git a/lib/meilisearch/rails/configuration.rb b/lib/meilisearch/rails/configuration.rb index 6912b352..10acef42 100644 --- a/lib/meilisearch/rails/configuration.rb +++ b/lib/meilisearch/rails/configuration.rb @@ -2,13 +2,17 @@ module MeiliSearch module Rails module Configuration def configuration - raise NotConfigured if @_config.blank? + raise NotConfigured if @_config.blank? || @_config[:meilisearch_api_key].nil? @_config end def configuration=(configuration) @_config = configuration + + return if !@_config || !@_config[:stringify_primary_keys].nil? + + @_config[:stringify_primary_keys] = true end def deactivate! diff --git a/lib/meilisearch/rails/multi_search/result.rb b/lib/meilisearch/rails/multi_search/result.rb index e7938fcc..c6549917 100644 --- a/lib/meilisearch/rails/multi_search/result.rb +++ b/lib/meilisearch/rails/multi_search/result.rb @@ -59,15 +59,28 @@ def load_results(klass, result) if records.respond_to? :in_order_of records.in_order_of(condition_key, hits_by_id.keys).each do |record| - record.formatted = hits_by_id[record.send(condition_key).to_s]['_formatted'] + record_id = if MeiliSearch::Rails.configuration[:stringify_primary_keys] + record.send(condition_key).to_s + else + record.send(condition_key) + end + record.formatted = hits_by_id[record_id]['_formatted'] end else results_by_id = records.index_by do |hit| - hit.send(condition_key).to_s + if MeiliSearch::Rails.configuration[:stringify_primary_keys] + hit.send(condition_key).to_s + else + hit.send(condition_key) + end end result['hits'].filter_map do |hit| - record = results_by_id[hit[condition_key.to_s].to_s] + record = if MeiliSearch::Rails.configuration[:stringify_primary_keys] + results_by_id[hit[condition_key.to_s].to_s] + else + results_by_id[hit[condition_key]] + end record&.formatted = hit['_formatted'] record end diff --git a/spec/integration/active_record/primary_key_persistent_type_spec.rb b/spec/integration/active_record/primary_key_persistent_type_spec.rb new file mode 100644 index 00000000..ce09d723 --- /dev/null +++ b/spec/integration/active_record/primary_key_persistent_type_spec.rb @@ -0,0 +1,19 @@ +require 'support/models/color' +require 'support/models/book' + +describe 'When primary key is integer' do + it 'stays as integer in index' do + MeiliSearch::Rails.configuration[:stringify_primary_keys] = false + + TestUtil.reset_colors! + Color.create!(id: 1, name: 'purple', short_name: 'p') + Color.create!(id: 2, name: 'blue', short_name: 'b') + Color.create!(id: 10, name: 'yellow', short_name: 'l') + raw_search_results = Color.raw_search('*', sort: ['id:asc'])['hits'] + raw_search_result_ids = raw_search_results.map { |h| h['id'].to_i } + + expect(raw_search_result_ids).to eq [1, 2, 10] + + MeiliSearch::Rails.configuration[:stringify_primary_keys] = true + end +end diff --git a/spec/integration/active_record/record_is_updated_spec.rb b/spec/integration/active_record/record_is_updated_spec.rb index ffbed0bc..44939d0e 100644 --- a/spec/integration/active_record/record_is_updated_spec.rb +++ b/spec/integration/active_record/record_is_updated_spec.rb @@ -3,6 +3,7 @@ describe 'When record is updated' do it 'updates the changed attributes on the index' do + TestUtil.reset_colors! purple = Color.create!(name: 'purple', short_name: 'p') expect(Color.search('purple')).to be_one expect(Color.search('pink')).to be_empty diff --git a/spec/support/models/color.rb b/spec/support/models/color.rb index c242fed7..ecb77f42 100644 --- a/spec/support/models/color.rb +++ b/spec/support/models/color.rb @@ -13,7 +13,7 @@ class Color < ActiveRecord::Base meilisearch synchronous: true, index_uid: safe_index_uid('Color') do searchable_attributes [:name] filterable_attributes ['short_name'] - sortable_attributes [:name] + sortable_attributes %i[id name] ranking_rules [ 'words', 'typo',