From f8fbe02b2155df0454200e67d25892f1984cc9a2 Mon Sep 17 00:00:00 2001 From: Fanis Tharropoulos Date: Wed, 25 Mar 2026 13:26:50 +0200 Subject: [PATCH] fix: resolve top-level model constants from Object - make `typesense_full_const_get` avoid resolving `Collection` as `Typesense::Collection` - add an integration regression spec for a top-level `Collection` model and search result loading --- lib/typesense-rails.rb | 4 ++-- spec/integration_spec.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/lib/typesense-rails.rb b/lib/typesense-rails.rb index 4fd82af..187352e 100644 --- a/lib/typesense-rails.rb +++ b/lib/typesense-rails.rb @@ -955,11 +955,11 @@ def typesense_settings_changed?(prev, current) def typesense_full_const_get(name) list = name.split("::") list.shift if list.first.blank? - obj = Object.const_defined?(:RUBY_VERSION) && RUBY_VERSION.to_f < 1.9 ? Object : self + obj = Object list.each do |x| # This is required because const_get tries to look for constants in the # ancestor chain, but we only want constants that are HERE - obj = obj.const_defined?(x) ? obj.const_get(x) : obj.const_missing(x) + obj = obj.const_defined?(x, false) ? obj.const_get(x, false) : obj.const_missing(x) end obj end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 7b6a7aa..3d27fcf 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -73,6 +73,9 @@ t.string :short_name t.integer :hex end + create_table :collections do |t| + t.string :name + end create_table :namespaced_models do |t| t.string :name t.integer :another_private_value @@ -212,6 +215,14 @@ def will_save_change_to_short_name? end end +class Collection < ActiveRecord::Base + include Typesense + + typesense auto_index: false, index_name: safe_index_name("Collection") do + attribute :name + end +end + class DisabledBoolean < ActiveRecord::Base include Typesense @@ -642,6 +653,35 @@ class SerializedObject < ActiveRecord::Base end end +describe "Collection" do + it "resolves the model class instead of Typesense::Collection" do + expect(Collection.typesense_options[:type]).to eq(Collection) + end + + it "uses the ActiveRecord model when loading search hits" do + record = Collection.create!(name: "Archive") + + allow(Collection).to receive(:typesense_raw_search).and_return( + { + "hits" => [ + { + "document" => { "id" => record.id.to_s }, + "highlights" => [] + } + ], + "found" => 1, + "page" => 1, + "request_params" => { "per_page" => 10 } + } + ) + + results = Collection.search("*", "name") + + expect(results.length).to eq(1) + expect(results.first).to eq(record) + end +end + describe "UniqUsers" do before(:all) do UniqUser.clear_index!