public
Fork of freelancing-god/thinking-sphinx
Description: Sphinx plugin for Rails and Merb
Homepage: http://ts.freelancing-gods.com
Clone URL: git://github.com/scoop/thinking-sphinx.git
Adding a lot more specs, including some tweaks
Sat Jun 07 14:00:22 -0700 2008
commit  352436d0e3cf74ff770f3dbf0ad3528394689252
tree    2176adc80778a141b34e47d7ddeae0d40402c5fe
parent  92450ffc2f6344d5822c4fcc3d9d77fcddde35b7
...
20
21
22
23
 
24
25
26
...
67
68
69
 
 
 
70
71
72
...
20
21
22
 
23
24
25
26
...
67
68
69
70
71
72
73
74
75
0
@@ -20,7 +20,7 @@ module ThinkingSphinx
0
   module Version #:nodoc:
0
     Major = 0
0
     Minor = 9
0
- Tiny = 6
0
+ Tiny = 7
0
     
0
     String = [Major, Minor, Tiny].join('.')
0
   end
0
@@ -67,6 +67,9 @@ module ThinkingSphinx
0
     @@deltas_enabled = value
0
   end
0
   
0
+ # Checks to see if MySQL will allow simplistic GROUP BY statements. If not,
0
+ # or if not using MySQL, this will return false.
0
+ #
0
   def self.use_group_by_shortcut?
0
     ::ActiveRecord::ConnectionAdapters.constants.include?("MysqlAdapter") &&
0
     ::ActiveRecord::Base.connection.is_a?(
...
122
123
124
125
 
126
127
128
 
129
130
 
131
132
 
133
134
 
135
136
137
...
122
123
124
 
125
126
127
 
128
129
 
130
131
 
132
133
 
134
135
136
137
0
@@ -122,16 +122,16 @@ module ThinkingSphinx
0
       options[:class_name] = klass.name
0
       options[:foreign_key] ||= "#{ref.name}_id"
0
       
0
- foreign_type = klass.connection.quote_column_name ref.options[:foreign_type]
0
+ quoted_foreign_type = klass.connection.quote_column_name ref.options[:foreign_type]
0
       case options[:conditions]
0
       when nil
0
- options[:conditions] = "::ts_join_alias::.#{foreign_type} = '#{klass.name}'"
0
+ options[:conditions] = "::ts_join_alias::.#{quoted_foreign_type} = '#{klass.name}'"
0
       when Array
0
- options[:conditions] << "::ts_join_alias::.#{foreign_type} = '#{klass.name}'"
0
+ options[:conditions] << "::ts_join_alias::.#{quoted_foreign_type} = '#{klass.name}'"
0
       when Hash
0
- options[:conditions].merge!(foreign_type => klass.name)
0
+ options[:conditions].merge!(ref.options[:foreign_type] => klass.name)
0
       else
0
- options[:conditions] << " AND ::ts_join_alias::.#{foreign_type} = '#{klass.name}'"
0
+ options[:conditions] << " AND ::ts_join_alias::.#{quoted_foreign_type} = '#{klass.name}'"
0
       end
0
       
0
       options
...
23
24
25
 
 
 
 
 
26
27
28
...
23
24
25
26
27
28
29
30
31
32
33
0
@@ -23,6 +23,11 @@ Spec::Runner.configure do |config|
0
     # sphinx.start
0
   end
0
   
0
+ config.before :each do
0
+ NotAMock::CallRecorder.instance.reset
0
+ NotAMock::Stubber.instance.reset
0
+ end
0
+
0
   config.after :all do
0
     # sphinx.stop
0
     
...
1
 
 
2
3
4
...
1
2
3
4
5
6
0
@@ -1,4 +1,6 @@
0
 require 'active_record'
0
+require 'active_record/connection_adapters/mysql_adapter'
0
+require 'active_record/connection_adapters/postgresql_adapter'
0
 require 'yaml'
0
 require 'spec/fixtures/models'
0
 
...
17
18
19
 
 
 
 
20
21
22
...
17
18
19
20
21
22
23
24
25
26
0
@@ -17,6 +17,10 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
0
         :after_commit, [:toggle_delta]
0
       )
0
     end
