From 36c3eb1b64146725d36750494e6d37fdbf705aaf Mon Sep 17 00:00:00 2001 From: Thiago Colares Date: Fri, 10 Oct 2025 12:07:09 -0400 Subject: [PATCH 1/3] Set primary_key in meilisearch_options during initial meilisearch load - Use the model's #primary_key or nil. - Rails' Active Record defaults #primary_key to "id". --- lib/meilisearch-rails.rb | 15 +++++++++++---- spec/options_spec.rb | 15 ++++++++++++++- spec/support/models/story.rb | 21 +++++++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 spec/support/models/story.rb diff --git a/lib/meilisearch-rails.rb b/lib/meilisearch-rails.rb index 3fb47b7..f481789 100644 --- a/lib/meilisearch-rails.rb +++ b/lib/meilisearch-rails.rb @@ -377,10 +377,7 @@ class << base def meilisearch(options = {}, &block) self.meilisearch_settings = IndexSettings.new(options, &block) - self.meilisearch_options = { - type: model_name.to_s.constantize, - per_page: meilisearch_settings.get_setting(:hitsPerPage) || 20, page: 1 - }.merge(options) + self.meilisearch_options = default_meilisearch_options(meilisearch_settings, options) attr_accessor :formatted @@ -805,6 +802,16 @@ def ms_ensure_init(options = meilisearch_options, settings = meilisearch_setting private + def default_meilisearch_options(meilisearch_settings, options) + type = model_name.to_s.constantize + { + type: type, + per_page: meilisearch_settings.get_setting(:hitsPerPage) || 20, + page: 1, + primary_key: type.respond_to?(:primary_key) ? type.primary_key : nil + }.merge(options) + end + def update_settings_if_changed(index, options, user_configuration) server_state = index.settings user_configuration = options[:primary_settings].to_settings.merge(user_configuration) if options[:inherit] diff --git a/spec/options_spec.rb b/spec/options_spec.rb index 7e2273c..609b225 100644 --- a/spec/options_spec.rb +++ b/spec/options_spec.rb @@ -5,6 +5,7 @@ require 'support/models/people' require 'support/models/vegetable' require 'support/models/fruit' +require 'support/models/story' require 'support/models/disabled_models' require 'support/models/queued_models' @@ -18,11 +19,23 @@ end describe ':primary_key' do - it 'sets the primary key specified' do + it 'sets the primary key passed to #meilisearch' do TestUtil.reset_people! People.create(first_name: 'Jane', last_name: 'Doe', card_number: 75_801_887) expect(People.index.fetch_info.primary_key).to eq('card_number') end + + it 'sets the primary key defined in #primary_key' do + TestUtil.reset_stories! + Story.create(story_id: 1, title: 'A nice story') + expect(Story.index.fetch_info.primary_key).to eq('story_id') + end + + it 'sets the primary key as id if not explicitly set' do + TestUtil.reset_books! + Book.create(name: 'Test Book', author: 'Test Author', premium: true, released: true, genre: 'Horror') + expect(Book.index.fetch_info.primary_key).to eq('id') + end end describe ':index_uid and :primary_key (shared index)' do diff --git a/spec/support/models/story.rb b/spec/support/models/story.rb new file mode 100644 index 0000000..1547456 --- /dev/null +++ b/spec/support/models/story.rb @@ -0,0 +1,21 @@ +require 'support/active_record_schema' + +ar_schema.create_table :stories do |t| + t.integer :story_id + t.string :title +end + +class Story < ActiveRecord::Base + include MeiliSearch::Rails + + self.primary_key = 'story_id' # Use model primary_key for index primary key + + meilisearch index_uid: safe_index_uid('MyCustomStory') # Don't set primary_key in meilisearch +end + +module TestUtil + def self.reset_stories! + Story.clear_index! + Story.delete_all + end +end From 3b305f08d1c80e8c9c30f1f0aab883bf3caf6cbb Mon Sep 17 00:00:00 2001 From: Thiago Colares Date: Fri, 10 Oct 2025 12:22:11 -0400 Subject: [PATCH 2/3] Reduce size of ClassMethods and fix RuboCop line offense - Module size is at the RuboCop limit; consider refactoring soon. --- lib/meilisearch-rails.rb | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/meilisearch-rails.rb b/lib/meilisearch-rails.rb index f481789..080bcc8 100644 --- a/lib/meilisearch-rails.rb +++ b/lib/meilisearch-rails.rb @@ -403,13 +403,7 @@ def meilisearch(options = {}, &block) raise ArgumentError, 'Cannot use a enqueue if the `synchronous` option is set' if options[:synchronous] proc = if options[:enqueue] == true - proc do |record, remove| - if remove - MSCleanUpJob.perform_later(record.ms_entries) - else - MSJob.perform_later(record, 'ms_index!') - end - end + proc { |record, remove| remove ? MSCleanUpJob.perform_later(record.ms_entries) : MSJob.perform_later(record, 'ms_index!') } elsif options[:enqueue].respond_to?(:call) options[:enqueue] elsif options[:enqueue].is_a?(Symbol) @@ -701,11 +695,7 @@ def ms_search(query, params = {}) condition_key = meilisearch_options[:type].primary_key if has_virtual_column_as_pk - hit_ids = if has_virtual_column_as_pk - json['hits'].map { |hit| hit[condition_key] } - else - json['hits'].map { |hit| hit[ms_pk(meilisearch_options).to_s] } - end + hit_ids = json['hits'].map { |hit| hit[has_virtual_column_as_pk ? condition_key : ms_pk(meilisearch_options).to_s] } # meilisearch_options[:type] refers to the Model name (e.g. Product) # results_by_id creates a hash with the primaryKey of the document (id) as the key and doc itself as the value From 5deec2abea09e4bc39f86e15f8113944dcd3718a Mon Sep 17 00:00:00 2001 From: Thiago Colares Date: Fri, 10 Oct 2025 15:56:08 -0400 Subject: [PATCH 3/3] Test extra scenarios for defined index primary_key --- spec/options_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/options_spec.rb b/spec/options_spec.rb index 609b225..7ff7b65 100644 --- a/spec/options_spec.rb +++ b/spec/options_spec.rb @@ -8,6 +8,7 @@ require 'support/models/story' require 'support/models/disabled_models' require 'support/models/queued_models' +require 'support/mongo_models/citizen' describe 'meilisearch_options' do describe ':index_uid' do @@ -23,18 +24,21 @@ TestUtil.reset_people! People.create(first_name: 'Jane', last_name: 'Doe', card_number: 75_801_887) expect(People.index.fetch_info.primary_key).to eq('card_number') + expect(MeiliSearch::Rails.client.index(People.index_uid).get_primary_key).to eq('card_number') end it 'sets the primary key defined in #primary_key' do TestUtil.reset_stories! Story.create(story_id: 1, title: 'A nice story') expect(Story.index.fetch_info.primary_key).to eq('story_id') + expect(MeiliSearch::Rails.client.index(Story.index_uid).get_primary_key).to eq('story_id') end it 'sets the primary key as id if not explicitly set' do TestUtil.reset_books! Book.create(name: 'Test Book', author: 'Test Author', premium: true, released: true, genre: 'Horror') expect(Book.index.fetch_info.primary_key).to eq('id') + expect(MeiliSearch::Rails.client.index(Book.index_uid).get_primary_key).to eq('id') end end