thinking-sphinx 3.0.0.rc → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/Gemfile +0 -4
  2. data/HISTORY +9 -0
  3. data/lib/thinking_sphinx.rb +1 -0
  4. data/lib/thinking_sphinx/active_record/index.rb +5 -0
  5. data/lib/thinking_sphinx/active_record/interpreter.rb +5 -0
  6. data/lib/thinking_sphinx/active_record/property.rb +2 -12
  7. data/lib/thinking_sphinx/active_record/sql_source.rb +3 -10
  8. data/lib/thinking_sphinx/active_record/sql_source/template.rb +4 -3
  9. data/lib/thinking_sphinx/configuration.rb +1 -1
  10. data/lib/thinking_sphinx/configuration/consistent_ids.rb +3 -1
  11. data/lib/thinking_sphinx/connection.rb +14 -0
  12. data/lib/thinking_sphinx/core.rb +1 -0
  13. data/lib/thinking_sphinx/core/index.rb +5 -9
  14. data/lib/thinking_sphinx/core/property.rb +13 -0
  15. data/lib/thinking_sphinx/middlewares/sphinxql.rb +1 -1
  16. data/lib/thinking_sphinx/rake_interface.rb +28 -5
  17. data/lib/thinking_sphinx/real_time.rb +1 -0
  18. data/lib/thinking_sphinx/real_time/attribute.rb +10 -0
  19. data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +3 -14
  20. data/lib/thinking_sphinx/real_time/field.rb +3 -1
  21. data/lib/thinking_sphinx/real_time/index.rb +29 -2
  22. data/lib/thinking_sphinx/real_time/index/template.rb +6 -5
  23. data/lib/thinking_sphinx/real_time/interpreter.rb +4 -0
  24. data/lib/thinking_sphinx/real_time/property.rb +2 -0
  25. data/lib/thinking_sphinx/real_time/transcriber.rb +37 -0
  26. data/lib/thinking_sphinx/tasks.rb +6 -5
  27. data/spec/acceptance/facets_spec.rb +2 -1
  28. data/spec/acceptance/index_options_spec.rb +20 -0
  29. data/spec/acceptance/searching_within_a_model_spec.rb +0 -1
  30. data/spec/acceptance/support/sphinx_helpers.rb +3 -0
  31. data/spec/internal/app/indices/product_index.rb +3 -3
  32. data/spec/thinking_sphinx/active_record/sql_source_spec.rb +14 -9
  33. data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +1 -1
  34. data/spec/thinking_sphinx/real_time/attribute_spec.rb +2 -2
  35. data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +3 -2
  36. data/spec/thinking_sphinx/real_time/field_spec.rb +4 -4
  37. data/spec/thinking_sphinx/real_time/index_spec.rb +9 -4
  38. data/thinking-sphinx.gemspec +4 -3
  39. metadata +42 -7
data/Gemfile CHANGED
@@ -2,10 +2,6 @@ source :rubygems
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'combustion',
6
- :git => 'git://github.com/pat/combustion.git',
7
- :ref => '45f50e64c3'
8
-
9
5
  gem 'mysql2', '~> 0.3.12b4', :platform => :ruby
10
6
  gem 'pg', '~> 0.11.0', :platform => :ruby
11
7
 
data/HISTORY CHANGED
@@ -1,3 +1,12 @@
1
+ 2013-01-02: 3.0.0
2
+ * [CHANGE] Updating Riddle dependency to 1.5.4.
3
+ * [FIX] Respect source options as well as underlying settings via the set_property method in index definitions.
4
+ * [FIX] Load real-time index definitions when listing fields, attributes, and/or conditions.
5
+ * [CHANGE] UTF-8 is now the default charset again (as it was in earlier Thinking Sphinx versions).
6
+ * [FEATURE] Initial realtime index support, including the ts:generate task for building index datasets. Sphinx 2.0.6 is required.
7
+ * [CHANGE] Removing ts:version rake task.
8
+ * [FEATURE] SphinxQL connection pooling via the Innertube gem.
9
+
1
10
  2012-12-22: 3.0.0.rc
2
11
  * [FEATURE] Source type support (query and ranged query) for both attributes and fields. Custom SQL strings can be supplied as well.
3
12
  * [FEATURE] Wordcount attributes and fields now supported.
@@ -8,6 +8,7 @@ end
8
8
  require 'riddle'
9
9
  require 'middleware'
10
10
  require 'active_record'