0
+
0
+ it "should have an after_commit method by default" do
0
+ Person.instance_methods.should include("after_commit")
0
+ end
0
   end
0
   
0
   describe "save_with_after_commit_callback method" do
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
0
@@ -0,0 +1,63 @@
0
+require 'spec/spec_helper'
0
+
0
+describe "ThinkingSphinx::ActiveRecord::Search" do
0
+ it "should add search_for_ids to ActiveRecord::Base" do
0
+ ActiveRecord::Base.methods.should include("search_for_ids")
0
+ end
0
+
0
+ it "should add search_for_ids to ActiveRecord::Base" do
0
+ ActiveRecord::Base.methods.should include("search")
0
+ end
0
+
0
+ describe "search_for_ids method" do
0
+ before :each do
0
+ ThinkingSphinx::Search.stub_method(:search_for_ids => true)
0
+ end
0
+
0
+ after :each do
0
+ ThinkingSphinx::Search.unstub_method(:search_for_ids)
0
+ end
0
+
0
+ it "should call ThinkingSphinx::Search#search_for_ids with the class option set" do
0
+ Person.search_for_ids("search")
0
+
0
+ ThinkingSphinx::Search.should have_received(:search_for_ids).with(
0
+ "search", :class => Person
0
+ )
0
+ end
0
+
0
+ it "should override the class option" do
0
+ Person.search_for_ids("search", :class => Friendship)
0
+
0
+ ThinkingSphinx::Search.should have_received(:search_for_ids).with(
0
+ "search", :class => Person
0
+ )
0
+ end
0
+ end
0
+
0
+ describe "search method" do
0
+ before :each do
0
+ ThinkingSphinx::Search.stub_method(:search => true)
0
+ end
0
+
0
+ after :each do
0
+ ThinkingSphinx::Search.unstub_method(:search)
0
+ end
0
+
0
+ it "should call ThinkingSphinx::Search#search with the class option set" do
0
+ Person.search("search")
0
+
0
+ ThinkingSphinx::Search.should have_received(:search).with(
0
+ "search", :class => Person
0
+ )
0
+ end
0
+
0
+ it "should override the class option" do
0
+ Person.search("search", :class => Friendship)
0
+
0
+ ThinkingSphinx::Search.should have_received(:search).with(
0
+ "search", :class => Person
0
+ )
0
+ end
0
+ end
0
+end
0
\ No newline at end of file
...
8
9
10
11
12
 
 
 
13
14
15
...
74
75
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
78
79
...
84
85
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
88
...
8
9
10
 
 
11
12
13
14
15
16
...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
0
@@ -8,8 +8,9 @@ describe "ThinkingSphinx::ActiveRecord" do
0
       end
0
       
0
       TestModule::TestModel.stub_methods(
0
- :before_save => true,
0
- :after_commit => true
0
+ :before_save => true,
0
+ :after_commit => true,
0
+ :after_destroy => true
0
       )
0
       
0
       @index = ThinkingSphinx::Index.stub_instance(:delta? => false)
0
@@ -74,6 +75,20 @@ describe "ThinkingSphinx::ActiveRecord" do
0
       TestModule::TestModel.should_not have_received(:after_commit)
0
     end
0
     
0
+ it "should add an after_destroy hook with delta indexing enabled" do
0
+ @index.stub_method(:delta? => true)
0
+
0
+ TestModule::TestModel.define_index do; end
0
+
0
+ TestModule::TestModel.should have_received(:after_destroy).with(:toggle_deleted)
0
+ end
0
+
0
+ it "should add an after_destroy hook with delta indexing disabled" do
0
+ TestModule::TestModel.define_index do; end
0
+
0
+ TestModule::TestModel.should have_received(:after_destroy).with(:toggle_deleted)
0
+ end
0
+
0
     it "should return the new index" do
0
       TestModule::TestModel.define_index.should == @index
0
     end
0
@@ -84,4 +99,59 @@ describe "ThinkingSphinx::ActiveRecord" do
0
       Person.to_crc32.should be_a_kind_of(Integer)
0
     end
0
   end
