Skip to content

Commit

Permalink
Added check to whether model instance exists within the core index be…
Browse files Browse the repository at this point in the history
…fore trying to update the deleted attribute
  • Loading branch information
pat committed Jun 24, 2008
1 parent 19c7541 commit b47e521
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 15 deletions.
6 changes: 5 additions & 1 deletion lib/thinking_sphinx/active_record.rb
Expand Up @@ -114,6 +114,10 @@ def to_crc32
)
end

def in_core_index?
@in_core_index ||= self.class.search_for_id(self.id, "#{self.class.name.downcase}_core")
end

def toggle_deleted
config = ThinkingSphinx::Configuration.new
client = Riddle::Client.new config.address, config.port
Expand All @@ -122,7 +126,7 @@ def toggle_deleted
"#{self.class.indexes.first.name}_core",
['sphinx_deleted'],
{self.id => 1}
)
) if self.in_core_index?

client.update(
"#{self.class.indexes.first.name}_delta",
Expand Down
7 changes: 7 additions & 0 deletions lib/thinking_sphinx/active_record/search.rb
Expand Up @@ -28,6 +28,13 @@ def search(*args)
args << options
ThinkingSphinx::Search.search(*args)
end

def search_for_id(*args)
options = args.extract_options!
options[:class] = self
args << options
ThinkingSphinx::Search.search_for_id(*args)
end
end
end
end
Expand Down
29 changes: 29 additions & 0 deletions lib/thinking_sphinx/search.rb
Expand Up @@ -182,6 +182,35 @@ def search(*args)
end
end

# Checks if a document with the given id exists within a specific index.
# Expected parameters:
#
# - ID of the document
# - Index to check within
# - Options hash (defaults to {})
#
# Example:
#
# ThinkingSphinx::Search.search_for_id(10, "user_core", :class => User)
#
def search_for_id(*args)
options = args.extract_options!
client = client_from_options options

query, filters = search_conditions(
options[:class], options[:conditions] || {}
)
client.filters += filters
client.match_mode = :extended unless query.empty?
client.id_range = args.first..args.first

begin
return client.query(query, args[1])[:matches].length > 0
rescue Errno::ECONNREFUSED => err
raise ThinkingSphinx::ConnectionError, "Connection to Sphinx Daemon (searchd) failed."
end
end

private

# This method handles the common search functionality, and returns both
Expand Down
34 changes: 26 additions & 8 deletions spec/unit/thinking_sphinx/active_record/search_spec.rb
Expand Up @@ -9,15 +9,15 @@
ActiveRecord::Base.methods.should include("search")
end

it "should add search_for_id to ActiveRecord::Base" do
ActiveRecord::Base.methods.should include("search_for_id")
end

describe "search_for_ids method" do
before :each do
ThinkingSphinx::Search.stub_method(:search_for_ids => true)
end

after :each do
ThinkingSphinx::Search.unstub_method(:search_for_ids)
end

it "should call ThinkingSphinx::Search#search_for_ids with the class option set" do
Person.search_for_ids("search")

Expand All @@ -40,10 +40,6 @@
ThinkingSphinx::Search.stub_method(:search => true)
end

after :each do
ThinkingSphinx::Search.unstub_method(:search)
end

it "should call ThinkingSphinx::Search#search with the class option set" do
Person.search("search")

Expand All @@ -60,4 +56,26 @@
)
end
end

describe "search_for_id method" do
before :each do
ThinkingSphinx::Search.stub_method(:search_for_id => true)
end

it "should call ThinkingSphinx::Search#search with the class option set" do
Person.search_for_id(10)

ThinkingSphinx::Search.should have_received(:search_for_id).with(
10, :class => Person
)
end

it "should override the class option" do
Person.search_for_id(10, :class => Friendship)

ThinkingSphinx::Search.should have_received(:search_for_id).with(
10, :class => Person
)
end
end
end
33 changes: 27 additions & 6 deletions spec/unit/thinking_sphinx/active_record_spec.rb
Expand Up @@ -100,6 +100,16 @@ class TestModel < ActiveRecord::Base; end
end
end

describe "in_core_index? method" do
it "should return the model's corresponding search_for_id value" do
Person.stub_method(:search_for_id => :searching_for_id)

person = Person.find(:first)
person.in_core_index?.should == :searching_for_id
Person.should have_received(:search_for_id).with(person.id, "person_core")
end
end

describe "toggle_deleted method" do
before :each do
@configuration = ThinkingSphinx::Configuration.stub_instance(
Expand All @@ -112,13 +122,14 @@ class TestModel < ActiveRecord::Base; end
ThinkingSphinx::Configuration.stub_method(:new => @configuration)
Riddle::Client.stub_method(:new => @client)
Person.indexes.each { |index| index.stub_method(:delta? => false) }
@person.stub_method(:in_core_index? => true)
end

after :each do
ThinkingSphinx::Configuration.unstub_method(:new)
Riddle::Client.unstub_method(:new)
Person.indexes.each { |index| index.unstub_method(:delta?) }
end
# after :each do
# ThinkingSphinx::Configuration.unstub_method(:new)
# Riddle::Client.unstub_method(:new)
# Person.indexes.each { |index| index.unstub_method(:delta?) }
# end

it "should create a client using the Configuration's address and port" do
@person.toggle_deleted
Expand All @@ -128,14 +139,24 @@ class TestModel < ActiveRecord::Base; end
)
end

it "should update the core index's deleted flag" do
it "should update the core index's deleted flag if in core index" do
@person.toggle_deleted

@client.should have_received(:update).with(
"person_core", ["sphinx_deleted"], {@person.id => 1}
)
end

it "shouldn't update the core index's deleted flag if the record isn't in it" do
@person.stub_method(:in_core_index? => false)

@person.toggle_deleted

@client.should_not have_received(:update).with(
"person_core", ["sphinx_deleted"], {@person.id => 1}
)
end

it "should update the delta index's deleted flag if delta indexing is enabled and the instance's delta is true" do
Person.indexes.each { |index| index.stub_method(:delta? => true) }
@person.delta = true
Expand Down
42 changes: 42 additions & 0 deletions spec/unit/thinking_sphinx/search_spec.rb
@@ -1,6 +1,48 @@
require 'spec/spec_helper'

describe ThinkingSphinx::Search do
describe "search_for_id method" do
before :each do
@client = Riddle::Client.stub_instance(
:filters => [],
:filters= => true,
:id_range= => true,
:query => {
:matches => []
}
)

ThinkingSphinx::Search.stub_methods(
:client_from_options => @client,
:search_conditions => ["", []]
)
end

it "should set the client id range to focus on the given id" do
ThinkingSphinx::Search.search_for_id 42, "an_index"

@client.should have_received(:id_range=).with(42..42)
end

it "should query on the given index" do
ThinkingSphinx::Search.search_for_id 42, "an_index"

@client.should have_received(:query).with("", "an_index")
end

it "should return true if a record is returned" do
@client.stub_method(:query => {
:matches => [24]
})

ThinkingSphinx::Search.search_for_id(42, "an_index").should be_true
end

it "should return false if no records are returned" do
ThinkingSphinx::Search.search_for_id(42, "an_index").should be_false
end
end

describe "instance_from_result method" do
before :each do
Person.stub_method(:find => true)
Expand Down

0 comments on commit b47e521

Please sign in to comment.