Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Adding sphinx_attributes to search results for access to attributes v…

…ia Sphinx.
  • Loading branch information...
commit 654bb509f1fc287e2ef65a97718d89cd73eddf7c 1 parent c4416e6
Pat Allan pat authored
11 features/direct_attributes.feature
View
@@ -0,0 +1,11 @@
+Feature: Direct Attributes
+ In order to avoid unnecessary SQL queries
+ I want to access attribute values from Sphinx's response
+
+ Scenario: Accessing attribute values directly
+ Given Sphinx is running
+ And I am searching on posts
+ When I search
+ Then the first result should have a comments count of 9
+
+
4 features/step_definitions/common_steps.rb
View
@@ -31,6 +31,10 @@
@method = @model ? :search_count : :count
end
+When /^I search$/ do
+ @results = nil
+end
+
When /^I search for (\w+)$/ do |query|
@results = nil
@query = query
4 features/step_definitions/search_steps.rb
View
@@ -83,3 +83,7 @@
excerpt.should == string
end
+
+Then /^the first result should have a (\w+\s?\w*) of (\d+)$/ do |attribute, value|
+ results.first.sphinx_attributes[attribute.gsub(/\s+/, '_')].should == value.to_i
+end
3  features/support/models/post.rb
View
@@ -11,8 +11,9 @@ class Post < ActiveRecord::Base
indexes tags.text, :as => :tags
indexes comments.content, :as => :comments
indexes authors.name, :as => :authors
-
+
has comments(:id), :as => :comment_ids, :source => :ranged_query
has category.name, :facet => true, :as => :category_name, :type => :string
+ has 'COUNT(DISTINCT comments.id)', :as => :comments_count, :type => :integer
end
end
18 lib/thinking_sphinx/search.rb
View
@@ -244,6 +244,7 @@ def populate
else
replace instances_from_matches
add_excerpter
+ add_sphinx_attributes
end
end
end
@@ -261,6 +262,23 @@ def add_excerpter
end
end
+ def add_sphinx_attributes
+ each do |object|
+ next if object.nil? || object.respond_to?(:sphinx_attributes)
+
+ match = @results[:matches].detect { |match|
+ match[:attributes]['sphinx_internal_id'] == object.
+ primary_key_for_sphinx &&
+ match[:attributes]['class_crc'] == object.class.to_crc32
+ }
+ next if match.nil?
+
+ object.metaclass.instance_eval do
+ define_method(:sphinx_attributes) { match[:attributes] }
+ end
+ end
+ end
+
def self.log(message, method = :debug)
return if ::ActiveRecord::Base.logger.nil?
::ActiveRecord::Base.logger.send method, message
4 spec/fixtures/models.rb
View
@@ -105,6 +105,10 @@ class Alpha < ActiveRecord::Base
def big_name
name.upcase
end
+
+ def sphinx_attributes
+ :existing
+ end
end
class Beta < ActiveRecord::Base
60 spec/lib/thinking_sphinx/search_spec.rb
View
@@ -732,28 +732,54 @@
end
end
- describe 'excerpts' do
- before :each do
- @search = ThinkingSphinx::Search.new
- end
+ context 'result objects' do
+ describe '#excerpts' do
+ before :each do
+ @search = ThinkingSphinx::Search.new
+ end
- it "should add excerpts method if objects don't already have one" do
- @search.first.should respond_to(:excerpts)
- end
+ it "should add excerpts method if objects don't already have one" do
+ @search.first.should respond_to(:excerpts)
+ end
- it "should return an instance of ThinkingSphinx::Excerpter" do
- @search.first.excerpts.should be_a(ThinkingSphinx::Excerpter)
- end
+ it "should return an instance of ThinkingSphinx::Excerpter" do
+ @search.first.excerpts.should be_a(ThinkingSphinx::Excerpter)
+ end
- it "should not add excerpts method if objects already have one" do
- @search.last.excerpts.should_not be_a(ThinkingSphinx::Excerpter)
- end
+ it "should not add excerpts method if objects already have one" do
+ @search.last.excerpts.should_not be_a(ThinkingSphinx::Excerpter)
+ end
- it "should set up the excerpter with the instances and search" do
- ThinkingSphinx::Excerpter.should_receive(:new).with(@search, @alpha_a)
- ThinkingSphinx::Excerpter.should_receive(:new).with(@search, @alpha_b)
+ it "should set up the excerpter with the instances and search" do
+ ThinkingSphinx::Excerpter.should_receive(:new).with(@search, @alpha_a)
+ ThinkingSphinx::Excerpter.should_receive(:new).with(@search, @alpha_b)
- @search.first
+ @search.first
+ end
+ end
+
+ describe '#sphinx_attributes' do
+ before :each do
+ @search = ThinkingSphinx::Search.new
+ end
+
+ it "should add sphinx_attributes method if objects don't already have one" do
+ @search.last.should respond_to(:sphinx_attributes)
+ end
+
+ it "should return a hash" do
+ @search.last.sphinx_attributes.should be_a(Hash)
+ end
+
+ it "should not add sphinx_attributes if objects have a method of that name already" do
+ @search.first.sphinx_attributes.should_not be_a(Hash)
+ end
+
+ it "should pair sphinx_attributes with the correct hash" do
+ hash = @search.last.sphinx_attributes
+ hash['sphinx_internal_id'].should == @search.last.id
+ hash['class_crc'].should == @search.last.class.to_crc32
+ end
end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.