0
+
0
+ describe "toggle_deleted method" do
0
+ before :each do
0
+ @configuration = ThinkingSphinx::Configuration.stub_instance(
0
+ :address => "an address",
0
+ :port => 123
0
+ )
0
+ @client = Riddle::Client.stub_instance(:update => true)
0
+ @person = Person.new
0
+
0
+ ThinkingSphinx::Configuration.stub_method(:new => @configuration)
0
+ Riddle::Client.stub_method(:new => @client)
0
+ Person.indexes.each { |index| index.stub_method(:delta? => false) }
0
+ end
0
+
0
+ after :each do
0
+ ThinkingSphinx::Configuration.unstub_method(:new)
0
+ Riddle::Client.unstub_method(:new)
0
+ Person.indexes.each { |index| index.unstub_method(:delta?) }
0
+ end
0
+
0
+ it "should create a client using the Configuration's address and port" do
0
+ @person.toggle_deleted
0
+
0
+ Riddle::Client.should have_received(:new).with(
0
+ @configuration.address, @configuration.port
0
+ )
0
+ end
0
+
0
+ it "should update the core index's deleted flag" do
0
+ @person.toggle_deleted
0
+
0
+ @client.should have_received(:update).with(
0
+ "person_core", ["sphinx_deleted"], {@person.id => 1}
0
+ )
0
+ end
0
+
0
+ it "should update the delta index's deleted flag if delta indexing is enabled" do
0
+ Person.indexes.each { |index| index.stub_method(:delta? => true) }
0
+
0
+ @person.toggle_deleted
0
+
0
+ @client.should have_received(:update).with(
0
+ "person_delta", ["sphinx_deleted"], {@person.id => 1}
0
+ )
0
+ end
0
+
0
+ it "shouldn't update the delta index if delta indexing is disabled" do
0
+ @person.toggle_deleted
0
+
0
+ @client.should_not have_received(:update).with(
0
+ "person_delta", ["sphinx_deleted"], {@person.id => 1}
0
+ )
0
+ end
0
+ end
0
 end
