thinking-sphinx 1.4.1 → 1.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +3 -0
- data/VERSION +1 -1
- data/features/facets.feature +18 -20
- data/features/thinking_sphinx/db/fixtures/cats.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/dogs.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/foxes.rb +1 -1
- data/features/thinking_sphinx/models/developer.rb +5 -1
- data/lib/thinking_sphinx/active_record.rb +2 -0
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +2 -0
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +9 -0
- data/lib/thinking_sphinx/attribute.rb +1 -1
- data/lib/thinking_sphinx/configuration.rb +23 -0
- data/lib/thinking_sphinx/deltas/default_delta.rb +4 -4
- data/lib/thinking_sphinx/deploy/capistrano.rb +3 -2
- data/lib/thinking_sphinx/facet.rb +6 -4
- data/lib/thinking_sphinx/facet_search.rb +2 -0
- data/lib/thinking_sphinx/field.rb +2 -0
- data/lib/thinking_sphinx/property.rb +24 -7
- data/lib/thinking_sphinx/search.rb +4 -2
- data/lib/thinking_sphinx/source.rb +5 -1
- data/lib/thinking_sphinx/source/sql.rb +20 -4
- data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +11 -0
- data/spec/thinking_sphinx/attribute_spec.rb +9 -0
- data/spec/thinking_sphinx/configuration_spec.rb +17 -0
- data/spec/thinking_sphinx/facet_spec.rb +14 -0
- data/spec/thinking_sphinx/field_spec.rb +11 -0
- data/spec/thinking_sphinx/source_spec.rb +10 -0
- metadata +7 -7
data/README.textile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.4.
|
1
|
+
1.4.2
|
data/features/facets.feature
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
Feature: Search and browse models by their defined facets
|
2
2
|
|
3
|
-
|
3
|
+
Background:
|
4
4
|
Given Sphinx is running
|
5
|
-
|
5
|
+
|
6
|
+
Scenario: Requesting facets
|
7
|
+
Given I am searching on developers
|
6
8
|
When I am requesting facet results
|
7
9
|
Then I should have valid facet results
|
8
10
|
And I should have 6 facets
|
@@ -14,8 +16,7 @@ Feature: Search and browse models by their defined facets
|
|
14
16
|
And I should have the facet Tags
|
15
17
|
|
16
18
|
Scenario: Requesting specific facets
|
17
|
-
Given
|
18
|
-
And I am searching on developers
|
19
|
+
Given I am searching on developers
|
19
20
|
When I am requesting facet results
|
20
21
|
And I am requesting just the facet State
|
21
22
|
Then I should have valid facet results
|
@@ -28,29 +29,25 @@ Feature: Search and browse models by their defined facets
|
|
28
29
|
And I should have the facet Age
|
29
30
|
|
30
31
|
Scenario: Requesting float facets
|
31
|
-
Given
|
32
|
-
And I am searching on alphas
|
32
|
+
Given I am searching on alphas
|
33
33
|
When I am requesting facet results
|
34
34
|
Then I should have 1 facet
|
35
35
|
And the Cost facet should have a 5.55 key
|
36
36
|
|
37
37
|
Scenario: Requesting facet results
|
38
|
-
Given
|
39
|
-
And I am searching on developers
|
38
|
+
Given I am searching on developers
|
40
39
|
When I am requesting facet results
|
41
40
|
And I drill down where Country is Australia
|
42
41
|
Then I should get 11 results
|
43
42
|
|
44
43
|
Scenario: Requesting facet results by multiple facets
|
45
|
-
Given
|
46
|
-
And I am searching on developers
|
44
|
+
Given I am searching on developers
|
47
45
|
When I am requesting facet results
|
48
46
|
And I drill down where Country is Australia and Age is 30
|
49
47
|
Then I should get 4 results
|
50
48
|
|
51
49
|
Scenario: Requesting facets with classes included
|
52
|
-
Given
|
53
|
-
And I am searching on developers
|
50
|
+
Given I am searching on developers
|
54
51
|
When I am requesting facet results
|
55
52
|
And I want classes included
|
56
53
|
Then I should have valid facet results
|
@@ -58,8 +55,7 @@ Feature: Search and browse models by their defined facets
|
|
58
55
|
And I should have the facet Class
|
59
56
|
|
60
57
|
Scenario: Requesting MVA facets
|
61
|
-
Given
|
62
|
-
And I am searching on developers
|
58
|
+
Given I am searching on developers
|
63
59
|
When I am requesting facet results
|
64
60
|
And I drill down where tag_ids includes the id of tag Australia
|
65
61
|
Then I should get 11 results
|
@@ -68,23 +64,25 @@ Feature: Search and browse models by their defined facets
|
|
68
64
|
Then I should get 5 results
|
69
65
|
|
70
66
|
Scenario: Requesting MVA string facets
|
71
|
-
Given
|
72
|
-
And I am searching on developers
|
67
|
+
Given I am searching on developers
|
73
68
|
When I am requesting facet results
|
74
69
|
Then the Tags facet should have an "Australia" key
|
75
70
|
Then the Tags facet should have an "Melbourne" key
|
76
71
|
Then the Tags facet should have an "Victoria" key
|
77
72
|
|
78
73
|
Scenario: Requesting MVA facets from source queries
|
79
|
-
Given
|
80
|
-
And I am searching on posts
|
74
|
+
Given I am searching on posts
|
81
75
|
When I am requesting facet results
|
82
76
|
Then the Comment Ids facet should have 9 keys
|
83
77
|
|
84
78
|
Scenario: Requesting facets from a subclass
|
85
|
-
Given
|
86
|
-
And I am searching on animals
|
79
|
+
Given I am searching on animals
|
87
80
|
When I am requesting facet results
|
88
81
|
And I want classes included
|
89
82
|
Then I should have the facet Class
|
90
83
|
|
84
|
+
Scenario: Requesting facets with explicit value sources
|
85
|
+
Given I am searching on developers
|
86
|
+
When I am requesting facet results
|
87
|
+
Then the City facet should have a "Melbourne" key
|
88
|
+
|
@@ -9,8 +9,12 @@ class Developer < ActiveRecord::Base
|
|
9
9
|
indexes country, :facet => true
|
10
10
|
indexes state, :facet => true
|
11
11
|
indexes tags.text, :as => :tags, :facet => true
|
12
|
+
|
12
13
|
has age, :facet => true
|
13
14
|
has tags(:id), :as => :tag_ids, :facet => true
|
14
|
-
|
15
|
+
|
16
|
+
facet "LOWER(city)", :as => :city, :type => :string, :value => :city
|
17
|
+
|
18
|
+
group_by 'city'
|
15
19
|
end
|
16
20
|
end
|
@@ -258,6 +258,8 @@ module ThinkingSphinx
|
|
258
258
|
ThinkingSphinx::Configuration.instance.client.update(
|
259
259
|
index, ['sphinx_deleted'], {document_id => [1]}
|
260
260
|
)
|
261
|
+
rescue Riddle::ConnectionError, ThinkingSphinx::SphinxError
|
262
|
+
# Not the end of the world if Sphinx isn't running.
|
261
263
|
end
|
262
264
|
|
263
265
|
def sphinx_offset
|
@@ -44,6 +44,8 @@ module ThinkingSphinx
|
|
44
44
|
config.client.update index_name, attribute_names, {
|
45
45
|
sphinx_document_id => attribute_values
|
46
46
|
} if self.class.search_for_id(sphinx_document_id, index_name)
|
47
|
+
rescue Riddle::ConnectionError, ThinkingSphinx::SphinxError
|
48
|
+
# Not the end of the world if Sphinx isn't running.
|
47
49
|
end
|
48
50
|
end
|
49
51
|
end
|
@@ -16,6 +16,8 @@ module ThinkingSphinx
|
|
16
16
|
ThinkingSphinx::MysqlAdapter.new model
|
17
17
|
when :postgresql
|
18
18
|
ThinkingSphinx::PostgreSQLAdapter.new model
|
19
|
+
when Class
|
20
|
+
adapter.new model
|
19
21
|
else
|
20
22
|
raise "Invalid Database Adapter: Sphinx only supports MySQL and PostgreSQL, not #{adapter}"
|
21
23
|
end
|
@@ -69,6 +71,13 @@ module ThinkingSphinx
|
|
69
71
|
"LOWER(#{clause})"
|
70
72
|
end
|
71
73
|
|
74
|
+
def case(expression, pairs, default)
|
75
|
+
"CASE #{expression} " +
|
76
|
+
pairs.keys.inject('') { |string, key|
|
77
|
+
string + "WHEN '#{key}' THEN #{pairs[key]} "
|
78
|
+
} + "ELSE #{default} END"
|
79
|
+
end
|
80
|
+
|
72
81
|
protected
|
73
82
|
|
74
83
|
def connection
|
@@ -89,7 +89,7 @@ module ThinkingSphinx
|
|
89
89
|
# datetimes to timestamps, as needed.
|
90
90
|
#
|
91
91
|
def to_select_sql
|
92
|
-
return nil unless include_as_association?
|
92
|
+
return nil unless include_as_association? && available?
|
93
93
|
|
94
94
|
separator = all_ints? || all_datetimes? || @crc ? ',' : ' '
|
95
95
|
|
@@ -147,6 +147,8 @@ module ThinkingSphinx
|
|
147
147
|
model = model.constantize
|
148
148
|
model.define_indexes
|
149
149
|
@configuration.indexes.concat model.to_riddle
|
150
|
+
|
151
|
+
enforce_common_attribute_types
|
150
152
|
end
|
151
153
|
end
|
152
154
|
|
@@ -296,5 +298,26 @@ module ThinkingSphinx
|
|
296
298
|
send("#{key}=", value) if self.respond_to?("#{key}")
|
297
299
|
end
|
298
300
|
end
|
301
|
+
|
302
|
+
def enforce_common_attribute_types
|
303
|
+
sql_indexes = configuration.indexes.reject { |index|
|
304
|
+
index.is_a? Riddle::Configuration::DistributedIndex
|
305
|
+
}
|
306
|
+
|
307
|
+
return unless sql_indexes.any? { |index|
|
308
|
+
index.sources.any? { |source|
|
309
|
+
source.sql_attr_bigint.include? :sphinx_internal_id
|
310
|
+
}
|
311
|
+
}
|
312
|
+
|
313
|
+
sql_indexes.each { |index|
|
314
|
+
index.sources.each { |source|
|
315
|
+
next if source.sql_attr_bigint.include? :sphinx_internal_id
|
316
|
+
|
317
|
+
source.sql_attr_bigint << :sphinx_internal_id
|
318
|
+
source.sql_attr_uint.delete :sphinx_internal_id
|
319
|
+
}
|
320
|
+
}
|
321
|
+
end
|
299
322
|
end
|
300
323
|
end
|
@@ -20,13 +20,13 @@ module ThinkingSphinx
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def toggle(instance)
|
23
|
-
instance.
|
23
|
+
instance.send "#{@column}=", true
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def toggled(instance)
|
27
|
-
instance.
|
27
|
+
instance.send "#{@column}"
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def reset_query(model)
|
31
31
|
"UPDATE #{model.quoted_table_name} SET " +
|
32
32
|
"#{model.connection.quote_column_name(@column.to_s)} = #{adapter.boolean(false)} " +
|
@@ -84,9 +84,10 @@ DESC
|
|
84
84
|
start
|
85
85
|
end
|
86
86
|
|
87
|
-
desc "Add the shared folder for sphinx files
|
87
|
+
desc "Add the shared folder for sphinx files"
|
88
88
|
task :shared_sphinx_folder, :roles => :web do
|
89
|
-
|
89
|
+
rails_env = fetch(:rails_env, "production")
|
90
|
+
run "mkdir -p #{shared_path}/sphinx/#{rails_env}"
|
90
91
|
end
|
91
92
|
|
92
93
|
def rake(*tasks)
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module ThinkingSphinx
|
2
2
|
class Facet
|
3
|
-
attr_reader :property
|
3
|
+
attr_reader :property, :value_source
|
4
4
|
|
5
|
-
def initialize(property)
|
6
|
-
@property
|
5
|
+
def initialize(property, value_source = nil)
|
6
|
+
@property = property
|
7
|
+
@value_source = value_source
|
7
8
|
|
8
9
|
if property.columns.length != 1
|
9
10
|
raise "Can't translate Facets on multiple-column field or attribute"
|
@@ -104,7 +105,8 @@ module ThinkingSphinx
|
|
104
105
|
item.to_crc32 == attribute_value
|
105
106
|
}
|
106
107
|
else
|
107
|
-
|
108
|
+
method = value_source || column.__name
|
109
|
+
objects.first.send(method)
|
108
110
|
end
|
109
111
|
end
|
110
112
|
|
@@ -69,6 +69,8 @@ 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
|
+
return nil unless available?
|
73
|
+
|
72
74
|
clause = columns_with_prefixes.join(', ')
|
73
75
|
|
74
76
|
clause = adapter.concatenate(clause) if concat_ws?
|
@@ -10,10 +10,11 @@ module ThinkingSphinx
|
|
10
10
|
|
11
11
|
raise "Cannot define a field or attribute in #{source.model.name} with no columns. Maybe you are trying to index a field with a reserved name (id, name). You can fix this error by using a symbol rather than a bare name (:id instead of id)." if @columns.empty? || @columns.any? { |column| !column.respond_to?(:__stack) }
|
12
12
|
|
13
|
-
@alias
|
14
|
-
@faceted
|
15
|
-
@admin
|
16
|
-
@sortable
|
13
|
+
@alias = options[:as]
|
14
|
+
@faceted = options[:facet]
|
15
|
+
@admin = options[:admin]
|
16
|
+
@sortable = options[:sortable] || false
|
17
|
+
@value_source = options[:value]
|
17
18
|
|
18
19
|
@alias = @alias.to_sym unless @alias.blank?
|
19
20
|
|
@@ -40,7 +41,7 @@ module ThinkingSphinx
|
|
40
41
|
def to_facet
|
41
42
|
return nil unless @faceted
|
42
43
|
|
43
|
-
ThinkingSphinx::Facet.new(self)
|
44
|
+
ThinkingSphinx::Facet.new(self, @value_source)
|
44
45
|
end
|
45
46
|
|
46
47
|
# Get the part of the GROUP BY clause related to this attribute - if one is
|
@@ -77,6 +78,10 @@ module ThinkingSphinx
|
|
77
78
|
!admin
|
78
79
|
end
|
79
80
|
|
81
|
+
def available?
|
82
|
+
columns.any? { |column| column_available?(column) }
|
83
|
+
end
|
84
|
+
|
80
85
|
private
|
81
86
|
|
82
87
|
# Could there be more than one value related to the parent record? If so,
|
@@ -128,9 +133,11 @@ module ThinkingSphinx
|
|
128
133
|
# figure out how to correctly reference a column in SQL.
|
129
134
|
#
|
130
135
|
def column_with_prefix(column)
|
136
|
+
return nil unless column_available?(column)
|
137
|
+
|
131
138
|
if column.is_string?
|
132
139
|
column.__name
|
133
|
-
elsif
|
140
|
+
elsif column.__stack.empty?
|
134
141
|
"#{@model.quoted_table_name}.#{quote_column(column.__name)}"
|
135
142
|
else
|
136
143
|
associations[column].collect { |assoc|
|
@@ -144,7 +151,17 @@ module ThinkingSphinx
|
|
144
151
|
def columns_with_prefixes
|
145
152
|
@columns.collect { |column|
|
146
153
|
column_with_prefix column
|
147
|
-
}.flatten
|
154
|
+
}.flatten.compact
|
155
|
+
end
|
156
|
+
|
157
|
+
def column_available?(column)
|
158
|
+
if column.is_string?
|
159
|
+
true
|
160
|
+
elsif column.__stack.empty?
|
161
|
+
@model.column_names.include?(column.__name.to_s)
|
162
|
+
else
|
163
|
+
associations[column].any? { |assoc| assoc.has_column?(column.__name) }
|
164
|
+
end
|
148
165
|
end
|
149
166
|
|
150
167
|
# Gets a stack of associations for a specific path.
|
@@ -468,8 +468,10 @@ module ThinkingSphinx
|
|
468
468
|
end
|
469
469
|
|
470
470
|
def prepare(client)
|
471
|
-
index_options =
|
472
|
-
|
471
|
+
index_options = {}
|
472
|
+
if one_class && one_class.sphinx_indexes && one_class.sphinx_indexes.first
|
473
|
+
index_options = one_class.sphinx_indexes.first.local_options
|
474
|
+
end
|
473
475
|
|
474
476
|
[
|
475
477
|
:max_matches, :group_by, :group_function, :group_clause,
|
@@ -82,6 +82,10 @@ module ThinkingSphinx
|
|
82
82
|
@adapter ||= @model.sphinx_database_adapter
|
83
83
|
end
|
84
84
|
|
85
|
+
def available_attributes
|
86
|
+
attributes.select { |attrib| attrib.available? }
|
87
|
+
end
|
88
|
+
|
85
89
|
def set_source_database_settings(source)
|
86
90
|
config = @database_configuration
|
87
91
|
|
@@ -94,7 +98,7 @@ module ThinkingSphinx
|
|
94
98
|
end
|
95
99
|
|
96
100
|
def set_source_attributes(source, offset, delta = false)
|
97
|
-
|
101
|
+
available_attributes.each do |attrib|
|
98
102
|
source.send(attrib.type_to_config) << attrib.config_value(offset, delta)
|
99
103
|
end
|
100
104
|
end
|
@@ -117,14 +117,30 @@ GROUP BY #{ sql_group_clause }
|
|
117
117
|
if @model.table_exists? &&
|
118
118
|
@model.column_names.include?(@model.inheritance_column)
|
119
119
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
120
|
+
types = types_to_crcs
|
121
|
+
return @model.to_crc32.to_s if types.empty?
|
122
|
+
|
123
|
+
adapter.case(adapter.convert_nulls(
|
124
|
+
adapter.quote_with_table(@model.inheritance_column)),
|
125
|
+
types_to_crcs, @model.to_crc32)
|
124
126
|
else
|
125
127
|
@model.to_crc32.to_s
|
126
128
|
end
|
127
129
|
end
|
130
|
+
|
131
|
+
def type_values
|
132
|
+
@model.connection.select_values <<-SQL
|
133
|
+
SELECT DISTINCT #{@model.inheritance_column}
|
134
|
+
FROM #{@model.table_name}
|
135
|
+
SQL
|
136
|
+
end
|
137
|
+
|
138
|
+
def types_to_crcs
|
139
|
+
type_values.compact.inject({}) { |hash, type|
|
140
|
+
hash[type] = type.to_crc32
|
141
|
+
hash
|
142
|
+
}
|
143
|
+
end
|
128
144
|
end
|
129
145
|
end
|
130
146
|
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
class CustomAdapter < ThinkingSphinx::AbstractAdapter
|
4
|
+
#
|
5
|
+
end
|
6
|
+
|
3
7
|
describe ThinkingSphinx::AbstractAdapter do
|
4
8
|
describe '.detect' do
|
5
9
|
let(:model) { stub('model') }
|
@@ -18,6 +22,13 @@ describe ThinkingSphinx::AbstractAdapter do
|
|
18
22
|
adapter.should be_a(ThinkingSphinx::PostgreSQLAdapter)
|
19
23
|
end
|
20
24
|
|
25
|
+
it "instantiates the provided class if one is provided" do
|
26
|
+
ThinkingSphinx::AbstractAdapter.stub(:adapter_for_model => CustomAdapter)
|
27
|
+
CustomAdapter.should_receive(:new).and_return(stub('adapter'))
|
28
|
+
|
29
|
+
ThinkingSphinx::AbstractAdapter.detect(model)
|
30
|
+
end
|
31
|
+
|
21
32
|
it "raises an exception for other responses" do
|
22
33
|
ThinkingSphinx::AbstractAdapter.stub(:adapter_for_model => :sqlite)
|
23
34
|
|
@@ -68,6 +68,15 @@ describe ThinkingSphinx::Attribute do
|
|
68
68
|
|
69
69
|
attribute.to_select_sql.should == "CONCAT_WS(' ', IFNULL(`cricket_teams`.`name`, ''), IFNULL(`football_teams`.`name`, ''), IFNULL(`football_teams`.`league`, '')) AS `team`"
|
70
70
|
end
|
71
|
+
|
72
|
+
it "should return nil if polymorphic association data does not exist" do
|
73
|
+
attribute = ThinkingSphinx::Attribute.new(@source,
|
74
|
+
[ThinkingSphinx::Index::FauxColumn.new(:source, :id)],
|
75
|
+
:as => :source_id, :type => :integer
|
76
|
+
)
|
77
|
+
|
78
|
+
attribute.to_select_sql.should be_nil
|
79
|
+
end
|
71
80
|
end
|
72
81
|
|
73
82
|
describe '#is_many?' do
|
@@ -231,6 +231,23 @@ describe ThinkingSphinx::Configuration do
|
|
231
231
|
file.should_not match(/index alpha_core\s+\{\s+[^\}]*prefix_fields\s+=[^\}]*\}/m)
|
232
232
|
end
|
233
233
|
|
234
|
+
describe '#generate' do
|
235
|
+
let(:config) { ThinkingSphinx::Configuration.instance }
|
236
|
+
|
237
|
+
it "should set all sphinx_internal_id attributes to bigints if one is" do
|
238
|
+
config.reset
|
239
|
+
config.generate
|
240
|
+
|
241
|
+
config.configuration.indexes.each do |index|
|
242
|
+
next if index.is_a? Riddle::Configuration::DistributedIndex
|
243
|
+
|
244
|
+
index.sources.each do |source|
|
245
|
+
source.sql_attr_bigint.should include(:sphinx_internal_id)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
234
251
|
describe '#client' do
|
235
252
|
before :each do
|
236
253
|
@config = ThinkingSphinx::Configuration.instance
|
@@ -329,5 +329,19 @@ describe ThinkingSphinx::Facet do
|
|
329
329
|
@facet.value(alpha, {'cost' => 1093140480}).should == 10.5
|
330
330
|
end
|
331
331
|
end
|
332
|
+
|
333
|
+
context 'manual value source' do
|
334
|
+
let(:index) { ThinkingSphinx::Index.new(Alpha) }
|
335
|
+
let(:source) { ThinkingSphinx::Source.new(index) }
|
336
|
+
let(:column) { ThinkingSphinx::Index::FauxColumn.new('LOWER(name)') }
|
337
|
+
let(:field) { ThinkingSphinx::Field.new(source, column) }
|
338
|
+
let(:facet) { ThinkingSphinx::Facet.new(field, :name) }
|
339
|
+
|
340
|
+
it "should use the given value source to figure out the value" do
|
341
|
+
alpha = Alpha.new(:name => 'Foo')
|
342
|
+
|
343
|
+
facet.value(alpha, {'foo_facet' => 'foo'.to_crc32}).should == 'Foo'
|
344
|
+
end
|
345
|
+
end
|
332
346
|
end
|
333
347
|
end
|
@@ -44,6 +44,17 @@ describe ThinkingSphinx::Field do
|
|
44
44
|
@field.unique_name.should == "col_name"
|
45
45
|
end
|
46
46
|
end
|
47
|
+
|
48
|
+
describe '#to_select_sql' do
|
49
|
+
it "should return nil if polymorphic association data does not exist" do
|
50
|
+
field = ThinkingSphinx::Field.new(@source,
|
51
|
+
[ThinkingSphinx::Index::FauxColumn.new(:source, :name)],
|
52
|
+
:as => :source_name
|
53
|
+
)
|
54
|
+
|
55
|
+
field.to_select_sql.should be_nil
|
56
|
+
end
|
57
|
+
end
|
47
58
|
|
48
59
|
describe "prefixes method" do
|
49
60
|
it "should default to false" do
|
@@ -48,6 +48,10 @@ describe ThinkingSphinx::Source do
|
|
48
48
|
@source, ThinkingSphinx::Index::FauxColumn.new(:contacts, :id),
|
49
49
|
:as => :contact_ids, :source => :query
|
50
50
|
)
|
51
|
+
ThinkingSphinx::Attribute.new(
|
52
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:source, :id),
|
53
|
+
:as => :source_id, :type => :integer
|
54
|
+
)
|
51
55
|
|
52
56
|
ThinkingSphinx::Join.new(
|
53
57
|
@source, ThinkingSphinx::Index::FauxColumn.new(:links)
|
@@ -103,6 +107,12 @@ describe ThinkingSphinx::Source do
|
|
103
107
|
@riddle.sql_attr_timestamp.first.should == :birthday
|
104
108
|
end
|
105
109
|
|
110
|
+
it "should not include an attribute definition for polymorphic references without data" do
|
111
|
+
@riddle.sql_attr_uint.select { |uint|
|
112
|
+
uint == :source_id
|
113
|
+
}.should be_empty
|
114
|
+
end
|
115
|
+
|
106
116
|
it "should set Sphinx Source options" do
|
107
117
|
@riddle.sql_range_step.should == 1000
|
108
118
|
@riddle.sql_ranged_throttle.should == 100
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thinking-sphinx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 1.4.
|
9
|
+
- 2
|
10
|
+
version: 1.4.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Pat Allan
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-01-13 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -51,12 +51,12 @@ dependencies:
|
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
hash:
|
54
|
+
hash: 27
|
55
55
|
segments:
|
56
56
|
- 1
|
57
57
|
- 2
|
58
|
-
-
|
59
|
-
version: 1.2.
|
58
|
+
- 2
|
59
|
+
version: 1.2.2
|
60
60
|
requirement: *id002
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
type: :runtime
|