11
+ require 'innertube'
11
12
 
12
13
  module ThinkingSphinx
13
14
  def self.count(query = '', options = {})
@@ -24,6 +24,11 @@ class ThinkingSphinx::ActiveRecord::Index < Riddle::Configuration::Index
24
24
  @facets ||= sources.collect(&:facets).flatten
25
25
  end
26
26
 
27
+ def sources
28
+ interpret_definition!
29
+ super
30
+ end
31
+
27
32
  def unique_attribute_names
28
33
  attributes.collect(&:name)
29
34
  end
@@ -36,6 +36,7 @@ class ThinkingSphinx::ActiveRecord::Interpreter <
36
36
  properties.each do |key, value|
37
37
  @index.send("#{key}=", value) if @index.class.settings.include?(key)
38
38
  __source.send("#{key}=", value) if __source.class.settings.include?(key)
39
+ __source.options[key] = value if source_option?(key)
39
40
  end
40
41
  end
41
42
 
@@ -53,4 +54,8 @@ class ThinkingSphinx::ActiveRecord::Interpreter <
53
54
  options = columns.extract_options!
54
55
  columns.collect { |column| klass.new(__source.model, column, options) }
55
56
  end
57
+
58
+ def source_option?(key)
59
+ ::ThinkingSphinx::ActiveRecord::SQLSource::OPTIONS.include?(key)
60
+ end
56
61
  end
@@ -1,4 +1,6 @@
1
1
  class ThinkingSphinx::ActiveRecord::Property
2
+ include ThinkingSphinx::Core::Property
3
+
2
4
  attr_reader :columns, :options
3
5
 
4
6
  def initialize(model, columns, options = {})
@@ -10,14 +12,6 @@ class ThinkingSphinx::ActiveRecord::Property
10
12
  }
11
13
  end
12
14
 
13
- def facet?
14
- options[:facet]
15
- end
16
-
17
- def multi?
18
- false
19
- end
20
-
21
15
  def name
22
16
  (options[:as] || columns.first.__name).to_s
23
17
  end
@@ -25,8 +19,4 @@ class ThinkingSphinx::ActiveRecord::Property
25
19
  def source_type
26
20
  options[:source]
27
21
  end
28
-
29
- def type
30
- nil
31
- end
32
22
  end
@@ -2,16 +2,9 @@ class ThinkingSphinx::ActiveRecord::SQLSource < Riddle::Configuration::SQLSource
2
2
  attr_reader :model, :database_settings, :options
3
3
  attr_accessor :fields, :attributes, :associations, :conditions, :groupings
4
4
 
5
- # Options:
6
- # - :name
7
- # - :offset
8
- # - :delta_processor
9
- # - :delta?
10
- # - :disable_range?
11
- # - :group_concat_max_len
12
- # - :utf8?
13
- # - :position
14
- #
5
+ OPTIONS = [:name, :offset, :delta_processor, :delta?, :disable_range?,
6
+ :group_concat_max_len, :utf8?, :position]
7
+
15
8
  def initialize(model, options = {})
16
9
  @model = model
17
10
  @database_settings = model.connection.instance_variable_get(:@config).clone
@@ -6,10 +6,11 @@ class ThinkingSphinx::ActiveRecord::SQLSource::Template
6
6
  end
7
7
 
8
8
  def apply
9
- add_field class_column, :sphinx_internal_class, :facet => true
9
+ add_field class_column, :sphinx_internal_class_name
10
10
 
11
- add_attribute :id, :sphinx_internal_id, nil
12
- add_attribute '0', :sphinx_deleted, :integer
11
+ add_attribute :id, :sphinx_internal_id, nil
12
+ add_attribute class_column, :sphinx_internal_class, :string, :facet => true
13
+ add_attribute '0', :sphinx_deleted, :integer
13
14
  end
14
15
 
15
16
  private
@@ -25,7 +25,7 @@ class ThinkingSphinx::Configuration < Riddle::Configuration
25
25
  searchd.address = Defaults::ADDRESS unless searchd.address.present?
26
26
  searchd.mysql41 = settings['mysql41'] || settings['port'] ||
27
27
  Defaults::PORT
28
- # searchd.workers = 'threads'
28
+ searchd.workers = 'threads'
29
29
 
30
30
  @offsets = {}
31
31
  end
@@ -26,6 +26,8 @@ class ThinkingSphinx::Configuration::ConsistentIds
26
26
  end