0
\ No newline at end of file
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
0
@@ -0,0 +1,247 @@
0
+require 'spec/spec_helper'
0
+
0
+describe ThinkingSphinx::Association do
0
+ describe "class-level children method" do
0
+ before :each do
0
+ @normal_reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
0
+ :options => {:polymorphic => false}
0
+ )
0
+ @normal_association = ThinkingSphinx::Association.stub_instance
0
+ @poly_reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
0
+ :options => {:polymorphic => true},
0
+ :macro => :has_many,
0
+ :name => "polly",
0
+ :active_record => "AR"
0
+ )
0
+ @non_poly_reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance
0
+
0
+ Person.stub_method(:reflect_on_association => @normal_reflection)
0
+ ThinkingSphinx::Association.stub_methods(
0
+ :new => @normal_association,
0
+ :polymorphic_classes => [Person, Person],
0
+ :casted_options => {:casted => :options}
0
+ )
0
+ ::ActiveRecord::Reflection::AssociationReflection.stub_method(
0
+ :new => @non_poly_reflection
0
+ )
0
+ end
0
+
0
+ it "should return an empty array if no association exists" do
0
+ Person.stub_method(:reflect_on_association => nil)
0
+
0
+ ThinkingSphinx::Association.children(Person, :assoc).should == []
0
+ end
0
+
0
+ it "should return a single association instance in an array if assocation isn't polymorphic" do
0
+ ThinkingSphinx::Association.children(Person, :assoc).should == [@normal_association]
0
+ end
0
+
0
+ it "should return multiple association instances for polymorphic associations" do
0
+ Person.stub_method(:reflect_on_association => @poly_reflection)
0
+
0
+ ThinkingSphinx::Association.children(Person, :assoc).should ==
0
+ [@normal_association, @normal_association]
0
+ end
0
+
0
+ it "should generate non-polymorphic 'casted' associations for each polymorphic possibility" do
0
+ Person.stub_method(:reflect_on_association => @poly_reflection)
0
+
0
+ ThinkingSphinx::Association.children(Person, :assoc)
0
+
0
+ ThinkingSphinx::Association.should have_received(:casted_options).with(
0
+ Person, @poly_reflection
0
+ ).twice
0
+
0
+ ::ActiveRecord::Reflection::AssociationReflection.should have_received(:new).with(
0
+ :has_many, :polly_Person, {:casted => :options}, "AR"
0
+ ).twice
0
+
0
+ ThinkingSphinx::Association.should have_received(:new).with(
0
+ nil, @non_poly_reflection
0
+ ).twice
0
+ end
0
+ end
0
+
0
+ describe "instance-level children method" do
0
+ it "should return the children associations for the given association" do
0
+ @reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
0
+ :klass => :klass
0
+ )
0
+ @association = ThinkingSphinx::Association.new(nil, @reflection)
0
+ ThinkingSphinx::Association.stub_method(:children => :result)
0
+
0
+ @association.children(:assoc).should == :result
0
+ ThinkingSphinx::Association.should have_received(:children).with(:klass, :assoc, @association)
0
+ end
0
+ end
0
+
0
+ describe "join_to method" do
0
+ before :each do
0
+ @parent_join = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.stub_instance
0
+ @join = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.stub_instance
0
+ @parent = ThinkingSphinx::Association.stub_instance(:join_to => true, :join => nil)
0
+ @base_join = Object.stub_instance(:joins => [:a, :b, :c])
0
+
0
+ ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.stub_method(:new => @join)
0
+ end
0
+
0
+ it "should call the parent's join_to if parent has no join" do
0
+ @assoc = ThinkingSphinx::Association.new(@parent, :ref)
0
+
0
+ @assoc.join_to(@base_join)
0
+
0
+ @parent.should have_received(:join_to).with(@base_join)
0
+ end
0
+
0
+ it "should not call the parent's join_to if it already has a join" do
0
+ @assoc = ThinkingSphinx::Association.new(@parent, :ref)
0
+ @parent.stub_method(:join => @parent_join)
0
+
0
+ @assoc.join_to(@base_join)
0
+
0
+ @parent.should_not have_received(:join_to)
0
+ end
0
+
0
+ it "should define the join association with a JoinAssociation instance" do
0
+ @assoc = ThinkingSphinx::Association.new(@parent, :ref)
0
+
0
+ @assoc.join_to(@base_join).should == @join
0
+ @assoc.join.should == @join
0
+ end
0
+ end
0
+
0
+ describe "to_sql method" do
0
+ before :each do
0
+ @reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
0
+ :klass => Person
0
+ )
0
+ @association = ThinkingSphinx::Association.new(nil, @reflection)
0
+ @parent = Object.stub_instance(:aliased_table_name => "ALIAS TABLE NAME")
0
+ @join = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.stub_instance(
0
+ :association_join => "full association join SQL",
0
+ :parent => @parent
0
+ )
0
+ @association.join = @join
0
+ end
0
+
0
+ it "should return the join's association join value" do
0
+ @association.to_sql.should == "full association join SQL"
0
+ end
0
+
0
+ it "should replace ::ts_join_alias:: with the aliased table name" do
0
+ @join.stub_method(:association_join => "text with ::ts_join_alias:: gone")
0
+
0
+ @association.to_sql.should == "text with `ALIAS TABLE NAME` gone"
0
+ end
0
+ end
0
+
0
+ describe "is_many? method" do
0
+ before :each do
0
+ @parent = ThinkingSphinx::Association.stub_instance(
0
+ :is_many? => :parent_is_many
0
+ )
0
+ @reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
0
+ :macro => :has_many
0
+ )
0
+ end
0
+
0
+ it "should return true if association is either a has_many or a habtm" do
0
+ association = ThinkingSphinx::Association.new(@parent, @reflection)
0
+ association.is_many?.should be_true
0
+
0
+ @reflection.stub_method(:macro => :has_and_belongs_to_many)
0
+ association.is_many?.should be_true
0
+ end
0
+
0
+ it "should return the parent value if not a has many or habtm and there is a parent" do
0
+ association = ThinkingSphinx::Association.new(@parent, @reflection)
0
+ @reflection.stub_method(:macro => :belongs_to)
0
+ association.is_many?.should == :parent_is_many
0
+ end
0
+
0
+ it "should return false if no parent and not a has many or habtm" do
0
+ association = ThinkingSphinx::Association.new(nil, @reflection)
0
+ @reflection.stub_method(:macro => :belongs_to)
0
+ association.is_many?.should be_false
0
+ end
0
+ end
0
+
0
+ describe "ancestors method" do
0
+ it "should return an array of associations - including all parents" do
0
+ parent = ThinkingSphinx::Association.stub_instance(:ancestors => [:all, :ancestors])
0
+ association = ThinkingSphinx::Association.new(parent, @reflection)
0
+ association.ancestors.should == [:all, :ancestors, association]
0
+ end
0
+ end
0
+
0
+ describe "polymorphic_classes method" do
0
+ it "should return all the polymorphic result types as classes" do
0
+ Person.connection.stub_method(:select_all => [
0
+ {"person_type" => "Person"},
0
+ {"person_type" => "Friendship"}
0
+ ])
0
+ ref = Object.stub_instance(
0
+ :active_record => Person,
0
+ :options => {:foreign_type => "person_type"}
0
+ )
0
+
0
+ ThinkingSphinx::Association.send(:polymorphic_classes, ref).should == [Person, Friendship]
0
+ end
0
+ end
0
+
0
+ describe "casted_options method" do
0
+ before :each do
0
+ @options = {
0
+ :foreign_key => "thing_id",
0
+ :foreign_type => "thing_type",
0
+ :polymorphic => true
0
+ }
0
+ @reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
0
+ :options => @options
0
+ )
0
+ end
0
+
0
+ it "should return a new options set for a specific class" do
0
+ ThinkingSphinx::Association.send(:casted_options, Person, @reflection).should == {
0
+ :polymorphic => nil,
0
+ :class_name => "Person",
0
+ :foreign_key => "thing_id",
0
+ :foreign_type => "thing_type",
0
+ :conditions => "::ts_join_alias::.`thing_type` = 'Person'"
0
+ }
0
+ end
0
+
0
+ it "should append to existing Array of conditions" do
0
+ @options[:conditions] = ["first condition"]
0
+ ThinkingSphinx::Association.send(:casted_options, Person, @reflection).should == {
0
+ :polymorphic => nil,
0
+ :class_name => "Person",
0
+ :foreign_key => "thing_id",
0
+ :foreign_type => "thing_type",
0
+ :conditions => ["first condition", "::ts_join_alias::.`thing_type` = 'Person'"]
0
+ }
0
+ end
0
+
0
+ it "should merge to an existing Hash of conditions" do
0
+ @options[:conditions] = {"field" => "value"}
0
+ ThinkingSphinx::Association.send(:casted_options, Person, @reflection).should == {
0
+ :polymorphic => nil,
0
+ :class_name => "Person",
0
+ :foreign_key => "thing_id",
0
+ :foreign_type => "thing_type",
0
+ :conditions => {"field" => "value", "thing_type" => "Person"}
0
+ }
0
+ end
0
+
0
+ it "should append to an existing String of conditions" do
0
+ @options[:conditions] = "first condition"
0
+ ThinkingSphinx::Association.send(:casted_options, Person, @reflection).should == {
0
+ :polymorphic => nil,
0
+ :class_name => "Person",
0
+ :foreign_key => "thing_id",
0
+ :foreign_type => "thing_type",
0
+ :conditions => "first condition AND ::ts_join_alias::.`thing_type` = 'Person'"
0
+ }
0
+ end
0
+ end
0
+end
0
\ No newline at end of file
...
1
2
3
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
6
7
...
36
37
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
40
41
...
72
73
74
75
76
77
78
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
82
83
84
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
87
88
89
...
1
2
3
 
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
120
121
122
 
 
 
 
 
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
 
 
 
 
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
0
@@ -1,7 +1,21 @@
0
 require 'spec/spec_helper'
