warp-thinking-sphinx 1.3.13 → 1.3.16
Sign up to get free protection for your applications and to get access to all the features.
- 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
|