27
27
 
28
28
  def sources
29
- @sources ||= @indices.collect(&:sources).flatten
29
+ @sources ||= @indices.select { |index|
30
+ index.respond_to?(:sources)
31
+ }.collect(&:sources).flatten
30
32
  end
31
33
  end
@@ -21,6 +21,13 @@ module ThinkingSphinx::Connection
21
21
  ThinkingSphinx::Connection::MRI
22
22
  end
23
23
 
24
+ def self.pool
25
+ @pool ||= Innertube::Pool.new(
26
+ Proc.new { ThinkingSphinx::Connection.new },
27
+ Proc.new { |connection| connection.close }
28
+ )
29
+ end
30
+
24
31
  class MRI
25
32
  attr_reader :client
26
33
 
@@ -32,8 +39,15 @@ module ThinkingSphinx::Connection
32
39
  }.merge(options))
33
40
  end
34
41
 
42
+ def close
43
+ client.close
44
+ end
45
+
35
46
  def execute(statement)
36
47
  client.query statement
48
+ rescue
49
+ puts "Error with statement: #{statement}"
50
+ raise
37
51
  end
38
52
 
39
53
  def query(statement)
@@ -5,3 +5,4 @@ end
5
5
  require 'thinking_sphinx/core/field'
6
6
  require 'thinking_sphinx/core/index'
7
7
  require 'thinking_sphinx/core/interpreter'
8
+ require 'thinking_sphinx/core/property'
@@ -7,10 +7,11 @@ module ThinkingSphinx::Core::Index
7
7
  end
8
8
 
9
9
  def initialize(reference, options = {})
10
- @reference = reference.to_sym
11
- @docinfo = :extern
12
- @options = options
13
- @offset = config.next_offset(reference)
10
+ @reference = reference.to_sym
11
+ @docinfo = :extern
12
+ @charset_type = 'utf-8'
13
+ @options = options
14
+ @offset = config.next_offset(reference)
14
15
 
15
16
  super "#{options[:name] || reference.to_s.gsub('/', '_')}_#{name_suffix}"
16
17
  end
@@ -47,11 +48,6 @@ module ThinkingSphinx::Core::Index
47
48
  super
48
49
  end
49
50
 
50
- def sources
51
- interpret_definition!
52
- super
53
- end
54
-
55
51
  private
56
52
 
57
53
  def config
@@ -0,0 +1,13 @@
1
+ module ThinkingSphinx::Core::Property
2
+ def facet?
3
+ options[:facet]
4
+ end
5
+
6
+ def multi?
7
+ false
8
+ end
9
+
10
+ def type
11
+ nil
12
+ end
13
+ end
@@ -69,7 +69,7 @@ class ThinkingSphinx::Middlewares::SphinxQL <
69
69
 
70
70
  def extended_query
71
71
  conditions = options[:conditions] || {}
72
- conditions[:sphinx_internal_class] = class_condition if classes.any?
72
+ conditions[:sphinx_internal_class_name] = class_condition if classes.any?
73
73
  @extended_query ||= begin
74
74
  ThinkingSphinx::Search::Query.new(context.search.query, conditions,
75
75
  options[:star]).to_s
@@ -1,12 +1,35 @@
1
1
  class ThinkingSphinx::RakeInterface
2
2
  def configure
3
- puts "Generating configuration to #{config.configuration_file}"
4
- config.render_to_file
3
+ puts "Generating configuration to #{configuration.configuration_file}"
4
+ configuration.render_to_file
5
+ end
6
+
7
+ def generate
8
+ configuration.preload_indices
9
+ configuration.render
10
+
11
+ FileUtils.mkdir_p configuration.indices_location
12
+
13
+ configuration.indices.each do |index|
14
+ next unless index.is_a?(ThinkingSphinx::RealTime::Index)
15
+
16
+ puts "Generating index files for #{index.name}"
17
+ transcriber = ThinkingSphinx::RealTime::Transcriber.new index
18
+ Dir["#{index.path}*"].each { |file| FileUtils.rm file }
19
+
20
+ index.model.find_each do |instance|
21
+ transcriber.copy instance
22
+ print "."
23
+ end
24
+ print "\n"
25
+
26
+ controller.rotate
27
+ end
5
28
  end
6
29
 
7
30
  def index(reconfigure = true)
8
31
  configure if reconfigure
