joshcutler-thinking-sphinx 1.3.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +167 -0
  3. data/VERSION +1 -0
  4. data/features/abstract_inheritance.feature +10 -0
  5. data/features/alternate_primary_key.feature +27 -0
  6. data/features/attribute_transformation.feature +22 -0
  7. data/features/attribute_updates.feature +77 -0
  8. data/features/deleting_instances.feature +67 -0
  9. data/features/direct_attributes.feature +11 -0
  10. data/features/excerpts.feature +13 -0
  11. data/features/extensible_delta_indexing.feature +9 -0
  12. data/features/facets.feature +82 -0
  13. data/features/facets_across_model.feature +29 -0
  14. data/features/handling_edits.feature +92 -0
  15. data/features/retry_stale_indexes.feature +24 -0
  16. data/features/searching_across_models.feature +20 -0
  17. data/features/searching_by_index.feature +40 -0
  18. data/features/searching_by_model.feature +175 -0
  19. data/features/searching_with_find_arguments.feature +56 -0
  20. data/features/sphinx_detection.feature +25 -0
  21. data/features/sphinx_scopes.feature +42 -0
  22. data/features/step_definitions/alpha_steps.rb +16 -0
  23. data/features/step_definitions/beta_steps.rb +7 -0
  24. data/features/step_definitions/common_steps.rb +193 -0
  25. data/features/step_definitions/extensible_delta_indexing_steps.rb +7 -0
  26. data/features/step_definitions/facet_steps.rb +96 -0
  27. data/features/step_definitions/find_arguments_steps.rb +36 -0
  28. data/features/step_definitions/gamma_steps.rb +15 -0
  29. data/features/step_definitions/scope_steps.rb +15 -0
  30. data/features/step_definitions/search_steps.rb +89 -0
  31. data/features/step_definitions/sphinx_steps.rb +35 -0
  32. data/features/sti_searching.feature +19 -0
  33. data/features/support/env.rb +21 -0
  34. data/features/support/lib/generic_delta_handler.rb +8 -0
  35. data/features/thinking_sphinx/database.example.yml +3 -0
  36. data/features/thinking_sphinx/db/fixtures/alphas.rb +10 -0
  37. data/features/thinking_sphinx/db/fixtures/authors.rb +1 -0
  38. data/features/thinking_sphinx/db/fixtures/betas.rb +11 -0
  39. data/features/thinking_sphinx/db/fixtures/boxes.rb +9 -0
  40. data/features/thinking_sphinx/db/fixtures/categories.rb +1 -0
  41. data/features/thinking_sphinx/db/fixtures/cats.rb +3 -0
  42. data/features/thinking_sphinx/db/fixtures/comments.rb +24 -0
  43. data/features/thinking_sphinx/db/fixtures/developers.rb +31 -0
  44. data/features/thinking_sphinx/db/fixtures/dogs.rb +3 -0
  45. data/features/thinking_sphinx/db/fixtures/extensible_betas.rb +10 -0
  46. data/features/thinking_sphinx/db/fixtures/foxes.rb +3 -0
  47. data/features/thinking_sphinx/db/fixtures/gammas.rb +10 -0
  48. data/features/thinking_sphinx/db/fixtures/music.rb +4 -0
  49. data/features/thinking_sphinx/db/fixtures/people.rb +1001 -0
  50. data/features/thinking_sphinx/db/fixtures/posts.rb +6 -0
  51. data/features/thinking_sphinx/db/fixtures/robots.rb +14 -0
  52. data/features/thinking_sphinx/db/fixtures/tags.rb +27 -0
  53. data/features/thinking_sphinx/db/migrations/create_alphas.rb +8 -0
  54. data/features/thinking_sphinx/db/migrations/create_animals.rb +5 -0
  55. data/features/thinking_sphinx/db/migrations/create_authors.rb +3 -0
  56. data/features/thinking_sphinx/db/migrations/create_authors_posts.rb +6 -0
  57. data/features/thinking_sphinx/db/migrations/create_betas.rb +5 -0
  58. data/features/thinking_sphinx/db/migrations/create_boxes.rb +5 -0
  59. data/features/thinking_sphinx/db/migrations/create_categories.rb +3 -0
  60. data/features/thinking_sphinx/db/migrations/create_comments.rb +10 -0
  61. data/features/thinking_sphinx/db/migrations/create_developers.rb +7 -0
  62. data/features/thinking_sphinx/db/migrations/create_extensible_betas.rb +5 -0
  63. data/features/thinking_sphinx/db/migrations/create_gammas.rb +3 -0
  64. data/features/thinking_sphinx/db/migrations/create_genres.rb +3 -0
  65. data/features/thinking_sphinx/db/migrations/create_music.rb +6 -0
  66. data/features/thinking_sphinx/db/migrations/create_people.rb +13 -0
  67. data/features/thinking_sphinx/db/migrations/create_posts.rb +5 -0
  68. data/features/thinking_sphinx/db/migrations/create_robots.rb +4 -0
  69. data/features/thinking_sphinx/db/migrations/create_taggings.rb +5 -0
  70. data/features/thinking_sphinx/db/migrations/create_tags.rb +4 -0
  71. data/features/thinking_sphinx/models/alpha.rb +22 -0
  72. data/features/thinking_sphinx/models/animal.rb +5 -0
  73. data/features/thinking_sphinx/models/author.rb +3 -0
  74. data/features/thinking_sphinx/models/beta.rb +8 -0
  75. data/features/thinking_sphinx/models/box.rb +8 -0
  76. data/features/thinking_sphinx/models/cat.rb +3 -0
  77. data/features/thinking_sphinx/models/category.rb +4 -0
  78. data/features/thinking_sphinx/models/comment.rb +10 -0
  79. data/features/thinking_sphinx/models/developer.rb +16 -0
  80. data/features/thinking_sphinx/models/dog.rb +3 -0
  81. data/features/thinking_sphinx/models/extensible_beta.rb +9 -0
  82. data/features/thinking_sphinx/models/fox.rb +5 -0
  83. data/features/thinking_sphinx/models/gamma.rb +5 -0
  84. data/features/thinking_sphinx/models/genre.rb +3 -0
  85. data/features/thinking_sphinx/models/medium.rb +5 -0
  86. data/features/thinking_sphinx/models/music.rb +8 -0
  87. data/features/thinking_sphinx/models/person.rb +23 -0
  88. data/features/thinking_sphinx/models/post.rb +21 -0
  89. data/features/thinking_sphinx/models/robot.rb +12 -0
  90. data/features/thinking_sphinx/models/tag.rb +3 -0
  91. data/features/thinking_sphinx/models/tagging.rb +4 -0
  92. data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
  93. data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
  94. data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
  95. data/lib/thinking_sphinx.rb +242 -0
  96. data/lib/thinking_sphinx/active_record.rb +380 -0
  97. data/lib/thinking_sphinx/active_record/attribute_updates.rb +50 -0
  98. data/lib/thinking_sphinx/active_record/delta.rb +61 -0
  99. data/lib/thinking_sphinx/active_record/has_many_association.rb +51 -0
  100. data/lib/thinking_sphinx/active_record/scopes.rb +75 -0
  101. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +46 -0
  102. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +58 -0
  103. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +147 -0
  104. data/lib/thinking_sphinx/association.rb +164 -0
  105. data/lib/thinking_sphinx/attribute.rb +390 -0
  106. data/lib/thinking_sphinx/auto_version.rb +22 -0
  107. data/lib/thinking_sphinx/class_facet.rb +15 -0
  108. data/lib/thinking_sphinx/configuration.rb +292 -0
  109. data/lib/thinking_sphinx/context.rb +74 -0
  110. data/lib/thinking_sphinx/core/array.rb +7 -0
  111. data/lib/thinking_sphinx/core/string.rb +15 -0
  112. data/lib/thinking_sphinx/deltas.rb +28 -0
  113. data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
  114. data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
  115. data/lib/thinking_sphinx/excerpter.rb +22 -0
  116. data/lib/thinking_sphinx/facet.rb +125 -0
  117. data/lib/thinking_sphinx/facet_search.rb +136 -0
  118. data/lib/thinking_sphinx/field.rb +80 -0
  119. data/lib/thinking_sphinx/index.rb +157 -0
  120. data/lib/thinking_sphinx/index/builder.rb +302 -0
  121. data/lib/thinking_sphinx/index/faux_column.rb +118 -0
  122. data/lib/thinking_sphinx/join.rb +37 -0
  123. data/lib/thinking_sphinx/property.rb +168 -0
  124. data/lib/thinking_sphinx/rails_additions.rb +150 -0
  125. data/lib/thinking_sphinx/search.rb +785 -0
  126. data/lib/thinking_sphinx/search_methods.rb +439 -0
  127. data/lib/thinking_sphinx/source.rb +159 -0
  128. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  129. data/lib/thinking_sphinx/source/sql.rb +130 -0
  130. data/lib/thinking_sphinx/tasks.rb +121 -0
  131. data/lib/thinking_sphinx/test.rb +52 -0
  132. data/rails/init.rb +16 -0
  133. data/spec/thinking_sphinx/active_record/delta_spec.rb +128 -0
  134. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +71 -0
  135. data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
  136. data/spec/thinking_sphinx/active_record_spec.rb +618 -0
  137. data/spec/thinking_sphinx/association_spec.rb +239 -0
  138. data/spec/thinking_sphinx/attribute_spec.rb +548 -0
  139. data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
  140. data/spec/thinking_sphinx/configuration_spec.rb +271 -0
  141. data/spec/thinking_sphinx/context_spec.rb +126 -0
  142. data/spec/thinking_sphinx/core/array_spec.rb +9 -0
  143. data/spec/thinking_sphinx/core/string_spec.rb +9 -0
  144. data/spec/thinking_sphinx/excerpter_spec.rb +49 -0
  145. data/spec/thinking_sphinx/facet_search_spec.rb +176 -0
  146. data/spec/thinking_sphinx/facet_spec.rb +333 -0
  147. data/spec/thinking_sphinx/field_spec.rb +113 -0
  148. data/spec/thinking_sphinx/index/builder_spec.rb +495 -0
  149. data/spec/thinking_sphinx/index/faux_column_spec.rb +36 -0
  150. data/spec/thinking_sphinx/index_spec.rb +183 -0
  151. data/spec/thinking_sphinx/rails_additions_spec.rb +203 -0
  152. data/spec/thinking_sphinx/search_methods_spec.rb +152 -0
  153. data/spec/thinking_sphinx/search_spec.rb +1206 -0
  154. data/spec/thinking_sphinx/source_spec.rb +243 -0
  155. data/spec/thinking_sphinx_spec.rb +204 -0
  156. data/tasks/distribution.rb +46 -0
  157. data/tasks/rails.rake +1 -0
  158. metadata +475 -0
