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.
- data/Gemfile +0 -4
- data/HISTORY +9 -0
- data/lib/thinking_sphinx.rb +1 -0
- data/lib/thinking_sphinx/active_record/index.rb +5 -0
- data/lib/thinking_sphinx/active_record/interpreter.rb +5 -0
- data/lib/thinking_sphinx/active_record/property.rb +2 -12
- data/lib/thinking_sphinx/active_record/sql_source.rb +3 -10
- data/lib/thinking_sphinx/active_record/sql_source/template.rb +4 -3
- data/lib/thinking_sphinx/configuration.rb +1 -1
- data/lib/thinking_sphinx/configuration/consistent_ids.rb +3 -1
- data/lib/thinking_sphinx/connection.rb +14 -0
- data/lib/thinking_sphinx/core.rb +1 -0
- data/lib/thinking_sphinx/core/index.rb +5 -9
- data/lib/thinking_sphinx/core/property.rb +13 -0
- data/lib/thinking_sphinx/middlewares/sphinxql.rb +1 -1
- data/lib/thinking_sphinx/rake_interface.rb +28 -5
- data/lib/thinking_sphinx/real_time.rb +1 -0
- data/lib/thinking_sphinx/real_time/attribute.rb +10 -0
- data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +3 -14
- data/lib/thinking_sphinx/real_time/field.rb +3 -1
- data/lib/thinking_sphinx/real_time/index.rb +29 -2
- data/lib/thinking_sphinx/real_time/index/template.rb +6 -5
- data/lib/thinking_sphinx/real_time/interpreter.rb +4 -0
- data/lib/thinking_sphinx/real_time/property.rb +2 -0
- data/lib/thinking_sphinx/real_time/transcriber.rb +37 -0
- data/lib/thinking_sphinx/tasks.rb +6 -5
- data/spec/acceptance/facets_spec.rb +2 -1
- data/spec/acceptance/index_options_spec.rb +20 -0
- data/spec/acceptance/searching_within_a_model_spec.rb +0 -1
- data/spec/acceptance/support/sphinx_helpers.rb +3 -0
- data/spec/internal/app/indices/product_index.rb +3 -3
- data/spec/thinking_sphinx/active_record/sql_source_spec.rb +14 -9
- data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +1 -1
- data/spec/thinking_sphinx/real_time/attribute_spec.rb +2 -2
- data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +3 -2
- data/spec/thinking_sphinx/real_time/field_spec.rb +4 -4
- data/spec/thinking_sphinx/real_time/index_spec.rb +9 -4
- data/thinking-sphinx.gemspec +4 -3
- metadata +42 -7
data/Gemfile
CHANGED
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.
|
data/lib/thinking_sphinx.rb
CHANGED
|
@@ -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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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, :
|
|
9
|
+
add_field class_column, :sphinx_internal_class_name
|
|
10
10
|
|
|
11
|
-
add_attribute :id,
|
|
12
|
-
add_attribute
|
|
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
|
-
|
|
28
|
+
searchd.workers = 'threads'
|
|
29
29
|
|
|
30
30
|
@offsets = {}
|
|
31
31
|
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)
|
data/lib/thinking_sphinx/core.rb
CHANGED
|
@@ -7,10 +7,11 @@ module ThinkingSphinx::Core::Index
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def initialize(reference, options = {})
|
|
10
|
-
@reference
|
|
11
|
-
@docinfo
|
|
12
|
-
@
|
|
13
|
-
@
|
|
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
|
|
@@ -69,7 +69,7 @@ class ThinkingSphinx::Middlewares::SphinxQL <
|
|
|
69
69
|
|
|
70
70
|
def extended_query
|
|
71
71
|
conditions = options[:conditions] || {}
|
|
72
|
-
conditions[:
|
|
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 #{
|
|
4
|
-
|
|
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
|
|
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
|
|
63
|
+
def configuration
|
|
41
64
|
ThinkingSphinx::Configuration.instance
|
|
42
65
|
end
|
|
43
66
|
|
|
44
67
|
def controller
|
|
45
|
-
|
|
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'
|
|
@@ -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
|
-
|
|
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
|
|
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 ||=
|
|
21
|
+
@indices ||= configuration.indices_for_references reference
|
|
33
22
|
end
|
|
34
23
|
|
|
35
24
|
def real_time_indices?
|
|
@@ -1,17 +1,40 @@
|
|
|
1
1
|
class ThinkingSphinx::RealTime::Index < Riddle::Configuration::RealtimeIndex
|
|
2
2
|
include ThinkingSphinx::Core::Index
|
|
3
3
|
|
|
4
|
-
|
|
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
|
|
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, :
|
|
9
|
+
add_field class_column, :sphinx_internal_class_name
|
|
10
10
|
|
|
11
|
-
add_attribute :id,
|
|
12
|
-
add_attribute
|
|
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
|
|
|
@@ -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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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).
|
|
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 == '
|
|
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 == '
|
|
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(:
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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('
|
|
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
|
-
|
|
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
|
data/thinking-sphinx.gemspec
CHANGED
|
@@ -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
|
|
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 '
|
|
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
|
-
|
|
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
|
|
5
|
-
prerelease:
|
|
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:
|
|
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.
|
|
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.
|
|
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:
|
|
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:
|