9
- FileUtils.mkdir_p config.indices_location
32
+ FileUtils.mkdir_p configuration.indices_location
10
33
  controller.index :verbose => true
11
34
  end
12
35
 
@@ -37,11 +60,11 @@ class ThinkingSphinx::RakeInterface
37
60
 
38
61
  private
39
62
 
40
- def config
63
+ def configuration
41
64
  ThinkingSphinx::Configuration.instance
42
65
  end
43
66
 
44
67
  def controller
45
- config.controller
68
+ configuration.controller
46
69
  end
47
70
  end
@@ -7,5 +7,6 @@ require 'thinking_sphinx/real_time/attribute'
7
7
  require 'thinking_sphinx/real_time/field'
8
8
  require 'thinking_sphinx/real_time/index'
9
9
  require 'thinking_sphinx/real_time/interpreter'
10
+ require 'thinking_sphinx/real_time/transcriber'
10
11
 
11
12
  require 'thinking_sphinx/real_time/callbacks/real_time_callbacks'
@@ -2,4 +2,14 @@ class ThinkingSphinx::RealTime::Attribute < ThinkingSphinx::RealTime::Property
2
2
  def type
3
3
  @options[:type]
4
4
  end
5
+
6
+ def translate(object)
7
+ super || default_value
8
+ end
9
+
10
+ private
11
+
12
+ def default_value
13
+ type == :string ? '' : 0
14
+ end
5
15
  end
@@ -7,29 +7,18 @@ class ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks <
7
7
  return unless real_time_indices?
8
8
 
9
9
  real_time_indices.each do |index|
10
- columns, values = ['id'], [index.document_id_for_key(instance.id)]
11
- (index.fields + index.attributes).each do |property|
12
- columns << property.name
13
- values << property.translate(instance)
14
- end
15
-
16
- sphinxql = Riddle::Query::Insert.new(index.name, columns, values).replace!
17
- connection.execute sphinxql.to_sql
10
+ ThinkingSphinx::RealTime::Transcriber.new(index).copy instance
18
11
  end
19
12
  end
20
13
 
21
14
  private
22
15
 
23
- def config
16
+ def configuration
24
17
  ThinkingSphinx::Configuration.instance
25
18
  end
26
19
 
27
- def connection
28
- connection = ThinkingSphinx::Connection.new
29
- end
30
-
31
20
  def indices
32
- @indices ||= config.indices_for_references reference
21
+ @indices ||= configuration.indices_for_references reference
33
22
  end
34
23
 
35
24
  def real_time_indices?
@@ -1,5 +1,7 @@
1
1
  class ThinkingSphinx::RealTime::Field < ThinkingSphinx::RealTime::Property
2
2
  include ThinkingSphinx::Core::Field
3
3
 
4
- #
4
+ def translate(object)
5
+ Array(super || '').join(' ')
6
+ end
5
7
  end
@@ -1,17 +1,40 @@
1
1
  class ThinkingSphinx::RealTime::Index < Riddle::Configuration::RealtimeIndex
2
2
  include ThinkingSphinx::Core::Index
3
3
 
4
- attr_accessor :fields, :attributes
4
+ attr_writer :fields, :attributes, :conditions
5
5
 
6
6
  def initialize(reference, options = {})
7
7
  @fields = []
8
8
  @attributes = []
9
+ @conditions = []
9
10
 
10
11
  Template.new(self).apply
11
12
 
12
13
  super reference, options
13
14
  end
14
15
 
16
+ def attributes
17
+ interpret_definition!
18
+
19
+ @attributes
20
+ end
21
+
22
+ def conditions
23
+ interpret_definition!
24
+
25
+ @conditions
26
+ end
27
+
28
+ def facets
29
+ properties.select(&:facet?)
30
+ end
31
+
32
+ def fields
33
+ interpret_definition!
34
+
35
+ @fields
36
+ end
37
+
15
38
  def unique_attribute_names
16
39
  attributes.collect(&:name)
17
40
  end
@@ -38,10 +61,14 @@ class ThinkingSphinx::RealTime::Index < Riddle::Configuration::RealtimeIndex
38
61
  when :float
39
62
  @rt_attr_float << attribute.name unless @rt_attr_float.include?(attribute.name)
40
63
  else
41
- raise "Unknown attribute type '#{attribute.type(model)}'"
64
+ raise "Unknown attribute type '#{attribute.type}'"
42
65
  end
43
66
  end
44
67
  end
