warp-thinking-sphinx 1.3.13 → 1.3.16
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/README.textile +2 -0
- data/VERSION +1 -1
- data/features/attribute_updates.feature +1 -0
- data/features/facets_across_model.feature +2 -2
- data/features/handling_edits.feature +1 -1
- data/features/support/db/fixtures/comments.rb +1 -1
- data/features/support/models/beta.rb +1 -1
- data/lib/thinking_sphinx.rb +15 -6
- data/lib/thinking_sphinx/active_record/has_many_association.rb +34 -11
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +4 -0
- data/lib/thinking_sphinx/attribute.rb +41 -21
- data/lib/thinking_sphinx/auto_version.rb +1 -1
- data/lib/thinking_sphinx/configuration.rb +18 -7
- data/lib/thinking_sphinx/context.rb +1 -7
- data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
- data/lib/thinking_sphinx/field.rb +3 -4
- data/lib/thinking_sphinx/property.rb +7 -1
- data/lib/thinking_sphinx/search.rb +10 -2
- data/lib/thinking_sphinx/source/internal_properties.rb +2 -1
- data/spec/thinking_sphinx/active_record/delta_spec.rb +1 -1
- data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +24 -2
- data/spec/thinking_sphinx/attribute_spec.rb +31 -45
- data/spec/thinking_sphinx/auto_version_spec.rb +5 -5
- data/spec/thinking_sphinx/configuration_spec.rb +37 -1
- data/spec/thinking_sphinx/field_spec.rb +0 -41
- data/spec/thinking_sphinx/search_spec.rb +26 -1
- data/tasks/distribution.rb +2 -2
- metadata +38 -19
data/README.textile
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.3.
|
|
1
|
+
1.3.16
|
|
@@ -5,7 +5,7 @@ Feature: Search and browse across models by their defined facets
|
|
|
5
5
|
When I am requesting facet results
|
|
6
6
|
And I want all possible attributes
|
|
7
7
|
Then I should have valid facet results
|
|
8
|
-
And I should have
|
|
8
|
+
And I should have 12 facets
|
|
9
9
|
And I should have the facet Class
|
|
10
10
|
And the Class facet should have a "Person" key
|
|
11
11
|
And I should have the facet Gender
|
|
@@ -19,7 +19,7 @@ Feature: Search and browse across models by their defined facets
|
|
|
19
19
|
When I am requesting facet results
|
|
20
20
|
And I want all possible attributes
|
|
21
21
|
And I don't want classes included
|
|
22
|
-
Then I should have
|
|
22
|
+
Then I should have 11 facets
|
|
23
23
|
And I should not have the facet Class
|
|
24
24
|
|
|
25
25
|
Scenario: Requesting facets common to all indexed models
|
|
@@ -14,7 +14,7 @@ Feature: Keeping Sphinx in line with model changes when requested
|
|
|
14
14
|
And I search for two
|
|
15
15
|
Then I should get 1 result
|
|
16
16
|
|
|
17
|
-
Scenario: Not
|
|
17
|
+
Scenario: Not returning an instance from old data if there is a delta
|
|
18
18
|
Given Sphinx is running
|
|
19
19
|
And I am searching on betas
|
|
20
20
|
When I search for two
|
data/lib/thinking_sphinx.rb
CHANGED
|
@@ -63,17 +63,26 @@ module ThinkingSphinx
|
|
|
63
63
|
# The collection of indexed models. Keep in mind that Rails lazily loads
|
|
64
64
|
# its classes, so this may not actually be populated with _all_ the models
|
|
65
65
|
# that have Sphinx indexes.
|
|
66
|
+
@@sphinx_mutex = Mutex.new
|
|
67
|
+
@@context = nil
|
|
68
|
+
|
|
66
69
|
def self.context
|
|
67
|
-
if
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
if @@context.nil?
|
|
71
|
+
@@sphinx_mutex.synchronize do
|
|
72
|
+
if @@context.nil?
|
|
73
|
+
@@context = ThinkingSphinx::Context.new
|
|
74
|
+
@@context.prepare
|
|
75
|
+
end
|
|
76
|
+
end
|
|
70
77
|
end
|
|
71
78
|
|
|
72
|
-
|
|
79
|
+
@@context
|
|
73
80
|
end
|
|
74
|
-
|
|
81
|
+
|
|
75
82
|
def self.reset_context!
|
|
76
|
-
|
|
83
|
+
@@sphinx_mutex.synchronize do
|
|
84
|
+
@@context = nil
|
|
85
|
+
end
|
|
77
86
|
end
|
|
78
87
|
|
|
79
88
|
def self.unique_id_expression(offset = nil)
|
|
@@ -2,27 +2,50 @@ module ThinkingSphinx
|
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
module HasManyAssociation
|
|
4
4
|
def search(*args)
|
|
5
|
+
options = args.extract_options!
|
|
6
|
+
options[:with] ||= {}
|
|
7
|
+
options[:with].merge! default_filter
|
|
8
|
+
|
|
9
|
+
args << options
|
|
10
|
+
@reflection.klass.search(*args)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def method_missing(method, *args, &block)
|
|
14
|
+
if responds_to_scope(method)
|
|
15
|
+
@reflection.klass.
|
|
16
|
+
search(:with => default_filter).
|
|
17
|
+
send(method, *args, &block)
|
|
18
|
+
else
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def attribute_for_foreign_key
|
|
5
26
|
foreign_key = @reflection.primary_key_name
|
|
6
27
|
stack = [@reflection.options[:through]].compact
|
|
7
28
|
|
|
8
|
-
|
|
29
|
+
@reflection.klass.define_indexes
|
|
9
30
|
(@reflection.klass.sphinx_indexes || []).each do |index|
|
|
10
31
|
attribute = index.attributes.detect { |attrib|
|
|
11
32
|
attrib.columns.length == 1 &&
|
|
12
33
|
attrib.columns.first.__name == foreign_key.to_sym
|
|
13
34
|
}
|
|
14
|
-
|
|
35
|
+
return attribute unless attribute.nil?
|
|
15
36
|
end
|
|
16
37
|
|
|
17
|
-
raise "Missing Attribute for Foreign Key #{foreign_key}"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
38
|
+
raise "Missing Attribute for Foreign Key #{foreign_key}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def default_filter
|
|
42
|
+
{attribute_for_foreign_key.unique_name => @owner.id}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def responds_to_scope(scope)
|
|
46
|
+
@reflection.klass.respond_to?(:sphinx_scopes) &&
|
|
47
|
+
@reflection.klass.sphinx_scopes.include?(scope)
|
|
25
48
|
end
|
|
26
49
|
end
|
|
27
50
|
end
|
|
28
|
-
end
|
|
51
|
+
end
|
|
@@ -93,19 +93,18 @@ module ThinkingSphinx
|
|
|
93
93
|
|
|
94
94
|
separator = all_ints? || all_datetimes? || @crc ? ',' : ' '
|
|
95
95
|
|
|
96
|
-
clause =
|
|
97
|
-
part = column_with_prefix(column)
|
|
96
|
+
clause = columns_with_prefixes.collect { |column|
|
|
98
97
|
case type
|
|
99
98
|
when :string
|
|
100
|
-
adapter.convert_nulls(
|
|
99
|
+
adapter.convert_nulls(column)
|
|
101
100
|
when :datetime
|
|
102
|
-
adapter.cast_to_datetime(
|
|
101
|
+
adapter.cast_to_datetime(column)
|
|
103
102
|
when :multi
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
column = adapter.cast_to_datetime(column) if is_many_datetimes?
|
|
104
|
+
column = adapter.convert_nulls(column, '0') if is_many_ints?
|
|
105
|
+
column
|
|
107
106
|
else
|
|
108
|
-
|
|
107
|
+
column
|
|
109
108
|
end
|
|
110
109
|
}.join(', ')
|
|
111
110
|
|
|
@@ -122,7 +121,8 @@ module ThinkingSphinx
|
|
|
122
121
|
:string => :sql_attr_str2ordinal,
|
|
123
122
|
:float => :sql_attr_float,
|
|
124
123
|
:boolean => :sql_attr_bool,
|
|
125
|
-
:integer => :sql_attr_uint
|
|
124
|
+
:integer => :sql_attr_uint,
|
|
125
|
+
:bigint => :sql_attr_bigint
|
|
126
126
|
}[type]
|
|
127
127
|
end
|
|
128
128
|
|
|
@@ -182,7 +182,7 @@ module ThinkingSphinx
|
|
|
182
182
|
object = object.send(method)
|
|
183
183
|
return sphinx_value(nil) if object.nil?
|
|
184
184
|
}
|
|
185
|
-
|
|
185
|
+
|
|
186
186
|
sphinx_value object.send(column.__name)
|
|
187
187
|
end
|
|
188
188
|
|
|
@@ -300,19 +300,11 @@ WHERE #{@source.index.delta_object.clause(model, true)})
|
|
|
300
300
|
is_many? && all_strings?
|
|
301
301
|
end
|
|
302
302
|
|
|
303
|
-
def type_from_database
|
|
304
|
-
klass = @associations.values.flatten.first ?
|
|
305
|
-
@associations.values.flatten.first.reflection.klass : @model
|
|
306
|
-
|
|
307
|
-
column = klass.columns.detect { |col|
|
|
308
|
-
@columns.collect { |c| c.__name.to_s }.include? col.name
|
|
309
|
-
}
|
|
310
|
-
column.nil? ? nil : column.type
|
|
311
|
-
end
|
|
312
|
-
|
|
313
303
|
def translated_type_from_database
|
|
314
304
|
case type_from_db = type_from_database
|
|
315
|
-
when :
|
|
305
|
+
when :integer
|
|
306
|
+
integer_type_from_db
|
|
307
|
+
when :datetime, :string, :float, :boolean
|
|
316
308
|
type_from_db
|
|
317
309
|
when :decimal
|
|
318
310
|
:float
|
|
@@ -330,6 +322,32 @@ block:
|
|
|
330
322
|
end
|
|
331
323
|
end
|
|
332
324
|
|
|
325
|
+
def type_from_database
|
|
326
|
+
column = column_from_db
|
|
327
|
+
column.nil? ? nil : column.type
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def integer_type_from_db
|
|
331
|
+
column = column_from_db
|
|
332
|
+
return nil if column.nil?
|
|
333
|
+
|
|
334
|
+
case column.sql_type
|
|
335
|
+
when adapter.bigint_pattern
|
|
336
|
+
:bigint
|
|
337
|
+
else
|
|
338
|
+
:integer
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def column_from_db
|
|
343
|
+
klass = @associations.values.flatten.first ?
|
|
344
|
+
@associations.values.flatten.first.reflection.klass : @model
|
|
345
|
+
|
|
346
|
+
klass.columns.detect { |col|
|
|
347
|
+
@columns.collect { |c| c.__name.to_s }.include? col.name
|
|
348
|
+
}
|
|
349
|
+
end
|
|
350
|
+
|
|
333
351
|
def all_of_type?(*column_types)
|
|
334
352
|
@columns.all? { |col|
|
|
335
353
|
klasses = @associations[col].empty? ? [@model] :
|
|
@@ -351,6 +369,8 @@ block:
|
|
|
351
369
|
value.to_i
|
|
352
370
|
when Date
|
|
353
371
|
value.to_time.to_i
|
|
372
|
+
when String
|
|
373
|
+
value.to_crc32
|
|
354
374
|
else
|
|
355
375
|
value
|
|
356
376
|
end
|
|
@@ -68,6 +68,7 @@ module ThinkingSphinx
|
|
|
68
68
|
:app_root, :model_directories, :delayed_job_priority
|
|
69
69
|
|
|
70
70
|
attr_accessor :source_options, :index_options
|
|
71
|
+
attr_accessor :version
|
|
71
72
|
|
|
72
73
|
attr_reader :environment, :configuration, :controller
|
|
73
74
|
|
|
@@ -93,8 +94,6 @@ module ThinkingSphinx
|
|
|
93
94
|
end
|
|
94
95
|
|
|
95
96
|
@configuration = Riddle::Configuration.new
|
|
96
|
-
@configuration.searchd.address = "127.0.0.1"
|
|
97
|
-
@configuration.searchd.port = 9312
|
|
98
97
|
@configuration.searchd.pid_file = "#{self.app_root}/log/searchd.#{environment}.pid"
|
|
99
98
|
@configuration.searchd.log = "#{self.app_root}/log/searchd.log"
|
|
100
99
|
@configuration.searchd.query_log = "#{self.app_root}/log/searchd.query.log"
|
|
@@ -102,6 +101,8 @@ module ThinkingSphinx
|
|
|
102
101
|
@controller = Riddle::Controller.new @configuration,
|
|
103
102
|
"#{self.app_root}/config/#{environment}.sphinx.conf"
|
|
104
103
|
|
|
104
|
+
self.address = "127.0.0.1"
|
|
105
|
+
self.port = 9312
|
|
105
106
|
self.database_yml_file = "#{self.app_root}/config/database.yml"
|
|
106
107
|
self.searchd_file_path = "#{self.app_root}/db/sphinx/#{environment}"
|
|
107
108
|
self.allow_star = false
|
|
@@ -114,15 +115,23 @@ module ThinkingSphinx
|
|
|
114
115
|
:charset_type => "utf-8"
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
self.version = nil
|
|
117
119
|
parse_config
|
|
120
|
+
self.version ||= @controller.sphinx_version
|
|
118
121
|
|
|
119
122
|
self
|
|
120
123
|
end
|
|
121
124
|
|
|
122
125
|
def self.environment
|
|
123
|
-
Thread.current[:thinking_sphinx_environment] ||=
|
|
124
|
-
defined?(Merb)
|
|
125
|
-
|
|
126
|
+
Thread.current[:thinking_sphinx_environment] ||= begin
|
|
127
|
+
if defined?(Merb)
|
|
128
|
+
Merb.environment
|
|
129
|
+
elsif defined?(RAILS_ENV)
|
|
130
|
+
RAILS_ENV
|
|
131
|
+
else
|
|
132
|
+
ENV['RAILS_ENV'] || 'development'
|
|
133
|
+
end
|
|
134
|
+
end
|
|
126
135
|
end
|
|
127
136
|
|
|
128
137
|
def environment
|
|
@@ -150,18 +159,20 @@ module ThinkingSphinx
|
|
|
150
159
|
end
|
|
151
160
|
|
|
152
161
|
def address
|
|
153
|
-
@
|
|
162
|
+
@address
|
|
154
163
|
end
|
|
155
164
|
|
|
156
165
|
def address=(address)
|
|
166
|
+
@address = address
|
|
157
167
|
@configuration.searchd.address = address
|
|
158
168
|
end
|
|
159
169
|
|
|
160
170
|
def port
|
|
161
|
-
@
|
|
171
|
+
@port
|
|
162
172
|
end
|
|
163
173
|
|
|
164
174
|
def port=(port)
|
|
175
|
+
@port = port
|
|
165
176
|
@configuration.searchd.port = port
|
|
166
177
|
end
|
|
167
178
|
|
|
@@ -7,7 +7,7 @@ class ThinkingSphinx::Context
|
|
|
7
7
|
|
|
8
8
|
def prepare
|
|
9
9
|
load_models
|
|
10
|
-
add_indexed_models
|
|
10
|
+
add_indexed_models
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def define_indexes
|
|
@@ -33,12 +33,6 @@ class ThinkingSphinx::Context
|
|
|
33
33
|
|
|
34
34
|
private
|
|
35
35
|
|
|
36
|
-
def cached?
|
|
37
|
-
defined?(Rails) &&
|
|
38
|
-
Rails::VERSION::STRING.to_f > 2.1 &&
|
|
39
|
-
Rails.configuration.cache_classes
|
|
40
|
-
end
|
|
41
|
-
|
|
42
36
|
def add_indexed_models
|
|
43
37
|
Object.subclasses_of(ActiveRecord::Base).each do |klass|
|
|
44
38
|
add_indexed_model klass if klass.has_sphinx_indexes?
|
|
@@ -44,7 +44,7 @@ module ThinkingSphinx
|
|
|
44
44
|
config = ThinkingSphinx::Configuration.instance
|
|
45
45
|
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
|
46
46
|
|
|
47
|
-
output = `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} #{rotate} #{model.delta_index_names.join(' ')}`
|
|
47
|
+
output = `#{config.bin_path}#{config.indexer_binary_name} --config '#{config.config_file}' #{rotate} #{model.delta_index_names.join(' ')}`
|
|
48
48
|
puts(output) unless ThinkingSphinx.suppress_delta_output?
|
|
49
49
|
end
|
|
50
50
|
|
|
@@ -69,13 +69,12 @@ module ThinkingSphinx
|
|
|
69
69
|
# multiple data values (has_many or has_and_belongs_to_many associations).
|
|
70
70
|
#
|
|
71
71
|
def to_select_sql
|
|
72
|
-
clause =
|
|
73
|
-
column_with_prefix(column)
|
|
74
|
-
}.join(', ')
|
|
72
|
+
clause = columns_with_prefixes.join(', ')
|
|
75
73
|
|
|
76
74
|
clause = adapter.concatenate(clause) if concat_ws?
|
|
75
|
+
#~ clause = adapter.group_concatenate(clause) if is_many?
|
|
77
76
|
|
|
78
|
-
"#{
|
|
77
|
+
"#{clause} AS #{quote_column(unique_name)}"
|
|
79
78
|
end
|
|
80
79
|
end
|
|
81
80
|
end
|
|
@@ -137,10 +137,16 @@ module ThinkingSphinx
|
|
|
137
137
|
assoc.has_column?(column.__name) ?
|
|
138
138
|
"#{quote_with_table(assoc.join.aliased_table_name, column.__name)}" :
|
|
139
139
|
nil
|
|
140
|
-
}.compact
|
|
140
|
+
}.compact
|
|
141
141
|
end
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
+
def columns_with_prefixes
|
|
145
|
+
@columns.collect { |column|
|
|
146
|
+
column_with_prefix column
|
|
147
|
+
}.flatten
|
|
148
|
+
end
|
|
149
|
+
|
|
144
150
|
# Gets a stack of associations for a specific path.
|
|
145
151
|
#
|
|
146
152
|
def association_stack(path, parent = nil)
|
|
@@ -73,6 +73,8 @@ module ThinkingSphinx
|
|
|
73
73
|
@array = []
|
|
74
74
|
@options = args.extract_options!
|
|
75
75
|
@args = args
|
|
76
|
+
|
|
77
|
+
populate if @options[:populate]
|
|
76
78
|
end
|
|
77
79
|
|
|
78
80
|
def to_a
|
|
@@ -80,6 +82,12 @@ module ThinkingSphinx
|
|
|
80
82
|
@array
|
|
81
83
|
end
|
|
82
84
|
|
|
85
|
+
def freeze
|
|
86
|
+
populate
|
|
87
|
+
@array.freeze
|
|
88
|
+
self
|
|
89
|
+
end
|
|
90
|
+
|
|
83
91
|
# Indication of whether the request has been made to Sphinx for the search
|
|
84
92
|
# query.
|
|
85
93
|
#
|
|
@@ -123,8 +131,8 @@ module ThinkingSphinx
|
|
|
123
131
|
# @param [Symbol] method The method name
|
|
124
132
|
# @return [Boolean] true if either Search or Array responds to the method.
|
|
125
133
|
#
|
|
126
|
-
def respond_to?(method)
|
|
127
|
-
super || @array.respond_to?(method)
|
|
134
|
+
def respond_to?(method, include_private = false)
|
|
135
|
+
super || @array.respond_to?(method, include_private)
|
|
128
136
|
end
|
|
129
137
|
|
|
130
138
|
# The current page number of the result set. Defaults to 1 if no page was
|
|
@@ -2,7 +2,8 @@ module ThinkingSphinx
|
|
|
2
2
|
class Source
|
|
3
3
|
module InternalProperties
|
|
4
4
|
def add_internal_attributes_and_facets
|
|
5
|
-
add_internal_attribute :sphinx_internal_id,
|
|
5
|
+
add_internal_attribute :sphinx_internal_id, nil,
|
|
6
|
+
@model.primary_key_for_sphinx.to_sym
|
|
6
7
|
add_internal_attribute :class_crc, :integer, crc_column, true
|
|
7
8
|
add_internal_attribute :subclass_crcs, :multi, subclasses_to_s
|
|
8
9
|
add_internal_attribute :sphinx_deleted, :integer, "0"
|
|
@@ -106,7 +106,7 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
|
|
|
106
106
|
|
|
107
107
|
it "should call indexer for the delta index" do
|
|
108
108
|
Person.sphinx_indexes.first.delta_object.should_receive(:`).with(
|
|
109
|
-
"#{ThinkingSphinx::Configuration.instance.bin_path}indexer --config #{ThinkingSphinx::Configuration.instance.config_file} --rotate person_delta"
|
|
109
|
+
"#{ThinkingSphinx::Configuration.instance.bin_path}indexer --config '#{ThinkingSphinx::Configuration.instance.config_file}' --rotate person_delta"
|
|
110
110
|
)
|
|
111
111
|
|
|
112
112
|
@person.send(:index_delta)
|
|
@@ -21,7 +21,13 @@ describe 'ThinkingSphinx::ActiveRecord::HasManyAssociation' do
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
@person.friendships.search "test"
|
|
24
|
-
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should define indexes for the reflection class" do
|
|
27
|
+
Friendship.should_receive(:define_indexes)
|
|
28
|
+
|
|
29
|
+
@person.friendships.search 'test'
|
|
30
|
+
end
|
|
25
31
|
end
|
|
26
32
|
|
|
27
33
|
describe "search method for has_many :through" do
|
|
@@ -46,4 +52,20 @@ describe 'ThinkingSphinx::ActiveRecord::HasManyAssociation' do
|
|
|
46
52
|
@person.friends.search "test"
|
|
47
53
|
end
|
|
48
54
|
end
|
|
49
|
-
|
|
55
|
+
|
|
56
|
+
describe 'filtering sphinx scopes' do
|
|
57
|
+
before :each do
|
|
58
|
+
Friendship.stub!(:search => Friendship)
|
|
59
|
+
|
|
60
|
+
@person = Person.find(:first)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should add a filter for the attribute in a sphinx scope call" do
|
|
64
|
+
Friendship.should_receive(:search).with do |options|
|
|
65
|
+
options[:with][:person_id].should == @person.id
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
@person.friendships.reverse
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -47,47 +47,6 @@ describe ThinkingSphinx::Attribute do
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
describe '#column_with_prefix' do
|
|
51
|
-
before :each do
|
|
52
|
-
@attribute = ThinkingSphinx::Attribute.new @source, [
|
|
53
|
-
ThinkingSphinx::Index::FauxColumn.new(:col_name)
|
|
54
|
-
]
|
|
55
|
-
@attribute.columns.each { |col| @attribute.associations[col] = [] }
|
|
56
|
-
@attribute.model = Person
|
|
57
|
-
|
|
58
|
-
@first_join = Object.new
|
|
59
|
-
@first_join.stub!(:aliased_table_name => "tabular")
|
|
60
|
-
@second_join = Object.new
|
|
61
|
-
@second_join.stub!(:aliased_table_name => "data")
|
|
62
|
-
|
|
63
|
-
@first_assoc = ThinkingSphinx::Association.new nil, nil
|
|
64
|
-
@first_assoc.stub!(:join => @first_join, :has_column? => true)
|
|
65
|
-
@second_assoc = ThinkingSphinx::Association.new nil, nil
|
|
66
|
-
@second_assoc.stub!(:join => @second_join, :has_column? => true)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it "should return the column name if the column is a string" do
|
|
70
|
-
@attribute.columns = [ThinkingSphinx::Index::FauxColumn.new("string")]
|
|
71
|
-
@attribute.send(:column_with_prefix, @attribute.columns.first).should == "string"
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it "should return the column with model's table prefix if there's no associations for the column" do
|
|
75
|
-
@attribute.send(:column_with_prefix, @attribute.columns.first).should == "`people`.`col_name`"
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
it "should return the column with its join table prefix if an association exists" do
|
|
79
|
-
column = @attribute.columns.first
|
|
80
|
-
@attribute.associations[column] = [@first_assoc]
|
|
81
|
-
@attribute.send(:column_with_prefix, column).should == "`tabular`.`col_name`"
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
it "should return multiple columns concatenated if more than one association exists" do
|
|
85
|
-
column = @attribute.columns.first
|
|
86
|
-
@attribute.associations[column] = [@first_assoc, @second_assoc]
|
|
87
|
-
@attribute.send(:column_with_prefix, column).should == "`tabular`.`col_name`, `data`.`col_name`"
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
50
|
describe '#to_select_sql' do
|
|
92
51
|
it "should convert a mixture of dates and datetimes to timestamps" do
|
|
93
52
|
attribute = ThinkingSphinx::Attribute.new(@source,
|
|
@@ -99,6 +58,16 @@ describe ThinkingSphinx::Attribute do
|
|
|
99
58
|
|
|
100
59
|
attribute.to_select_sql.should == "CONCAT_WS(',', UNIX_TIMESTAMP(`friendships`.`created_at`), UNIX_TIMESTAMP(`friendships`.`created_on`)) AS `times`"
|
|
101
60
|
end
|
|
61
|
+
|
|
62
|
+
it "should handle columns which don't exist for polymorphic joins" do
|
|
63
|
+
attribute = ThinkingSphinx::Attribute.new(@source,
|
|
64
|
+
[ ThinkingSphinx::Index::FauxColumn.new(:team, :name),
|
|
65
|
+
ThinkingSphinx::Index::FauxColumn.new(:team, :league) ],
|
|
66
|
+
:as => :team
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
attribute.to_select_sql.should == "CONCAT_WS(' ', IFNULL(`cricket_teams`.`name`, ''), IFNULL(`football_teams`.`name`, ''), IFNULL(`football_teams`.`league`, '')) AS `team`"
|
|
70
|
+
end
|
|
102
71
|
end
|
|
103
72
|
|
|
104
73
|
describe '#is_many?' do
|
|
@@ -183,15 +152,15 @@ describe ThinkingSphinx::Attribute do
|
|
|
183
152
|
|
|
184
153
|
it "should return the column type from the database if not :multi or more than one association" do
|
|
185
154
|
@column.send(:instance_variable_set, :@name, "birthday")
|
|
186
|
-
@attribute.
|
|
155
|
+
@attribute.type.should == :datetime
|
|
187
156
|
|
|
188
157
|
@attribute.send(:instance_variable_set, :@type, nil)
|
|
189
158
|
@column.send(:instance_variable_set, :@name, "first_name")
|
|
190
|
-
@attribute.
|
|
159
|
+
@attribute.type.should == :string
|
|
191
160
|
|
|
192
161
|
@attribute.send(:instance_variable_set, :@type, nil)
|
|
193
162
|
@column.send(:instance_variable_set, :@name, "id")
|
|
194
|
-
@attribute.
|
|
163
|
+
@attribute.type.should == :integer
|
|
195
164
|
end
|
|
196
165
|
|
|
197
166
|
it "should return :multi if the columns return multiple datetimes" do
|
|
@@ -200,6 +169,15 @@ describe ThinkingSphinx::Attribute do
|
|
|
200
169
|
|
|
201
170
|
@attribute.type.should == :multi
|
|
202
171
|
end
|
|
172
|
+
|
|
173
|
+
it "should return :bigint for 64bit integers" do
|
|
174
|
+
Person.columns.detect { |col|
|
|
175
|
+
col.name == 'id'
|
|
176
|
+
}.stub!(:sql_type => 'BIGINT(20)')
|
|
177
|
+
@column.send(:instance_variable_set, :@name, 'id')
|
|
178
|
+
|
|
179
|
+
@attribute.type.should == :bigint
|
|
180
|
+
end
|
|
203
181
|
end
|
|
204
182
|
|
|
205
183
|
describe '#all_ints?' do
|
|
@@ -558,5 +536,13 @@ describe ThinkingSphinx::Attribute do
|
|
|
558
536
|
@instance.stub!(:assoc_name => stub('object', :id => 42))
|
|
559
537
|
@attribute.live_value(@instance).should == 42
|
|
560
538
|
end
|
|
539
|
+
|
|
540
|
+
it "should translate crc strings to their integer values" do
|
|
541
|
+
@attribute = ThinkingSphinx::Attribute.new @source, [
|
|
542
|
+
stub('column', :__stack => [], :__name => "col_name")
|
|
543
|
+
], :crc => true, :type => :string
|
|
544
|
+
@instance.stub!(:col_name => 'foo')
|
|
545
|
+
@attribute.live_value(@instance).should == 'foo'.to_crc32
|
|
546
|
+
end
|
|
561
547
|
end
|
|
562
|
-
end
|
|
548
|
+
end
|
|
@@ -3,14 +3,14 @@ require 'spec/spec_helper'
|
|
|
3
3
|
describe ThinkingSphinx::AutoVersion do
|
|
4
4
|
describe '.detect' do
|
|
5
5
|
before :each do
|
|
6
|
-
@
|
|
6
|
+
@config = ThinkingSphinx::Configuration.instance
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
it "should require 0.9.8 if that is the detected version" do
|
|
10
10
|
ThinkingSphinx::AutoVersion.should_receive(:require).
|
|
11
11
|
with('riddle/0.9.8')
|
|
12
12
|
|
|
13
|
-
@
|
|
13
|
+
@config.stub!(:version => '0.9.8')
|
|
14
14
|
ThinkingSphinx::AutoVersion.detect
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -18,21 +18,21 @@ describe ThinkingSphinx::AutoVersion do
|
|
|
18
18
|
ThinkingSphinx::AutoVersion.should_receive(:require).
|
|
19
19
|
with('riddle/0.9.9')
|
|
20
20
|
|
|
21
|
-
@
|
|
21
|
+
@config.stub!(:version => '0.9.9')
|
|
22
22
|
ThinkingSphinx::AutoVersion.detect
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
it "should output a warning if the detected version is something else" do
|
|
26
26
|
STDERR.should_receive(:puts)
|
|
27
27
|
|
|
28
|
-
@
|
|
28
|
+
@config.stub!(:version => '0.9.7')
|
|
29
29
|
ThinkingSphinx::AutoVersion.detect
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "should output a warning if the version cannot be determined" do
|
|
33
33
|
STDERR.should_receive(:puts)
|
|
34
34
|
|
|
35
|
-
@
|
|
35
|
+
@config.stub!(:version => nil)
|
|
36
36
|
ThinkingSphinx::AutoVersion.detect
|
|
37
37
|
end
|
|
38
38
|
end
|
|
@@ -17,7 +17,15 @@ describe ThinkingSphinx::Configuration do
|
|
|
17
17
|
Merb.stub!(:environment => "merb_production")
|
|
18
18
|
ThinkingSphinx::Configuration.environment.should == "merb_production"
|
|
19
19
|
|
|
20
|
-
Object.send
|
|
20
|
+
Object.send :remove_const, :Merb
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should use RAILS_ENV if set" do
|
|
24
|
+
RAILS_ENV = 'global_rails'
|
|
25
|
+
|
|
26
|
+
ThinkingSphinx::Configuration.environment.should == 'global_rails'
|
|
27
|
+
|
|
28
|
+
Object.send :remove_const, :RAILS_ENV
|
|
21
29
|
end
|
|
22
30
|
|
|
23
31
|
it "should use the Rails environment value if set" do
|
|
@@ -29,6 +37,34 @@ describe ThinkingSphinx::Configuration do
|
|
|
29
37
|
ThinkingSphinx::Configuration.environment.should == "development"
|
|
30
38
|
end
|
|
31
39
|
end
|
|
40
|
+
|
|
41
|
+
describe '#version' do
|
|
42
|
+
before :each do
|
|
43
|
+
@config = ThinkingSphinx::Configuration.instance
|
|
44
|
+
@config.reset
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should use the given version from sphinx.yml if there is one" do
|
|
48
|
+
open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
|
|
49
|
+
f.write YAML.dump({'development' => {'version' => '0.9.7'}})
|
|
50
|
+
end
|
|
51
|
+
@config.reset
|
|
52
|
+
|
|
53
|
+
@config.version.should == '0.9.7'
|
|
54
|
+
|
|
55
|
+
FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should detect the version from Riddle otherwise" do
|
|
59
|
+
controller = @config.controller
|
|
60
|
+
controller.stub!(:sphinx_version => '0.9.6')
|
|
61
|
+
|
|
62
|
+
Riddle::Controller.stub!(:new => controller)
|
|
63
|
+
@config.reset
|
|
64
|
+
|
|
65
|
+
@config.version.should == '0.9.6'
|
|
66
|
+
end
|
|
67
|
+
end
|
|
32
68
|
|
|
33
69
|
describe "parse_config method" do
|
|
34
70
|
before :each do
|
|
@@ -77,47 +77,6 @@ describe ThinkingSphinx::Field do
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
describe "column_with_prefix method" do
|
|
81
|
-
before :each do
|
|
82
|
-
@field = ThinkingSphinx::Field.new @source, [
|
|
83
|
-
ThinkingSphinx::Index::FauxColumn.new(:col_name)
|
|
84
|
-
]
|
|
85
|
-
@field.columns.each { |col| @field.associations[col] = [] }
|
|
86
|
-
@field.model = Person
|
|
87
|
-
|
|
88
|
-
@first_join = Object.new
|
|
89
|
-
@first_join.stub!(:aliased_table_name => "tabular")
|
|
90
|
-
@second_join = Object.new
|
|
91
|
-
@second_join.stub!(:aliased_table_name => "data")
|
|
92
|
-
|
|
93
|
-
@first_assoc = ThinkingSphinx::Association.new nil, nil
|
|
94
|
-
@first_assoc.stub!(:join => @first_join, :has_column? => true)
|
|
95
|
-
@second_assoc = ThinkingSphinx::Association.new nil, nil
|
|
96
|
-
@second_assoc.stub!(:join => @second_join, :has_column? => true)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
it "should return the column name if the column is a string" do
|
|
100
|
-
@field.columns = [ThinkingSphinx::Index::FauxColumn.new("string")]
|
|
101
|
-
@field.send(:column_with_prefix, @field.columns.first).should == "string"
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
it "should return the column with model's table prefix if there's no associations for the column" do
|
|
105
|
-
@field.send(:column_with_prefix, @field.columns.first).should == "`people`.`col_name`"
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
it "should return the column with its join table prefix if an association exists" do
|
|
109
|
-
column = @field.columns.first
|
|
110
|
-
@field.associations[column] = [@first_assoc]
|
|
111
|
-
@field.send(:column_with_prefix, column).should == "`tabular`.`col_name`"
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
it "should return multiple columns concatenated if more than one association exists" do
|
|
115
|
-
column = @field.columns.first
|
|
116
|
-
@field.associations[column] = [@first_assoc, @second_assoc]
|
|
117
|
-
@field.send(:column_with_prefix, column).should == "`tabular`.`col_name`, `data`.`col_name`"
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
80
|
describe "is_many? method" do
|
|
122
81
|
before :each do
|
|
123
82
|
@assoc_a = stub('assoc', :is_many? => true)
|
|
@@ -43,7 +43,12 @@ describe ThinkingSphinx::Search do
|
|
|
43
43
|
|
|
44
44
|
it "should be true once the client request has been made" do
|
|
45
45
|
@search.first
|
|
46
|
-
@search.
|
|
46
|
+
@search.should be_populated
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should be populated if :populate is set to true" do
|
|
50
|
+
search = ThinkingSphinx::Search.new(:populate => true)
|
|
51
|
+
search.should be_populated
|
|
47
52
|
end
|
|
48
53
|
end
|
|
49
54
|
|
|
@@ -1172,6 +1177,26 @@ describe ThinkingSphinx::Search do
|
|
|
1172
1177
|
}.should_not be_nil
|
|
1173
1178
|
end
|
|
1174
1179
|
end
|
|
1180
|
+
|
|
1181
|
+
describe '#freeze' do
|
|
1182
|
+
before :each do
|
|
1183
|
+
@search = ThinkingSphinx::Search.new
|
|
1184
|
+
end
|
|
1185
|
+
|
|
1186
|
+
it "should populate the result set" do
|
|
1187
|
+
@search.freeze
|
|
1188
|
+
@search.should be_populated
|
|
1189
|
+
end
|
|
1190
|
+
|
|
1191
|
+
it "should freeze the underlying array" do
|
|
1192
|
+
@search.freeze
|
|
1193
|
+
@search.to_a.should be_frozen
|
|
1194
|
+
end
|
|
1195
|
+
|
|
1196
|
+
it "should return the Search object" do
|
|
1197
|
+
@search.freeze.should be_a(ThinkingSphinx::Search)
|
|
1198
|
+
end
|
|
1199
|
+
end
|
|
1175
1200
|
end
|
|
1176
1201
|
|
|
1177
1202
|
describe ThinkingSphinx::Search, "playing nice with Search model" do
|
data/tasks/distribution.rb
CHANGED
|
@@ -28,8 +28,8 @@ Jeweler::Tasks.new do |gem|
|
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
gem.add_dependency 'activerecord', '>= 1.15.6'
|
|
31
|
-
gem.add_dependency 'riddle', '>= 1.0.
|
|
32
|
-
gem.add_dependency 'after_commit', '>= 1.0.
|
|
31
|
+
gem.add_dependency 'riddle', '>= 1.0.10'
|
|
32
|
+
gem.add_dependency 'after_commit', '>= 1.0.6'
|
|
33
33
|
|
|
34
34
|
gem.post_install_message = <<-MESSAGE
|
|
35
35
|
If you're upgrading, you should read this:
|
metadata
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: warp-thinking-sphinx
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
4
|
+
prerelease: false
|
|
5
|
+
segments:
|
|
6
|
+
- 1
|
|
7
|
+
- 3
|
|
8
|
+
- 16
|
|
9
|
+
version: 1.3.16
|
|
5
10
|
platform: ruby
|
|
6
11
|
authors:
|
|
7
12
|
- Pat Allan
|
|
@@ -9,39 +14,51 @@ autorequire:
|
|
|
9
14
|
bindir: bin
|
|
10
15
|
cert_chain: []
|
|
11
16
|
|
|
12
|
-
date:
|
|
17
|
+
date: 2010-03-19 00:00:00 +13:00
|
|
13
18
|
default_executable:
|
|
14
19
|
dependencies:
|
|
15
20
|
- !ruby/object:Gem::Dependency
|
|
16
21
|
name: activerecord
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
prerelease: false
|
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
20
24
|
requirements:
|
|
21
25
|
- - ">="
|
|
22
26
|
- !ruby/object:Gem::Version
|
|
27
|
+
segments:
|
|
28
|
+
- 1
|
|
29
|
+
- 15
|
|
30
|
+
- 6
|
|
23
31
|
version: 1.15.6
|
|
24
|
-
|
|
32
|
+
type: :runtime
|
|
33
|
+
version_requirements: *id001
|
|
25
34
|
- !ruby/object:Gem::Dependency
|
|
26
35
|
name: riddle
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
prerelease: false
|
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
30
38
|
requirements:
|
|
31
39
|
- - ">="
|
|
32
40
|
- !ruby/object:Gem::Version
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
segments:
|
|
42
|
+
- 1
|
|
43
|
+
- 0
|
|
44
|
+
- 10
|
|
45
|
+
version: 1.0.10
|
|
46
|
+
type: :runtime
|
|
47
|
+
version_requirements: *id002
|
|
35
48
|
- !ruby/object:Gem::Dependency
|
|
36
49
|
name: after_commit
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
prerelease: false
|
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
40
52
|
requirements:
|
|
41
53
|
- - ">="
|
|
42
54
|
- !ruby/object:Gem::Version
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
segments:
|
|
56
|
+
- 1
|
|
57
|
+
- 0
|
|
58
|
+
- 6
|
|
59
|
+
version: 1.0.6
|
|
60
|
+
type: :runtime
|
|
61
|
+
version_requirements: *id003
|
|
45
62
|
description: A concise and easy-to-use Ruby library that connects ActiveRecord to the Sphinx search daemon, managing configuration, indexing and searching.
|
|
46
63
|
email: pat@freelancing-gods.com
|
|
47
64
|
executables: []
|
|
@@ -113,18 +130,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
113
130
|
requirements:
|
|
114
131
|
- - ">="
|
|
115
132
|
- !ruby/object:Gem::Version
|
|
133
|
+
segments:
|
|
134
|
+
- 0
|
|
116
135
|
version: "0"
|
|
117
|
-
version:
|
|
118
136
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
137
|
requirements:
|
|
120
138
|
- - ">="
|
|
121
139
|
- !ruby/object:Gem::Version
|
|
140
|
+
segments:
|
|
141
|
+
- 0
|
|
122
142
|
version: "0"
|
|
123
|
-
version:
|
|
124
143
|
requirements: []
|
|
125
144
|
|
|
126
145
|
rubyforge_project:
|
|
127
|
-
rubygems_version: 1.3.
|
|
146
|
+
rubygems_version: 1.3.6
|
|
128
147
|
signing_key:
|
|
129
148
|
specification_version: 3
|
|
130
149
|
summary: ActiveRecord/Rails Sphinx library
|