0
 
0
 describe ThinkingSphinx::Attribute do
0
- describe "to_select_sql method" do
0
+ describe '#initialize' do
0
+ it 'raises if no columns are provided so that configuration errors are easier to track down' do
0
+ lambda {
0
+ ThinkingSphinx::Attribute.new([])
0
+ }.should raise_error(RuntimeError)
0
+ end
0
+
0
+ it 'raises if an element of the columns param is an integer - as happens when you use id instead of :id - so that configuration errors are easier to track down' do
0
+ lambda {
0
+ ThinkingSphinx::Attribute.new([1234])
0
+ }.should raise_error(RuntimeError)
0
+ end
0
+ end
0
+
0
+ describe "to_select_sql method with MySQL" do
0
     before :each do
0
       @index = Person.indexes.first
0
       @index.link!
0
@@ -36,6 +50,40 @@ describe ThinkingSphinx::Attribute do
0
     end
0
   end
0
   
0
+ describe "to_select_sql method with PostgreSQL" do
0
+ before :each do
0
+ @index = Person.indexes.first
0
+ Person.connection.class.stub_method(
0
+ :name => "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
0
+ )
0
+ @index.link!
0
+ end
0
+
0
+ it "should concat with spaces if there's more than one non-integer column" do
0
+ @index.attributes[0].to_select_sql.should match(/|| ' ' ||/)
0
+ end
0
+
0
+ it "should concat with spaces if there's more than one association for a non-integer column" do
0
+ @index.attributes[1].to_select_sql.should match(/|| ' ' ||/)
0
+ end
0
+
0
+ it "should concat with commas if there's multiple integer columns" do
0
+ @index.attributes[2].to_select_sql.should match(/|| ',' ||/)
0
+ end
0
+
0
+ it "should concat with commas if there's more than one association for an integer column" do
0
+ @index.attributes[3].to_select_sql.should match(/|| ',' ||/)
0
+ end
0
+
0
+ it "should group with spaces if there's string columns from a has_many or has_and_belongs_to_many association" do
0
+ @index.attributes[4].to_select_sql.should match(/array_to_string\(array_accum\(.+, ' '\)/)
0
+ end
0
+
0
+ it "should group with commas if there's integer columns from a has_many or has_and_belongs_to_many association" do
0
+ @index.attributes[5].to_select_sql.should match(/array_to_string\(array_accum\(.+, ','\)/)
0
+ end
0
+ end
0
+
0
   describe "to_group_sql method" do
0
     before :each do
0
       @attribute = ThinkingSphinx::Attribute.new([Object.stub_instance(:__stack => [])])
0
@@ -72,17 +120,237 @@ describe ThinkingSphinx::Attribute do
0
     end
0
   end
0
   
0
- describe '#initialize' do
0
- it 'raises if no columns are provided so that configuration errors are easier to track down' do
0
- lambda {
0
- ThinkingSphinx::Attribute.new([])
0
- }.should raise_error(RuntimeError)
0
+ describe "to_sphinx_clause method" do
0
+ before :each do
0
+ @attribute = ThinkingSphinx::Attribute.new [Object.stub_instance(:__stack => [])]
0
+ @attribute.stub_method(:unique_name => "unique name")
0
+ end
0
+
0
+ it "should use sql_attr_multi syntax for MVA attributes" do
0
+ @attribute.stub_method(:type => :multi)
0
+ @attribute.to_sphinx_clause.should match(/^sql_attr_multi\s+= uint unique name from field$/)
0
+ end
0
+
0
+ it "should use sql_attr_timestamp syntax for datetime values" do
0
+ @attribute.stub_method(:type => :datetime)
0
+ @attribute.to_sphinx_clause.should match(/^sql_attr_timestamp\s+= unique name$/)
0
+ end
0
+
0
+ it "should use sql_attr_str2ordinal for string values" do
0
+ @attribute.stub_method(:type => :string)
0
+ @attribute.to_sphinx_clause.should match(/^sql_attr_str2ordinal\s+= unique name$/)
0
     end
0
+
0
+ it "should use sql_attr_float for float values" do
0
+ @attribute.stub_method(:type => :float)
0
+ @attribute.to_sphinx_clause.should match(/^sql_attr_float\s+= unique name$/)
0
+ end
0
+
0
+ it "should use sql_attr_bool for boolean values" do
0
+ @attribute.stub_method(:type => :boolean)
0
+ @attribute.to_sphinx_clause.should match(/^sql_attr_bool\s+= unique name$/)
0
+ end
0
+
0
+ it "should use sql_attr_uint for integer values" do
0
+ @attribute.stub_method(:type => :integer)
0
+ @attribute.to_sphinx_clause.should match(/^sql_attr_uint\s+= unique name$/)
0
+ end
0
+
0
+ it "should assume integer for any other types" do
0
+ @attribute.stub_method(:type =>