68
+
69
+ def properties
70
+ fields + attributes
71
+ end
45
72
  end
46
73
 
47
74
  require 'thinking_sphinx/real_time/index/template'
@@ -6,18 +6,19 @@ class ThinkingSphinx::RealTime::Index::Template
6
6
  end
7
7
 
8
8
  def apply
9
- add_field class_column, :sphinx_internal_class
9
+ add_field class_column, :sphinx_internal_class_name
10
10
 
11
- add_attribute :id, :sphinx_internal_id, :integer
12
- add_attribute 0, :sphinx_deleted, :integer
11
+ add_attribute :id, :sphinx_internal_id, :integer
12
+ add_attribute class_column, :sphinx_internal_class, :string, :facet => true
13
+ add_attribute 0, :sphinx_deleted, :integer
13
14
  end
14
15
 
15
16
  private
16
17
 
17
- def add_attribute(column, name, type)
18
+ def add_attribute(column, name, type, options = {})
18
19
  index.attributes << ThinkingSphinx::RealTime::Attribute.new(
19
20
  ThinkingSphinx::ActiveRecord::Column.new(*column),
20
- :as => name, :type => type
21
+ options.merge(:as => name, :type => type)
21
22
  )
22
23
  end
23
24
 
@@ -20,4 +20,8 @@ class ThinkingSphinx::RealTime::Interpreter <
20
20
  @index.send("#{key}=", value) if @index.class.settings.include?(key)
21
21
  end
22
22
  end
23
+
24
+ def where(condition)
25
+ @index.conditions << condition
26
+ end
23
27
  end
@@ -1,4 +1,6 @@
1
1
  class ThinkingSphinx::RealTime::Property
2
+ include ThinkingSphinx::Core::Property
3
+
2
4
  attr_reader :options
3
5
 
4
6
  def initialize(column, options = {})
@@ -0,0 +1,37 @@
1
+ class ThinkingSphinx::RealTime::Transcriber
2
+ def initialize(index)
3
+ @index = index
4
+ end
5
+
6
+ def copy(instance)
7
+ return unless copy? instance
8
+
9
+ columns, values = ['id'], [index.document_id_for_key(instance.id)]
10
+ (index.fields + index.attributes).each do |property|
11
+ columns << property.name
12
+ values << property.translate(instance)
13
+ end
14
+
15
+ sphinxql = Riddle::Query::Insert.new index.name, columns, values
16
+ ThinkingSphinx::Connection.pool.take do |connection|
17
+ connection.execute sphinxql.replace!.to_sql
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :index
24
+
25
+ def copy?(instance)
26
+ index.conditions.empty? || index.conditions.all? { |condition|
27
+ case condition
28
+ when Symbol
29
+ instance.send(condition)
30
+ when Proc
31
+ condition.call instance
32
+ else
33
+ "Unexpected condition: #{condition}. Expecting Symbol or Proc."
34
+ end
35
+ }
36
+ end
37
+ end
@@ -1,9 +1,4 @@
1
1
  namespace :ts do
2
- desc 'The current version of Thinking Sphinx'
3
- task :version do
4
- puts "Thinking Sphinx v#{ThinkingSphinx::VERSION}"
5
- end
6
-
7
2
  desc 'Generate the Sphinx configuration file'
8
3
  task :configure => :environment do
9
4
  interface.configure
@@ -14,8 +9,14 @@ namespace :ts do
14
9
  interface.index(ENV['INDEX_ONLY'] != 'true')
15
10
  end
16
11
 
12
+ desc 'Generate fresh index files for real-time indices'
13
+ task :generate => :environment do
14
+ interface.generate
15
+ end
16
+
17
17
  desc 'Stop Sphinx, index and then restart Sphinx'
18
18
  task :rebuild => [:stop, :index, :start]
19
+
19
20
  desc 'Restart the Sphinx daemon'
20
21
  task :restart => [:stop, :start]
21
22
 
@@ -23,10 +23,11 @@ describe 'Faceted searching', :live => true do
23
23
  Tee.create!
24
24
  Tee.create!
25
25
  City.create!
26
+ Product.create!
26
27
  index
27
28
 
28
29
  ThinkingSphinx.facets.to_hash[:class].should == {
29
- 'Tee' => 2, 'City' => 1
30
+ 'Tee' => 2, 'City' => 1, 'Product' => 1
30
31
  }
31
32
  end
32
33
 
