diff --git a/features/sti_searching.feature b/features/sti_searching.feature index 32537c806..4eb713534 100644 --- a/features/sti_searching.feature +++ b/features/sti_searching.feature @@ -12,3 +12,8 @@ Feature: Searching via STI model relationships Given Sphinx is running And I am searching on cats Then I should get as many results as there are cats + + Scenario: Searching across super and subclass indexes + Given Sphinx is running + When I search for "fantastic" + Then I should get 1 result diff --git a/features/support/db/fixtures/foxes.rb b/features/support/db/fixtures/foxes.rb new file mode 100644 index 000000000..20ae5985f --- /dev/null +++ b/features/support/db/fixtures/foxes.rb @@ -0,0 +1,3 @@ +%w( fantastic ).each do |name| + Fox.create :name => name +end diff --git a/features/support/models/fox.rb b/features/support/models/fox.rb new file mode 100644 index 000000000..93577a908 --- /dev/null +++ b/features/support/models/fox.rb @@ -0,0 +1,5 @@ +class Fox < Animal + define_index do + indexes :name + end +end diff --git a/lib/thinking_sphinx.rb b/lib/thinking_sphinx.rb index e6b9c5c11..8e1182004 100644 --- a/lib/thinking_sphinx.rb +++ b/lib/thinking_sphinx.rb @@ -63,6 +63,13 @@ def self.version def self.indexed_models Thread.current[:thinking_sphinx_indexed_models] ||= [] end + + def self.superclass_indexed_models + klasses = indexed_models.collect { |name| name.constantize } + klasses.reject { |klass| + klass.superclass.ancestors.any? { |ancestor| klasses.include?(ancestor) } + }.collect { |klass| klass.name } + end def self.unique_id_expression(offset = nil) "* #{indexed_models.size} + #{offset || 0}" diff --git a/lib/thinking_sphinx/active_record.rb b/lib/thinking_sphinx/active_record.rb index cb4ddfcda..1d4fa5232 100644 --- a/lib/thinking_sphinx/active_record.rb +++ b/lib/thinking_sphinx/active_record.rb @@ -127,6 +127,7 @@ def define_index(name = nil, &block) unless ThinkingSphinx.indexed_models.include?(self.name) ThinkingSphinx.indexed_models << self.name + ThinkingSphinx.indexed_models.sort! end add_sphinx_callbacks_and_extend(index.delta?) @@ -166,11 +167,11 @@ def delta_index_names sphinx_indexes.select(&:delta?).collect(&:delta_name) end - def to_riddle(offset) + def to_riddle sphinx_database_adapter.setup local_sphinx_indexes.collect { |index| - index.to_riddle(offset) + index.to_riddle(sphinx_offset) }.flatten end @@ -195,6 +196,10 @@ def delete_in_index(index, document_id) ) end + def sphinx_offset + ThinkingSphinx.superclass_indexed_models.index eldest_indexed_ancestor + end + private def local_sphinx_indexes @@ -219,6 +224,12 @@ def add_sphinx_callbacks_and_extend(delta = false) after_commit :index_delta end end + + def eldest_indexed_ancestor + ancestors.reverse.detect { |ancestor| + ThinkingSphinx.indexed_models.include?(ancestor.name) + }.name + end end def in_index?(suffix) @@ -263,7 +274,7 @@ def primary_key_for_sphinx def sphinx_document_id primary_key_for_sphinx * ThinkingSphinx.indexed_models.size + - ThinkingSphinx.indexed_models.index(self.class.source_of_sphinx_index.name) + self.class.sphinx_offset end private diff --git a/lib/thinking_sphinx/configuration.rb b/lib/thinking_sphinx/configuration.rb index 2a9b79aa9..07413048d 100644 --- a/lib/thinking_sphinx/configuration.rb +++ b/lib/thinking_sphinx/configuration.rb @@ -147,8 +147,8 @@ def build(file_path=nil) @configuration.indexes.clear - ThinkingSphinx.indexed_models.each_with_index do |model, model_index| - @configuration.indexes.concat model.constantize.to_riddle(model_index) + ThinkingSphinx.indexed_models.each do |model| + @configuration.indexes.concat model.constantize.to_riddle end open(file_path, "w") do |file| diff --git a/spec/thinking_sphinx/active_record_spec.rb b/spec/thinking_sphinx/active_record_spec.rb index dbbb41066..d10f42439 100644 --- a/spec/thinking_sphinx/active_record_spec.rb +++ b/spec/thinking_sphinx/active_record_spec.rb @@ -365,19 +365,9 @@ it "should return values with the expected offset" do person = Person.find(:first) model_count = ThinkingSphinx.indexed_models.length - offset = ThinkingSphinx.indexed_models.index("Person") + Person.stub!(:sphinx_offset => 3) - (person.id * model_count + offset).should == person.sphinx_document_id - - alpha = Alpha.find(:first) - offset = ThinkingSphinx.indexed_models.index("Alpha") - - (alpha.id * model_count + offset).should == alpha.sphinx_document_id - - beta = Beta.find(:first) - offset = ThinkingSphinx.indexed_models.index("Beta") - - (beta.id * model_count + offset).should == beta.sphinx_document_id + (person.id * model_count + 3).should == person.sphinx_document_id end end @@ -510,4 +500,25 @@ Alpha.delta_index_names.should == ['foo_delta'] end end + + describe '.sphinx_offset' do + it "should return the index of the model's name in all known indexed models" do + ThinkingSphinx.stub!(:indexed_models => ['Alpha', 'Beta']) + + Alpha.sphinx_offset.should == 0 + Beta.sphinx_offset.should == 1 + end + + it "should ignore classes that have indexed superclasses" do + ThinkingSphinx.stub!(:indexed_models => ['Alpha', 'Parent', 'Person']) + + Person.sphinx_offset.should == 1 + end + + it "should respect first known indexed parents" do + ThinkingSphinx.stub!(:indexed_models => ['Alpha', 'Parent', 'Person']) + + Parent.sphinx_offset.should == 1 + end + end end diff --git a/spec/thinking_sphinx_spec.rb b/spec/thinking_sphinx_spec.rb index 890c83a9f..b443d2641 100644 --- a/spec/thinking_sphinx_spec.rb +++ b/spec/thinking_sphinx_spec.rb @@ -91,6 +91,20 @@ end end + describe '.superclass_indexed_models' do + it "should return indexed model names" do + ThinkingSphinx.stub!(:indexed_models => ['Alpha', 'Beta']) + + ThinkingSphinx.superclass_indexed_models.should == ['Alpha', 'Beta'] + end + + it "should not include classes which have indexed superclasses" do + ThinkingSphinx.stub!(:indexed_models => ['Parent', 'Person']) + + ThinkingSphinx.superclass_indexed_models.should == ['Person'] + end + end + describe "use_group_by_shortcut? method" do before :each do adapter = defined?(JRUBY_VERSION) ? :JdbcAdapter : :MysqlAdapter