@@ -0,0 +1,36 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Index::FauxColumn do
4
+ describe "coerce class method" do
5
+ before :each do
6
+ @column = stub('column')
7
+ ThinkingSphinx::Index::FauxColumn.stub!(:new => @column)
8
+ end
9
+
10
+ it "should return a single faux column if passed a string" do
11
+ ThinkingSphinx::Index::FauxColumn.coerce("string").should == @column
12
+ end
13
+
14
+ it "should return a single faux column if passed a symbol" do
15
+ ThinkingSphinx::Index::FauxColumn.coerce(:string).should == @column
16
+ end
17
+
18
+ it "should return an array of faux columns if passed an array of strings" do
19
+ ThinkingSphinx::Index::FauxColumn.coerce(["one", "two"]).should == [
20
+ @column, @column
21
+ ]
22
+ end
23
+
24
+ it "should return an array of faux columns if passed an array of symbols" do
25
+ ThinkingSphinx::Index::FauxColumn.coerce([:one, :two]).should == [
26
+ @column, @column
27
+ ]
28
+ end
29
+ end
30
+
31
+ describe '#to_ary' do
32
+ it "should return an array with the instance inside it" do
33
+ subject.to_ary.should == [subject]
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,183 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Index do
4
+ describe "prefix_fields method" do
5
+ before :each do
6
+ @index = ThinkingSphinx::Index.new(Person)
7
+
8
+ @field_a = stub('field', :prefixes => true)
9
+ @field_b = stub('field', :prefixes => false)
10
+ @field_c = stub('field', :prefixes => true)
11
+
12
+ @index.stub!(:fields => [@field_a, @field_b, @field_c])
13
+ end
14
+
15
+ it "should return fields that are flagged as prefixed" do
16
+ @index.prefix_fields.should include(@field_a)
17
+ @index.prefix_fields.should include(@field_c)
18
+ end
19
+
20
+ it "should not return fields that aren't flagged as prefixed" do
21
+ @index.prefix_fields.should_not include(@field_b)
22
+ end
23
+ end
24
+
25
+ describe "infix_fields method" do
26
+ before :each do
27
+ @index = ThinkingSphinx::Index.new(Person)
28
+
29
+ @field_a = stub('field', :infixes => true)
30
+ @field_b = stub('field', :infixes => false)
31
+ @field_c = stub('field', :infixes => true)
32
+
33
+ @index.stub!(:fields => [@field_a, @field_b, @field_c])
34
+ end
35
+
36
+ it "should return fields that are flagged as infixed" do
37
+ @index.infix_fields.should include(@field_a)
38
+ @index.infix_fields.should include(@field_c)
39
+ end
40
+
41
+ it "should not return fields that aren't flagged as infixed" do
42
+ @index.infix_fields.should_not include(@field_b)
43
+ end
44
+ end
45
+
46
+ describe '.name_for' do
47
+ it "should return the model's name downcased" do
48
+ ThinkingSphinx::Index.name_for(Alpha).should == 'alpha'
49
+ end
50
+
51
+ it "should separate words by underscores" do
52
+ ThinkingSphinx::Index.name_for(ActiveRecord).should == 'active_record'
53
+ end
54
+
55
+ it "should separate namespaces by underscores" do
56
+ ThinkingSphinx::Index.name_for(ActiveRecord::Base).
57
+ should == 'active_record_base'
58
+ end
59
+ end
60
+
61
+ describe '#name' do
62
+ it "should return the downcased name of the index's model" do
63
+ ThinkingSphinx::Index.new(Alpha).name.should == 'alpha'
64
+ end
65
+
66
+ it "should return a custom name if one is set" do
67
+ index = ThinkingSphinx::Index.new(Alpha)
68
+ index.name = 'custom'
69
+ index.name.should == 'custom'
70
+ end
71
+ end
72
+
73
+ describe '#core_name' do
74
+ it "should take the index's name and append _core" do
75
+ ThinkingSphinx::Index.new(Alpha).core_name.should == 'alpha_core'
76
+ end
77
+ end
78
+
79
+ describe '#delta_name' do
80
+ it "should take the index's name and append _delta" do
81
+ ThinkingSphinx::Index.new(Alpha).delta_name.should == 'alpha_delta'
82
+ end
83
+ end
84
+
85
+ describe '#all_names' do
86
+ it "should return the core index name by default" do
87
+ ThinkingSphinx::Index.new(Alpha).all_names.should == ['alpha_core']
88
+ end
89
+
90
+ it "should return both core and delta names if deltas are enabled" do
91
+ index = ThinkingSphinx::Index.new(Alpha)
92
+ index.delta_object = stub('delta')
93
+
94
+ index.all_names.should == ['alpha_core', 'alpha_delta']
95
+ end
96
+
97
+ it "should respect custom names" do
98
+ index = ThinkingSphinx::Index.new(Alpha)
99
+ index.name = 'custom'
100
+
101
+ index.all_names.should == ['custom_core']
102
+ end
103
+
104
+ it "should respect custom names when deltas are enabled" do
105
+ index = ThinkingSphinx::Index.new(Alpha)
106
+ index.name = 'custom'
107
+ index.delta_object = stub('delta')
108
+
109
+ index.all_names.should == ['custom_core', 'custom_delta']
110
+ end
111
+ end
112
+
113
+ describe '#to_riddle' do
114
+ it "should return two Riddle indexes if deltas are disabled" do
115
+ index = ThinkingSphinx::Index.new(Alpha)
116
+
117
+ index.to_riddle(0).length.should == 2
118
+ end
119
+
120
+ it "should return three Riddle indexes if deltas are enabled" do
121
+ index = ThinkingSphinx::Index.new(Beta)
122
+ index.delta_object = stub('delta')
123
+
124
+ index.to_riddle(0).length.should == 3
125
+ end
126
+
127
+ it "should include a distributed index" do
128
+ index = ThinkingSphinx::Index.new(Alpha)
129
+
130
+ index.to_riddle(0).last.
131
+ should be_a(Riddle::Configuration::DistributedIndex)
132
+ end
133
+
134
+ context 'core index' do
135
+ it "should use the core name" do
136
+ @index = ThinkingSphinx::Index.new(Alpha).to_riddle(0).first
137
+ @index.name.should == 'alpha_core'
138
+ end
139
+
140
+ it "should not try to set disable_range on the index" do
141
+ ThinkingSphinx::Configuration.instance.
142
+ index_options[:disable_range] = true
143
+
144
+ lambda {
145
+ @index = ThinkingSphinx::Index.new(Alpha).to_riddle(0).first
146
+ }.should_not raise_error(NoMethodError)
147
+ end
148
+ end
149
+
150
+ context 'delta index' do
151
+ before :each do
152
+ index = ThinkingSphinx::Index.new(Beta)
153
+ index.delta_object = stub('delta')
154
+ @index = index.to_riddle(0)[1]
155
+ end
156
+
157
+ it "should use the delta name" do
158
+ @index.name.should == 'beta_delta'
159
+ end
160
+ end
161
+
162
+ context 'distributed index' do
163
+ it "should use the index's name" do
164
+ index = ThinkingSphinx::Index.new(Alpha)
165
+
166
+ index.to_riddle(0).last.name.should == 'alpha'
167
+ end
168
+
169
+ it "should add the core index" do
170
+ index = ThinkingSphinx::Index.new(Alpha)
171
+
172
+ index.to_riddle(0).last.local_indexes.should include('alpha_core')
173
+ end
174
+
175
+ it "should add the delta index if there is one" do
176
+ index = ThinkingSphinx::Index.new(Beta)
177
+ index.delta_object = stub('delta')
178
+
179
+ index.to_riddle(0).last.local_indexes.should include('beta_delta')
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,203 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::HashExcept do
4
+ before(:each) do
5
+ @hash = { :number => 20, :letter => 'b', :shape => 'rectangle' }
6
+ end
7
+
8
+ describe "except method" do
9
+ it "returns a hash without the specified keys" do
10
+ new_hash = @hash.except(:number)
11
+ new_hash.should_not have_key(:number)
12
+ end
13
+ end
14
+
15
+ describe "except! method" do
16
+ it "modifies hash removing specified keys" do
17
+ @hash.except!(:number)
18
+ @hash.should_not have_key(:number)
19
+ end
20
+ end
21
+
22
+ describe "extends Hash" do
23
+ before :each do
24
+ @instance_methods = Hash.instance_methods.collect { |m| m.to_s }
25
+ end
26
+
27
+ it 'with except' do
28
+ @instance_methods.include?('except').should be_true
29
+ end
30
+
31
+ it 'with except!' do
32
+ @instance_methods.include?('except!').should be_true
33
+ end
34
+ end
35
+ end
36
+
37
+ describe ThinkingSphinx::ArrayExtractOptions do
38
+ describe 'extract_options! method' do
39
+ it 'returns a hash' do
40
+ array = []
41
+ array.extract_options!.should be_kind_of(Hash)
42
+ end
43
+
44
+ it 'returns the last option if it is a hash' do
45
+ array = ['a', 'b', {:c => 'd'}]
46
+ array.extract_options!.should == {:c => 'd'}
47
+ end
48
+ end
49
+
50
+ describe "extends Array" do
51
+ it 'with extract_options!' do
52
+ Array.instance_methods.collect { |m| m.to_s }.include?('extract_options!').should be_true
53
+ end
54
+ end
55
+ end
56
+
57
+ describe ThinkingSphinx::AbstractQuotedTableName do
58
+ describe 'quote_table_name method' do
59
+ it 'calls quote_column_name' do
60
+ adapter = ActiveRecord::ConnectionAdapters::AbstractAdapter.new(defined?(JRUBY_VERSION) ? 'jdbcmysql' : 'mysql')
61
+ adapter.should_receive(:quote_column_name).with('messages')
62
+ adapter.quote_table_name('messages')
63
+ end
64
+ end
65
+
66
+ describe "extends ActiveRecord::ConnectionAdapters::AbstractAdapter" do
67
+ it 'with quote_table_name' do
68
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.instance_methods.collect { |m|
69
+ m.to_s
70
+ }.include?('quote_table_name').should be_true
71
+ end
72
+ end
73
+ end
74
+
75
+ describe ThinkingSphinx::MysqlQuotedTableName do
76
+ describe "quote_table_name method" do
77
+ it 'correctly quotes' do
78
+ adapter = ActiveRecord::Base.connection
79
+ adapter.quote_table_name('thinking_sphinx.messages').should == "`thinking_sphinx`.`messages`"
80
+ end
81
+ end
82
+
83
+ describe "extends ActiveRecord::ConnectionAdapters::MysqlAdapter" do
84
+ it 'with quote_table_name' do
85
+ adapter = defined?(JRUBY_VERSION) ? :JdbcAdapter : :MysqlAdapter
86
+ ActiveRecord::ConnectionAdapters.const_get(adapter).instance_methods.collect { |m|
87
+ m.to_s
88
+ }.include?("quote_table_name").should be_true
89
+ end
90
+ end
91
+ end
92
+
93
+ describe ThinkingSphinx::ActiveRecordQuotedName do
94
+ describe "quoted_table_name method" do
95
+ it 'returns table name wrappd in quotes' do
96
+ Person.quoted_table_name.should == '`people`'
97
+ end
98
+ end
99
+
100
+ describe "extends ActiveRecord::Base" do
101
+ it 'with quoted_table_name' do
102
+ ActiveRecord::Base.respond_to?("quoted_table_name").should be_true
103
+ end
104
+ end
105
+ end
106
+
107
+ describe ThinkingSphinx::ActiveRecordStoreFullSTIClass do
108
+ describe "store_full_sti_class method" do
109
+ it 'returns false' do
110
+ Person.store_full_sti_class.should be_false
111
+ end
112
+ end
113
+
114
+ describe "extends ActiveRecord::Base" do
115
+ it 'with store_full_sti_class' do
116
+ ActiveRecord::Base.respond_to?(:store_full_sti_class).should be_true
117
+ end
118
+ end
119
+ end
120
+
121
+ describe ThinkingSphinx::SingletonClass do
122
+ describe 'singleton_class' do
123
+ it "should exist as an instance method in Object" do
124
+ Object.new.should respond_to('singleton_class')
125
+ end
126
+
127
+ it "should return the meta/eigen/singleton class" do
128
+ Object.new.singleton_class.should be_a(Class)
129
+ end
130
+ end
131
+ end
132
+
133
+ class TestModel
134
+ @@squares = 89
135
+ @@circles = 43
136
+
137
+ def number_of_polygons
138
+ @@polygons
139
+ end
140
+ end
141
+
142
+ describe ThinkingSphinx::ClassAttributeMethods do
143
+ describe "cattr_reader method" do
144
+ it 'creates getters' do
145
+ TestModel.cattr_reader :herbivores
146
+ test_model = TestModel.new
147
+ test_model.respond_to?(:herbivores).should be_true
148
+ end
149
+
150
+ it 'sets the initial value to nil' do
151
+ TestModel.cattr_reader :carnivores
152
+ test_model = TestModel.new
153
+ test_model.carnivores.should be_nil
154
+ end
155
+
156
+ it 'does not override an existing definition' do
157
+ TestModel.cattr_reader :squares
158
+ test_model = TestModel.new
159
+ test_model.squares.should == 89
160
+ end
161
+ end
162
+
163
+ describe "cattr_writer method" do
164
+ it 'creates setters' do
165
+ TestModel.cattr_writer :herbivores
166
+ test_model = TestModel.new
167
+ test_model.respond_to?(:herbivores=).should be_true
168
+ end
169
+
170
+ it 'does not override an existing definition' do
171
+ TestModel.cattr_writer :polygons
172
+ test_model = TestModel.new
173
+ test_model.polygons = 100
174
+ test_model.number_of_polygons.should == 100
175
+ end
176
+ end
177
+
178
+ describe "cattr_accessor method" do
179
+ it 'calls cattr_reader' do
180
+ Class.should_receive(:cattr_reader).with('polygons')
181
+ Class.cattr_accessor('polygons')
182
+ end
183
+
184
+ it 'calls cattr_writer' do
185
+ Class.should_receive(:cattr_writer).with('polygons')
186
+ Class.cattr_accessor('polygons')
187
+ end
188
+ end
189
+
190
+ describe "extends Class" do
191
+ it 'with cattr_reader' do
192
+ Class.respond_to?('cattr_reader').should be_true
193
+ end
194
+
195
+ it 'with cattr_writer' do
196
+ Class.respond_to?('cattr_writer').should be_true
197
+ end
198
+
199
+ it 'with cattr_accessor' do
200
+ Class.respond_to?('cattr_accessor').should be_true
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,152 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::SearchMethods do
4
+ it "should be included into models with indexes" do
5
+ Alpha.included_modules.should include(ThinkingSphinx::SearchMethods)
6
+ end
7
+
8
+ it "should not be included into models that don't have indexes" do
9
+ Gamma.included_modules.should_not include(ThinkingSphinx::SearchMethods)
10
+ end
11
+
12
+ describe '.search_context' do
13
+ it "should return nil if not within a model" do
14
+ ThinkingSphinx.search_context.should be_nil
15
+ end
16
+
17
+ it "should return the model if within one" do
18
+ Alpha.search_context.should == Alpha
19
+ end
20
+ end
21
+
22
+ describe '.search' do
23
+ it "should return an instance of ThinkingSphinx::Search" do
24
+ Alpha.search.class.should == ThinkingSphinx::Search
25
+ end
26
+
27
+ it "should set the classes option if not already set" do
28
+ search = Alpha.search
29
+ search.options[:classes].should == [Alpha]
30
+ end
31
+
32
+ it "shouldn't set the classes option if already defined" do
33
+ search = Alpha.search :classes => [Beta]
34
+ search.options[:classes].should == [Beta]
35
+ end
36
+
37
+ it "should default to nil for the classes options" do
38
+ ThinkingSphinx.search.options[:classes].should be_nil
39
+ end
40
+ end
41
+
42
+ describe '.search_for_ids' do
43
+ it "should return an instance of ThinkingSphinx::Search" do
44
+ Alpha.search.class.should == ThinkingSphinx::Search
45
+ end
46
+
47
+ it "should set the classes option if not already set" do
48
+ search = Alpha.search_for_ids
49
+ search.options[:classes].should == [Alpha]
50
+ end
51
+
52
+ it "shouldn't set the classes option if already defined" do
53
+ search = Alpha.search_for_ids :classes => [Beta]
54
+ search.options[:classes].should == [Beta]
55
+ end
56
+
57
+ it "should set ids_only to true" do
58
+ search = Alpha.search_for_ids
59
+ search.options[:ids_only].should be_true
60
+ end
61
+ end
62
+
63
+ describe '.search_for_id' do
64
+ before :each do
65
+ @config = ThinkingSphinx::Configuration.instance
66
+ @client = Riddle::Client.new
67
+
68
+ @config.stub!(:client => @client)
69
+ @client.stub!(:query => {:matches => [], :total_found => 0})
70
+ end
71
+
72
+ it "should set the id range to the given id value" do
73
+ ThinkingSphinx.search_for_id(101, 'alpha_core')
74
+
75
+ @client.id_range.should == (101..101)
76
+ end
77
+
78
+ it "should not make any calls to the database" do
79
+ Alpha.should_not_receive(:find)
80
+
81
+ ThinkingSphinx.search_for_id(101, 'alpha_core', :classes => [Alpha])
82
+ end
83
+
84
+ it "should return true if there is a record" do
85
+ @client.stub!(:query => {:matches => [
86
+ {:attributes => {'sphinx_internal_id' => 100}}
87
+ ], :total_found => 1})
88
+
89
+ ThinkingSphinx.search_for_id(101, 'alpha_core').should be_true
90
+ end
91
+
92
+ it "should return false if there isn't a record" do
93
+ ThinkingSphinx.search_for_id(101, 'alpha_core').should be_false
94
+ end
95
+ end
96
+
97
+ describe '.count' do
98
+ before :each do
99
+ @config = ThinkingSphinx::Configuration.instance
100
+ @client = Riddle::Client.new
101
+
102
+ @config.stub!(:client => @client)
103
+ @client.stub!(:query => {:matches => [], :total_found => 42})
104
+ end
105
+
106
+ it "should fall through to ActiveRecord if called on a class" do
107
+ @client.should_not_receive(:query)
108
+
109
+ Alpha.count
110
+ end
111
+
112
+ it "should return the total number of results if called globally" do
113
+ ThinkingSphinx.count.should == 42
114
+ end
115
+ end
116
+
117
+ describe '.search_count' do
118
+ before :each do
119
+ @config = ThinkingSphinx::Configuration.instance
120
+ @client = Riddle::Client.new
121
+
122
+ @config.stub!(:client => @client)
123
+ @client.stub!(:query => {:matches => [], :total_found => 42})
124
+ end
125
+
126
+ it "should return the total number of results" do
127
+ Alpha.search_count.should == 42
128
+ end
129
+
130
+ it "should not make any calls to the database" do
131
+ Alpha.should_not_receive(:find)
132
+
133
+ Alpha.search_count
134
+ end
135
+ end
136
+
137
+ describe '.facets' do
138
+ it "should return a FacetSearch instance" do
139
+ Alpha.facets.should be_a(ThinkingSphinx::FacetSearch)
140
+ end
141
+
142
+ it "should set the classes option if not already set" do
143
+ facets = Alpha.facets
144
+ facets.options[:classes].should == [Alpha]
145
+ end
146
+
147
+ it "shouldn't set the classes option if already defined" do
148
+ facets = Alpha.facets :classes => [Beta]
149
+ facets.options[:classes].should == [Beta]
150
+ end
151
+ end
152
+ end