@@ -84,4 +84,24 @@ describe 'Index options' do
84
84
  index.sources.first.sql_attr_str2wordcount.should == ['content']
85
85
  end
86
86
  end
87
+
88
+ context 'respecting source options' do
89
+ before :each do
90
+ index.definition_block = Proc.new {
91
+ indexes title
92
+
93
+ set_property :sql_range_step => 5
94
+ set_property :disable_range? => true
95
+ }
96
+ index.render
97
+ end
98
+
99
+ it "allows for core source settings" do
100
+ index.sources.first.sql_range_step.should == 5
101
+ end
102
+
103
+ it "allows for source options" do
104
+ index.sources.first.disable_range?.should be_true
105
+ end
106
+ end
87
107
  end
@@ -51,7 +51,6 @@ end
51
51
 
52
52
  describe 'Searching within a model with a realtime index', :live => true do
53
53
  it "returns results" do
54
- pending "Sphinx bug on OS X means I can't currently test this."
55
54
  product = Product.create! :name => 'Widget'
56
55
 
57
56
  Product.search.first.should == product
@@ -15,6 +15,9 @@ RSpec.configure do |config|
15
15
  config.include SphinxHelpers
16
16
 
17
17
  config.before :all do |group|
18
+ FileUtils.rm_rf ThinkingSphinx::Configuration.instance.indices_location
19
+ FileUtils.rm_rf ThinkingSphinx::Configuration.instance.searchd.binlog_path
20
+
18
21
  sphinx.setup && sphinx.start if group.class.metadata[:live]
19
22
  end
20
23
 
@@ -1,3 +1,3 @@
1
- # ThinkingSphinx::Index.define :product, :with => :real_time do
2
- # indexes name
3
- # end
1
+ ThinkingSphinx::Index.define :product, :with => :real_time do
2
+ indexes name
3
+ end
@@ -32,9 +32,19 @@ describe ThinkingSphinx::ActiveRecord::SQLSource do
32
32
  source.attributes.collect(&:name).should include('sphinx_internal_id')
33
33
  end
34
34
 
35
+ it "has the class name attribute by default" do
36
+ source.attributes.collect(&:name).should include('sphinx_internal_class')
37
+ end
38
+
35
39
  it "has the internal deleted attribute by default" do
36
40
  source.attributes.collect(&:name).should include('sphinx_deleted')
37
41
  end
42
+
43
+ it "marks the internal class attribute as a facet" do
44
+ source.attributes.detect { |attribute|
45
+ attribute.name == 'sphinx_internal_class'
46
+ }.options[:facet].should be_true
47
+ end
38
48
  end
39
49
 
40
50
  describe '#delta_processor' do
@@ -77,12 +87,13 @@ describe ThinkingSphinx::ActiveRecord::SQLSource do
77
87
 
78
88
  describe '#fields' do
79
89
  it "has the internal class field by default" do
80
- source.fields.collect(&:name).should include('sphinx_internal_class')
90
+ source.fields.collect(&:name).
91
+ should include('sphinx_internal_class_name')
81
92
  end
82
93
 
83
94
  it "sets the sphinx class field to use a string of the class name" do
84
95
  source.fields.detect { |field|
85
- field.name == 'sphinx_internal_class'
96
+ field.name == 'sphinx_internal_class_name'
86
97
  }.columns.first.__name.should == "'User'"
87
98
  end
88
99
 
@@ -94,16 +105,10 @@ describe ThinkingSphinx::ActiveRecord::SQLSource do
94
105
  model.stub :column_names => ['type'], :sti_name => 'User'
95
106
 
96
107
  source.fields.detect { |field|
97
- field.name == 'sphinx_internal_class'
108
+ field.name == 'sphinx_internal_class_name'
98
109
  }.columns.first.__name.
99
110
  should == "ifnull(\"users\".\"type\", 'User')"
100
111
  end
101
-
102
- it "marks the internal class field as a facet" do
103
- source.fields.detect { |field|
104
- field.name == 'sphinx_internal_class'
105
- }.options[:facet].should be_true
106
- end
107
112
  end
108
113
 
109
114
  describe '#name' do
@@ -102,7 +102,7 @@ describe ThinkingSphinx::Middlewares::SphinxQL do
102
102
  search.options[:classes] = [submodel]
103
103
 
104
104
  ThinkingSphinx::Search::Query.should_receive(:new).with(anything,
105
- hash_including(:sphinx_internal_class => '(Lion)'), anything).
105
+ hash_including(:sphinx_internal_class_name => '(Lion)'), anything).
106
106
  and_return(query)
107
107
 
108
108
  middleware.call [context]
@@ -44,11 +44,11 @@ describe ThinkingSphinx::RealTime::Attribute do
44
44
  attribute.translate(object).should == 'the parent name'
45
45
  end
46
46
 
47
- it "returns nil if any element in the object tree is nil" do
47
+ it "returns zero if any element in the object tree is nil" do
48
48
  column.stub :__name => :name, :__stack => [:parent]
49
49
  object.parent = nil
50
50
 
51
- attribute.translate(object).should be_nil
51
+ attribute.translate(object).should be_zero
52
52
  end
53
53
  end
54
54
 
@@ -7,12 +7,13 @@ describe ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks do
7
7
  let(:instance) { double('instance', :id => 12) }
8
8
  let(:config) { double('config', :indices_for_references => [index]) }
9
9
  let(:index) { double('index', :name => 'my_index', :is_a? => true,
10
- :document_id_for_key => 123, :fields => [], :attributes => []) }
10
+ :document_id_for_key => 123, :fields => [], :attributes => [],
11
+ :conditions => []) }
11
12
  let(:connection) { double('connection', :execute => true) }
12
13
 
13
14
  before :each do
14
15
  ThinkingSphinx::Configuration.stub :instance => config
15
- ThinkingSphinx::Connection.stub :new => connection
16
+ ThinkingSphinx::Connection.stub_chain(:pool, :take).and_yield connection
16
17
  end
17
18
 
18
19
  describe '.after_save' do
@@ -26,10 +26,10 @@ describe ThinkingSphinx::RealTime::Field do
26
26
  field.translate(object).should == 'value'
27
27
  end
28
28
 
29
- it "returns the column's name if it's an integer" do
29
+ it "returns the column's name as a string if it's an integer" do
30
30
  column.stub :__name => 404
31
31
 
32
- field.translate(object).should == 404
32
+ field.translate(object).should == '404'
33
33
  end
34
34
 
35
35
  it "returns the object's method matching the column's name" do
@@ -44,11 +44,11 @@ describe ThinkingSphinx::RealTime::Field do
44
44
  field.translate(object).should == 'the parent name'
45
45
  end
46
46
 
47
- it "returns nil if any element in the object tree is nil" do
47
+ it "returns a blank string if any element in the object tree is nil" do
48
48
  column.stub :__name => :name, :__stack => [:parent]
49
49
  object.parent = nil
50
50
 
51
- field.translate(object).should be_nil
51
+ field.translate(object).should == ''
52
52
  end
53
53
  end
54
54
  end
@@ -15,6 +15,10 @@ describe ThinkingSphinx::RealTime::Index do
15
15
  index.attributes.collect(&:name).should include('sphinx_internal_id')
16
16
  end
17
17
 
18
+ it "has the class name attribute by default" do
19
+ index.attributes.collect(&:name).should include('sphinx_internal_class')
20
+ end
21
+
18
22
  it "has the internal deleted attribute by default" do
19
23
  index.attributes.collect(&:name).should include('sphinx_deleted')
20
24
  end
@@ -37,7 +41,7 @@ describe ThinkingSphinx::RealTime::Index do
37
41
 
38
42
  describe '#fields' do
39
43
  it "has the internal class field by default" do
40
- index.fields.collect(&:name).should include('sphinx_internal_class')
44
+ index.fields.collect(&:name).should include('sphinx_internal_class_name')
41
45
  end
42
46
  end
43
47
 
@@ -135,7 +139,7 @@ describe ThinkingSphinx::RealTime::Index do
135
139
 
136
140
  describe '#render' do
137
141
  it "interprets the provided definition" do
138
- index.should_receive(:interpret_definition!)
142
+ index.should_receive(:interpret_definition!).at_least(:once)
139
143
 
140
144
  begin
141
145
  index.render
@@ -147,8 +151,9 @@ describe ThinkingSphinx::RealTime::Index do
147
151
 
148
152
  describe '#unique_attribute_names' do
149
153
  it "returns all attribute names" do
150
- index.unique_attribute_names.
151
- should == ['sphinx_internal_id', 'sphinx_deleted']
154
+ index.unique_attribute_names.should == [
155
+ 'sphinx_internal_id', 'sphinx_internal_class', 'sphinx_deleted'
156
+ ]
152
157
  end
153
158
  end
154
159
  end
@@ -3,7 +3,7 @@ $:.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'thinking-sphinx'
6
- s.version = '3.0.0.rc'
6
+ s.version = '3.0.0'
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Pat Allan"]
9
9
  s.email = ["pat@freelancing-gods.com"]
@@ -23,10 +23,11 @@ Gem::Specification.new do |s|
23
23
  s.add_runtime_dependency 'activerecord', '>= 3.1.0'
24
24
  s.add_runtime_dependency 'builder', '>= 2.1.2'
25
25
  s.add_runtime_dependency 'middleware', '>= 0.1.0'
26
- s.add_runtime_dependency 'riddle', '>= 1.5.3'
26
+ s.add_runtime_dependency 'innertube', '>= 1.0.2'
27
+ s.add_runtime_dependency 'riddle', '>= 1.5.4'
27
28
 
28
29
  s.add_development_dependency 'appraisal', '~> 0.4.0'
29
- # s.add_development_dependency 'combustion', '~> 0.3.1'
30
+ s.add_development_dependency 'combustion', '~> 0.3.3'
30
31
  s.add_development_dependency 'database_cleaner', '~> 0.7.1'
31
32
  s.add_development_dependency 'rspec', '~> 2.11.0'
32
33
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thinking-sphinx
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.rc
5
- prerelease: 6
4
+ version: 3.0.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Pat Allan
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-22 00:00:00.000000000 Z
12
+ date: 2013-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.1.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: innertube
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.2
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.2
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: riddle
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +82,7 @@ dependencies:
66
82
  requirements:
67
83
  - - ! '>='
68
84
  - !ruby/object:Gem::Version
69
- version: 1.5.3
85
+ version: 1.5.4
70
86
  type: :runtime
71
87
  prerelease: false
72
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +90,7 @@ dependencies:
74
90
  requirements:
75
91
  - - ! '>='
76
92
  - !ruby/object:Gem::Version
77
- version: 1.5.3
93
+ version: 1.5.4
78
94
  - !ruby/object:Gem::Dependency
79
95
  name: appraisal
80
96
  requirement: !ruby/object:Gem::Requirement
@@ -91,6 +107,22 @@ dependencies:
91
107
  - - ~>
92
108
  - !ruby/object:Gem::Version
93
109
  version: 0.4.0
110
+ - !ruby/object:Gem::Dependency
111
+ name: combustion
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.3.3
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: 0.3.3
94
126
  - !ruby/object:Gem::Dependency
95
127
  name: database_cleaner
96
128
  requirement: !ruby/object:Gem::Requirement
@@ -181,6 +213,7 @@ files:
181
213
  - lib/thinking_sphinx/core/field.rb
182
214
  - lib/thinking_sphinx/core/index.rb
183
215
  - lib/thinking_sphinx/core/interpreter.rb
216
+ - lib/thinking_sphinx/core/property.rb
184
217
  - lib/thinking_sphinx/deltas.rb
185
218
  - lib/thinking_sphinx/deltas/default_delta.rb
186
219
  - lib/thinking_sphinx/excerpter.rb
@@ -221,6 +254,7 @@ files:
221
254
  - lib/thinking_sphinx/real_time/index/template.rb
222
255
  - lib/thinking_sphinx/real_time/interpreter.rb
223
256
  - lib/thinking_sphinx/real_time/property.rb
257
+ - lib/thinking_sphinx/real_time/transcriber.rb
224
258
  - lib/thinking_sphinx/scopes.rb
225
259
  - lib/thinking_sphinx/search.rb
226
260
  - lib/thinking_sphinx/search/batch_inquirer.rb
@@ -358,9 +392,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
358
392
  required_rubygems_version: !ruby/object:Gem::Requirement
359
393
  none: false
360
394
  requirements:
361
- - - ! '>'
395
+ - - ! '>='
362
396
  - !ruby/object:Gem::Version
363
- version: 1.3.1
397
+ version: '0'
364
398
  requirements: []
365
399
  rubyforge_project: thinking-sphinx
366
400
  rubygems_version: 1.8.23
@@ -476,3 +510,4 @@ test_files:
476
510
  - spec/thinking_sphinx/search/query_spec.rb
477
511
  - spec/thinking_sphinx/search_spec.rb
478
512
  - spec/thinking_sphinx_spec.rb
513
+ has_rdoc: