skalee-thinking-sphinx 1.3.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENCE +20 -0
- data/README.textile +201 -0
- data/Rakefile +3 -0
- data/VERSION +1 -0
- data/contribute.rb +385 -0
- data/cucumber.yml +1 -0
- data/features/abstract_inheritance.feature +10 -0
- data/features/alternate_primary_key.feature +27 -0
- data/features/attribute_transformation.feature +22 -0
- data/features/attribute_updates.feature +51 -0
- data/features/deleting_instances.feature +67 -0
- data/features/direct_attributes.feature +11 -0
- data/features/excerpts.feature +13 -0
- data/features/extensible_delta_indexing.feature +9 -0
- data/features/facets.feature +82 -0
- data/features/facets_across_model.feature +29 -0
- data/features/handling_edits.feature +92 -0
- data/features/retry_stale_indexes.feature +24 -0
- data/features/searching_across_models.feature +20 -0
- data/features/searching_by_index.feature +40 -0
- data/features/searching_by_model.feature +175 -0
- data/features/searching_with_find_arguments.feature +56 -0
- data/features/sphinx_detection.feature +25 -0
- data/features/sphinx_scopes.feature +42 -0
- data/features/step_definitions/alpha_steps.rb +16 -0
- data/features/step_definitions/beta_steps.rb +7 -0
- data/features/step_definitions/common_steps.rb +188 -0
- data/features/step_definitions/extensible_delta_indexing_steps.rb +7 -0
- data/features/step_definitions/facet_steps.rb +96 -0
- data/features/step_definitions/find_arguments_steps.rb +36 -0
- data/features/step_definitions/gamma_steps.rb +15 -0
- data/features/step_definitions/scope_steps.rb +15 -0
- data/features/step_definitions/search_steps.rb +89 -0
- data/features/step_definitions/sphinx_steps.rb +35 -0
- data/features/sti_searching.feature +19 -0
- data/features/support/database.example.yml +3 -0
- data/features/support/db/.gitignore +1 -0
- data/features/support/db/fixtures/alphas.rb +10 -0
- data/features/support/db/fixtures/authors.rb +1 -0
- data/features/support/db/fixtures/betas.rb +10 -0
- data/features/support/db/fixtures/boxes.rb +9 -0
- data/features/support/db/fixtures/categories.rb +1 -0
- data/features/support/db/fixtures/cats.rb +3 -0
- data/features/support/db/fixtures/comments.rb +24 -0
- data/features/support/db/fixtures/developers.rb +29 -0
- data/features/support/db/fixtures/dogs.rb +3 -0
- data/features/support/db/fixtures/extensible_betas.rb +10 -0
- data/features/support/db/fixtures/foxes.rb +3 -0
- data/features/support/db/fixtures/gammas.rb +10 -0
- data/features/support/db/fixtures/music.rb +4 -0
- data/features/support/db/fixtures/people.rb +1001 -0
- data/features/support/db/fixtures/posts.rb +6 -0
- data/features/support/db/fixtures/robots.rb +14 -0
- data/features/support/db/fixtures/tags.rb +27 -0
- data/features/support/db/migrations/create_alphas.rb +8 -0
- data/features/support/db/migrations/create_animals.rb +5 -0
- data/features/support/db/migrations/create_authors.rb +3 -0
- data/features/support/db/migrations/create_authors_posts.rb +6 -0
- data/features/support/db/migrations/create_betas.rb +5 -0
- data/features/support/db/migrations/create_boxes.rb +5 -0
- data/features/support/db/migrations/create_categories.rb +3 -0
- data/features/support/db/migrations/create_comments.rb +10 -0
- data/features/support/db/migrations/create_developers.rb +9 -0
- data/features/support/db/migrations/create_extensible_betas.rb +5 -0
- data/features/support/db/migrations/create_gammas.rb +3 -0
- data/features/support/db/migrations/create_genres.rb +3 -0
- data/features/support/db/migrations/create_music.rb +6 -0
- data/features/support/db/migrations/create_people.rb +13 -0
- data/features/support/db/migrations/create_posts.rb +5 -0
- data/features/support/db/migrations/create_robots.rb +4 -0
- data/features/support/db/migrations/create_taggings.rb +5 -0
- data/features/support/db/migrations/create_tags.rb +4 -0
- data/features/support/env.rb +21 -0
- data/features/support/lib/generic_delta_handler.rb +8 -0
- data/features/support/models/alpha.rb +22 -0
- data/features/support/models/animal.rb +5 -0
- data/features/support/models/author.rb +3 -0
- data/features/support/models/beta.rb +8 -0
- data/features/support/models/box.rb +8 -0
- data/features/support/models/cat.rb +3 -0
- data/features/support/models/category.rb +4 -0
- data/features/support/models/comment.rb +10 -0
- data/features/support/models/developer.rb +16 -0
- data/features/support/models/dog.rb +3 -0
- data/features/support/models/extensible_beta.rb +9 -0
- data/features/support/models/fox.rb +5 -0
- data/features/support/models/gamma.rb +5 -0
- data/features/support/models/genre.rb +3 -0
- data/features/support/models/medium.rb +5 -0
- data/features/support/models/music.rb +8 -0
- data/features/support/models/person.rb +23 -0
- data/features/support/models/post.rb +21 -0
- data/features/support/models/robot.rb +12 -0
- data/features/support/models/tag.rb +3 -0
- data/features/support/models/tagging.rb +4 -0
- data/ginger_scenarios.rb +28 -0
- data/init.rb +5 -0
- data/install.rb +5 -0
- data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
- data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
- data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +19 -0
- data/lib/thinking_sphinx/active_record/delta.rb +47 -0
- data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
- data/lib/thinking_sphinx/active_record/scopes.rb +75 -0
- data/lib/thinking_sphinx/active_record.rb +348 -0
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +143 -0
- data/lib/thinking_sphinx/association.rb +164 -0
- data/lib/thinking_sphinx/attribute.rb +362 -0
- data/lib/thinking_sphinx/auto_version.rb +22 -0
- data/lib/thinking_sphinx/class_facet.rb +15 -0
- data/lib/thinking_sphinx/configuration.rb +300 -0
- data/lib/thinking_sphinx/context.rb +68 -0
- data/lib/thinking_sphinx/core/array.rb +7 -0
- data/lib/thinking_sphinx/core/string.rb +15 -0
- data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
- data/lib/thinking_sphinx/deltas.rb +28 -0
- data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
- data/lib/thinking_sphinx/excerpter.rb +22 -0
- data/lib/thinking_sphinx/facet.rb +125 -0
- data/lib/thinking_sphinx/facet_search.rb +136 -0
- data/lib/thinking_sphinx/field.rb +82 -0
- data/lib/thinking_sphinx/index/builder.rb +296 -0
- data/lib/thinking_sphinx/index/faux_column.rb +110 -0
- data/lib/thinking_sphinx/index.rb +157 -0
- data/lib/thinking_sphinx/property.rb +162 -0
- data/lib/thinking_sphinx/rails_additions.rb +150 -0
- data/lib/thinking_sphinx/search.rb +769 -0
- data/lib/thinking_sphinx/search_methods.rb +439 -0
- data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
- data/lib/thinking_sphinx/source/sql.rb +130 -0
- data/lib/thinking_sphinx/source.rb +153 -0
- data/lib/thinking_sphinx/tasks.rb +131 -0
- data/lib/thinking_sphinx/test.rb +52 -0
- data/lib/thinking_sphinx.rb +225 -0
- data/rails/init.rb +16 -0
- data/recipes/thinking_sphinx.rb +3 -0
- data/spec/fixtures/data.sql +32 -0
- data/spec/fixtures/database.yml.default +3 -0
- data/spec/fixtures/models.rb +145 -0
- data/spec/fixtures/structure.sql +125 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/sphinx_helper.rb +81 -0
- data/spec/thinking_sphinx/active_record/delta_spec.rb +128 -0
- data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +55 -0
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
- data/spec/thinking_sphinx/active_record_spec.rb +622 -0
- data/spec/thinking_sphinx/association_spec.rb +239 -0
- data/spec/thinking_sphinx/attribute_spec.rb +570 -0
- data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
- data/spec/thinking_sphinx/configuration_spec.rb +234 -0
- data/spec/thinking_sphinx/context_spec.rb +119 -0
- data/spec/thinking_sphinx/core/array_spec.rb +9 -0
- data/spec/thinking_sphinx/core/string_spec.rb +9 -0
- data/spec/thinking_sphinx/excerpter_spec.rb +57 -0
- data/spec/thinking_sphinx/facet_search_spec.rb +176 -0
- data/spec/thinking_sphinx/facet_spec.rb +333 -0
- data/spec/thinking_sphinx/field_spec.rb +154 -0
- data/spec/thinking_sphinx/index/builder_spec.rb +479 -0
- data/spec/thinking_sphinx/index/faux_column_spec.rb +30 -0
- data/spec/thinking_sphinx/index_spec.rb +183 -0
- data/spec/thinking_sphinx/rails_additions_spec.rb +203 -0
- data/spec/thinking_sphinx/search_methods_spec.rb +152 -0
- data/spec/thinking_sphinx/search_spec.rb +1181 -0
- data/spec/thinking_sphinx/source_spec.rb +235 -0
- data/spec/thinking_sphinx_spec.rb +204 -0
- data/tasks/distribution.rb +41 -0
- data/tasks/rails.rake +1 -0
- data/tasks/testing.rb +72 -0
- data/vendor/after_commit/.gitignore +1 -0
- data/vendor/after_commit/lib/after_commit/active_record.rb +122 -0
- data/vendor/after_commit/lib/after_commit/connection_adapters.rb +168 -0
- data/vendor/after_commit/lib/after_commit/test_bypass.rb +30 -0
- data/vendor/after_commit/lib/after_commit.rb +70 -0
- data/vendor/riddle/lib/riddle/0.9.8.rb +1 -0
- data/vendor/riddle/lib/riddle/0.9.9/client/filter.rb +22 -0
- data/vendor/riddle/lib/riddle/0.9.9/client.rb +49 -0
- data/vendor/riddle/lib/riddle/0.9.9/configuration/searchd.rb +28 -0
- data/vendor/riddle/lib/riddle/0.9.9.rb +7 -0
- data/vendor/riddle/lib/riddle/auto_version.rb +11 -0
- data/vendor/riddle/lib/riddle/client/filter.rb +62 -0
- data/vendor/riddle/lib/riddle/client/message.rb +70 -0
- data/vendor/riddle/lib/riddle/client/response.rb +94 -0
- data/vendor/riddle/lib/riddle/client.rb +745 -0
- data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +49 -0
- data/vendor/riddle/lib/riddle/configuration/index.rb +149 -0
- data/vendor/riddle/lib/riddle/configuration/indexer.rb +20 -0
- data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
- data/vendor/riddle/lib/riddle/configuration/searchd.rb +28 -0
- data/vendor/riddle/lib/riddle/configuration/section.rb +43 -0
- data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
- data/vendor/riddle/lib/riddle/configuration/sql_source.rb +53 -0
- data/vendor/riddle/lib/riddle/configuration/xml_source.rb +29 -0
- data/vendor/riddle/lib/riddle/configuration.rb +33 -0
- data/vendor/riddle/lib/riddle/controller.rb +78 -0
- data/vendor/riddle/lib/riddle.rb +51 -0
- metadata +312 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Source do
|
4
|
+
before :each do
|
5
|
+
@index = ThinkingSphinx::Index.new(Person)
|
6
|
+
@source = ThinkingSphinx::Source.new(@index, :sql_range_step => 1000)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#initialize' do
|
10
|
+
it "should store the current connection details" do
|
11
|
+
config = Person.connection.instance_variable_get(:@config)
|
12
|
+
@source.database_configuration.should == config
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should generate the name from the model" do
|
17
|
+
@source.name.should == "person"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should handle namespaced models for name generation" do
|
21
|
+
index = ThinkingSphinx::Index.new(Admin::Person)
|
22
|
+
source = ThinkingSphinx::Source.new(index)
|
23
|
+
source.name.should == "admin_person"
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#to_riddle_for_core" do
|
27
|
+
before :each do
|
28
|
+
config = ThinkingSphinx::Configuration.instance
|
29
|
+
config.source_options[:sql_ranged_throttle] = 100
|
30
|
+
|
31
|
+
ThinkingSphinx::Field.new(
|
32
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:first_name)
|
33
|
+
)
|
34
|
+
ThinkingSphinx::Field.new(
|
35
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:last_name)
|
36
|
+
)
|
37
|
+
|
38
|
+
ThinkingSphinx::Attribute.new(
|
39
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:id), :as => :internal_id
|
40
|
+
)
|
41
|
+
ThinkingSphinx::Attribute.new(
|
42
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:birthday)
|
43
|
+
)
|
44
|
+
ThinkingSphinx::Attribute.new(
|
45
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:tags, :id), :as => :tag_ids
|
46
|
+
)
|
47
|
+
ThinkingSphinx::Attribute.new(
|
48
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:contacts, :id),
|
49
|
+
:as => :contact_ids, :source => :query
|
50
|
+
)
|
51
|
+
|
52
|
+
@source.conditions << "`birthday` <= NOW()"
|
53
|
+
@source.groupings << "`first_name`"
|
54
|
+
|
55
|
+
@index.local_options[:group_concat_max_len] = 1024
|
56
|
+
|
57
|
+
@riddle = @source.to_riddle_for_core(1, 0)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should generate a Riddle Source object" do
|
61
|
+
@riddle.should be_a_kind_of(Riddle::Configuration::SQLSource)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should use the index and name its own name" do
|
65
|
+
@riddle.name.should == "person_core_0"
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should use the model's database connection to determine type" do
|
69
|
+
@riddle.type.should == "mysql"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should match the model's database settings" do
|
73
|
+
config = Person.connection.instance_variable_get(:@config)
|
74
|
+
@riddle.sql_db.should == config[:database]
|
75
|
+
@riddle.sql_user.should == config[:username]
|
76
|
+
@riddle.sql_pass.should == config[:password].to_s
|
77
|
+
@riddle.sql_host.should == config[:host]
|
78
|
+
@riddle.sql_port.should == config[:port]
|
79
|
+
@riddle.sql_sock.should == config[:socket]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should use a default username of root if nothing else is provided" do
|
83
|
+
Person.connection.stub!(:instance_variable_get => {
|
84
|
+
:user => nil,
|
85
|
+
:username => nil
|
86
|
+
})
|
87
|
+
@source = ThinkingSphinx::Source.new(@index)
|
88
|
+
|
89
|
+
riddle = @source.to_riddle_for_core(1, 0)
|
90
|
+
riddle.sql_user.should == 'root'
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should assign attributes" do
|
94
|
+
# 3 internal attributes plus the one requested
|
95
|
+
@riddle.sql_attr_uint.length.should == 4
|
96
|
+
@riddle.sql_attr_uint.last.should == :internal_id
|
97
|
+
|
98
|
+
@riddle.sql_attr_timestamp.length.should == 1
|
99
|
+
@riddle.sql_attr_timestamp.first.should == :birthday
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should set Sphinx Source options" do
|
103
|
+
@riddle.sql_range_step.should == 1000
|
104
|
+
@riddle.sql_ranged_throttle.should == 100
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#sql_query" do
|
108
|
+
before :each do
|
109
|
+
@query = @riddle.sql_query
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should select data from the model table" do
|
113
|
+
@query.should match(/FROM `people`/)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should select each of the fields" do
|
117
|
+
@query.should match(/`first_name`.+FROM/)
|
118
|
+
@query.should match(/`last_name`.+FROM/)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should select each of the attributes" do
|
122
|
+
@query.should match(/`id` AS `internal_id`.+FROM/)
|
123
|
+
@query.should match(/`birthday`.+FROM/)
|
124
|
+
@query.should match(/`tags`.`id`.+ AS `tag_ids`.+FROM/)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should not match the sourced MVA attribute" do
|
128
|
+
@query.should_not match(/contact_ids/)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should include joins for required associations" do
|
132
|
+
@query.should match(/LEFT OUTER JOIN `tags`/)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should not include joins for the sourced MVA attribute" do
|
136
|
+
@query.should_not match(/LEFT OUTER JOIN `contacts`/)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should include any defined conditions" do
|
140
|
+
@query.should match(/WHERE.+`birthday` <= NOW()/)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should include any defined groupings" do
|
144
|
+
@query.should match(/GROUP BY.+`first_name`/)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "#sql_query_range" do
|
149
|
+
before :each do
|
150
|
+
@query = @riddle.sql_query_range
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should select data from the model table" do
|
154
|
+
@query.should match(/FROM `people`/)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should select the minimum and the maximum ids" do
|
158
|
+
@query.should match(/SELECT.+MIN.+MAX.+FROM/)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "#sql_query_info" do
|
163
|
+
before :each do
|
164
|
+
@query = @riddle.sql_query_info
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should select all fields from the model table" do
|
168
|
+
@query.should match(/SELECT \* FROM `people`/)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should filter the primary key with the offset" do
|
172
|
+
model_count = ThinkingSphinx.context.indexed_models.size
|
173
|
+
@query.should match(/WHERE `id` = \(\(\$id - 1\) \/ #{model_count}\)/)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#sql_query_pre" do
|
178
|
+
before :each do
|
179
|
+
@queries = @riddle.sql_query_pre
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should default to just the UTF8 statement" do
|
183
|
+
@queries.detect { |query|
|
184
|
+
query == "SET NAMES utf8"
|
185
|
+
}.should_not be_nil
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should set the group_concat_max_len session value for MySQL if requested" do
|
189
|
+
@queries.detect { |query|
|
190
|
+
query == "SET SESSION group_concat_max_len = 1024"
|
191
|
+
}.should_not be_nil
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "#to_riddle_for_core with range disabled" do
|
197
|
+
before :each do
|
198
|
+
ThinkingSphinx::Field.new(
|
199
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:first_name)
|
200
|
+
)
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "set per-index" do
|
204
|
+
before :each do
|
205
|
+
@index.local_options[:disable_range] = true
|
206
|
+
@riddle = @source.to_riddle_for_core(1, 0)
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should not have the range in the sql_query" do
|
210
|
+
@riddle.sql_query.should_not match(/`people`.`id` >= \$start/)
|
211
|
+
@riddle.sql_query.should_not match(/`people`.`id` <= \$end/)
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should not have a sql_query_range" do
|
215
|
+
@riddle.sql_query_range.should be_nil
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe "set globally" do
|
220
|
+
before :each do
|
221
|
+
ThinkingSphinx::Configuration.instance.index_options[:disable_range] = true
|
222
|
+
@riddle = @source.to_riddle_for_core(1, 0)
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should not have the range in the sql_query" do
|
226
|
+
@riddle.sql_query.should_not match(/`people`.`id` >= \$start/)
|
227
|
+
@riddle.sql_query.should_not match(/`people`.`id` <= \$end/)
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should not have a sql_query_range" do
|
231
|
+
@riddle.sql_query_range.should be_nil
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx do
|
4
|
+
describe '.context' do
|
5
|
+
it "should return a Context instance" do
|
6
|
+
ThinkingSphinx.context.should be_a(ThinkingSphinx::Context)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should remember changes to the Context instance" do
|
10
|
+
models = ThinkingSphinx.context.indexed_models
|
11
|
+
|
12
|
+
ThinkingSphinx.context.indexed_models.replace([:model])
|
13
|
+
ThinkingSphinx.context.indexed_models.should == [:model]
|
14
|
+
|
15
|
+
ThinkingSphinx.context.indexed_models.replace(models)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.reset_context!' do
|
20
|
+
it "should remove the existing Context instance" do
|
21
|
+
existing = ThinkingSphinx.context
|
22
|
+
|
23
|
+
ThinkingSphinx.reset_context!
|
24
|
+
ThinkingSphinx.context.should_not == existing
|
25
|
+
|
26
|
+
Thread.current[:thinking_sphinx_context] = existing
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.define_indexes?' do
|
31
|
+
it "should define indexes by default" do
|
32
|
+
ThinkingSphinx.define_indexes?.should be_true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '.define_indexes=' do
|
37
|
+
it "should disable index definition" do
|
38
|
+
ThinkingSphinx.define_indexes = false
|
39
|
+
ThinkingSphinx.define_indexes?.should be_false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should enable index definition" do
|
43
|
+
ThinkingSphinx.define_indexes = false
|
44
|
+
ThinkingSphinx.define_indexes?.should be_false
|
45
|
+
ThinkingSphinx.define_indexes = true
|
46
|
+
ThinkingSphinx.define_indexes?.should be_true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '.deltas_enabled?' do
|
51
|
+
it "should index deltas by default" do
|
52
|
+
ThinkingSphinx.deltas_enabled = nil
|
53
|
+
ThinkingSphinx.deltas_enabled?.should be_true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '.deltas_enabled=' do
|
58
|
+
it "should disable delta indexing" do
|
59
|
+
ThinkingSphinx.deltas_enabled = false
|
60
|
+
ThinkingSphinx.deltas_enabled?.should be_false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should enable delta indexing" do
|
64
|
+
ThinkingSphinx.deltas_enabled = false
|
65
|
+
ThinkingSphinx.deltas_enabled?.should be_false
|
66
|
+
ThinkingSphinx.deltas_enabled = true
|
67
|
+
ThinkingSphinx.deltas_enabled?.should be_true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '.updates_enabled?' do
|
72
|
+
it "should update indexes by default" do
|
73
|
+
ThinkingSphinx.updates_enabled = nil
|
74
|
+
ThinkingSphinx.updates_enabled?.should be_true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '.updates_enabled=' do
|
79
|
+
it "should disable index updating" do
|
80
|
+
ThinkingSphinx.updates_enabled = false
|
81
|
+
ThinkingSphinx.updates_enabled?.should be_false
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should enable index updating" do
|
85
|
+
ThinkingSphinx.updates_enabled = false
|
86
|
+
ThinkingSphinx.updates_enabled?.should be_false
|
87
|
+
ThinkingSphinx.updates_enabled = true
|
88
|
+
ThinkingSphinx.updates_enabled?.should be_true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '.sphinx_running?' do
|
93
|
+
it "should always say Sphinx is running if flagged as being on a remote machine" do
|
94
|
+
ThinkingSphinx.remote_sphinx = true
|
95
|
+
ThinkingSphinx.stub!(:sphinx_running_by_pid? => false)
|
96
|
+
|
97
|
+
ThinkingSphinx.sphinx_running?.should be_true
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should actually pay attention to Sphinx if not on a remote machine" do
|
101
|
+
ThinkingSphinx.remote_sphinx = false
|
102
|
+
ThinkingSphinx.stub!(:sphinx_running_by_pid? => false)
|
103
|
+
ThinkingSphinx.sphinx_running?.should be_false
|
104
|
+
|
105
|
+
ThinkingSphinx.stub!(:sphinx_running_by_pid? => true)
|
106
|
+
ThinkingSphinx.sphinx_running?.should be_true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '.version' do
|
111
|
+
it "should return the version from the stored YAML file" do
|
112
|
+
version = Jeweler::VersionHelper.new(
|
113
|
+
File.join(File.dirname(__FILE__), '..')
|
114
|
+
).to_s
|
115
|
+
|
116
|
+
ThinkingSphinx.version.should == version
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "use_group_by_shortcut? method" do
|
121
|
+
before :each do
|
122
|
+
adapter = defined?(JRUBY_VERSION) ? :JdbcAdapter : :MysqlAdapter
|
123
|
+
unless ::ActiveRecord::ConnectionAdapters.const_defined?(adapter)
|
124
|
+
pending "No MySQL"
|
125
|
+
return
|
126
|
+
end
|
127
|
+
|
128
|
+
@connection = stub('adapter',
|
129
|
+
:select_all => true,
|
130
|
+
:class => ActiveRecord::ConnectionAdapters::MysqlAdapter,
|
131
|
+
:config => {:adapter => defined?(JRUBY_VERSION) ? 'jdbcmysql' : 'mysql'}
|
132
|
+
)
|
133
|
+
::ActiveRecord::Base.stub!(
|
134
|
+
:connection => @connection
|
135
|
+
)
|
136
|
+
|
137
|
+
Thread.current[:thinking_sphinx_use_group_by_shortcut] = nil
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should return true if no ONLY_FULL_GROUP_BY" do
|
141
|
+
@connection.stub!(
|
142
|
+
:select_all => {:a => "OTHER SETTINGS"}
|
143
|
+
)
|
144
|
+
|
145
|
+
ThinkingSphinx.use_group_by_shortcut?.should be_true
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should return true if NULL value" do
|
149
|
+
@connection.stub!(
|
150
|
+
:select_all => {:a => nil}
|
151
|
+
)
|
152
|
+
|
153
|
+
ThinkingSphinx.use_group_by_shortcut?.should be_true
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should return false if ONLY_FULL_GROUP_BY is set" do
|
157
|
+
@connection.stub!(
|
158
|
+
:select_all => {:a => "OTHER SETTINGS,ONLY_FULL_GROUP_BY,blah"}
|
159
|
+
)
|
160
|
+
|
161
|
+
ThinkingSphinx.use_group_by_shortcut?.should be_false
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should return false if ONLY_FULL_GROUP_BY is set in any of the values" do
|
165
|
+
@connection.stub!(
|
166
|
+
:select_all => {
|
167
|
+
:a => "OTHER SETTINGS",
|
168
|
+
:b => "ONLY_FULL_GROUP_BY"
|
169
|
+
}
|
170
|
+
)
|
171
|
+
|
172
|
+
ThinkingSphinx.use_group_by_shortcut?.should be_false
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "if not using MySQL" do
|
176
|
+
before :each do
|
177
|
+
adapter = defined?(JRUBY_VERSION) ? 'JdbcAdapter' : 'PostgreSQLAdapter'
|
178
|
+
unless ::ActiveRecord::ConnectionAdapters.const_defined?(adapter)
|
179
|
+
pending "No PostgreSQL"
|
180
|
+
return
|
181
|
+
end
|
182
|
+
|
183
|
+
@connection = stub(adapter).as_null_object
|
184
|
+
@connection.stub!(
|
185
|
+
:select_all => true,
|
186
|
+
:config => {:adapter => defined?(JRUBY_VERSION) ? 'jdbcpostgresql' : 'postgresql'}
|
187
|
+
)
|
188
|
+
::ActiveRecord::Base.stub!(
|
189
|
+
:connection => @connection
|
190
|
+
)
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should return false" do
|
194
|
+
ThinkingSphinx.use_group_by_shortcut?.should be_false
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should not call select_all" do
|
198
|
+
@connection.should_not_receive(:select_all)
|
199
|
+
|
200
|
+
ThinkingSphinx.use_group_by_shortcut?
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'yard'
|
2
|
+
require 'jeweler'
|
3
|
+
|
4
|
+
desc 'Generate documentation'
|
5
|
+
YARD::Rake::YardocTask.new
|
6
|
+
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "hawkerb-thinking-sphinx"
|
9
|
+
gem.summary = "ActiveRecord/Rails Sphinx library"
|
10
|
+
gem.description = "A concise and easy-to-use Ruby library that connects ActiveRecord to the Sphinx search daemon, managing configuration, indexing and searching."
|
11
|
+
gem.authors = ["Pat Allan", "Jaroslaw Skrzypek"]
|
12
|
+
gem.email = "hawk@zenbe.com"
|
13
|
+
gem.homepage = "http://github.com/hawkerb/thinking-sphinx"
|
14
|
+
|
15
|
+
# s.rubyforge_project = "thinking-sphinx"
|
16
|
+
gem.files = FileList[
|
17
|
+
"rails/*.rb",
|
18
|
+
"lib/**/*.rb",
|
19
|
+
"LICENCE",
|
20
|
+
"README.textile",
|
21
|
+
"tasks/**/*.rb",
|
22
|
+
"tasks/**/*.rake",
|
23
|
+
"VERSION"
|
24
|
+
]
|
25
|
+
gem.test_files = FileList[
|
26
|
+
"features/**/*",
|
27
|
+
"spec/**/*_spec.rb"
|
28
|
+
]
|
29
|
+
|
30
|
+
gem.add_dependency 'activerecord', '>= 1.15.6'
|
31
|
+
gem.add_dependency 'riddle', '>= 1.0.8'
|
32
|
+
gem.add_dependency 'after_commit', '>= 1.0.5'
|
33
|
+
|
34
|
+
gem.post_install_message = <<-MESSAGE
|
35
|
+
If you're upgrading, you should read this:
|
36
|
+
http://freelancing-god.github.com/ts/en/upgrading.html
|
37
|
+
|
38
|
+
MESSAGE
|
39
|
+
end
|
40
|
+
Jeweler::GemcutterTasks.new
|
41
|
+
|
data/tasks/rails.rake
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../lib/thinking_sphinx/tasks')
|
data/tasks/testing.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
require 'cucumber/rake/task'
|
4
|
+
|
5
|
+
desc "Run the specs under spec"
|
6
|
+
Spec::Rake::SpecTask.new do |t|
|
7
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
8
|
+
t.spec_opts << "-c"
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Run all feature-set configurations"
|
12
|
+
task :features do |t|
|
13
|
+
databases = ENV['DATABASES'] || 'mysql,postgresql'
|
14
|
+
databases.split(',').each do |database|
|
15
|
+
puts "rake features:#{database}"
|
16
|
+
system "rake features:#{database}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
namespace :features do
|
21
|
+
def add_task(name, description)
|
22
|
+
Cucumber::Rake::Task.new(name, description) do |t|
|
23
|
+
t.cucumber_opts = "--format pretty features/*.feature DATABASE=#{name}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
add_task :mysql, "Run feature-set against MySQL"
|
28
|
+
add_task :postgresql, "Run feature-set against PostgreSQL"
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Generate RCov reports"
|
32
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
33
|
+
t.libs << 'lib'
|
34
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
35
|
+
t.rcov = true
|
36
|
+
t.rcov_opts = [
|
37
|
+
'--exclude', 'spec',
|
38
|
+
'--exclude', 'gems',
|
39
|
+
'--exclude', 'riddle',
|
40
|
+
'--exclude', 'ruby'
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
namespace :rcov do
|
45
|
+
def add_task(name, description)
|
46
|
+
Cucumber::Rake::Task.new(name, description) do |t|
|
47
|
+
t.cucumber_opts = "--format pretty"
|
48
|
+
t.profile = name
|
49
|
+
t.rcov = true
|
50
|
+
t.rcov_opts = [
|
51
|
+
'--exclude', 'spec',
|
52
|
+
'--exclude', 'gems',
|
53
|
+
'--exclude', 'riddle',
|
54
|
+
'--exclude', 'features'
|
55
|
+
]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
add_task :mysql, "Run feature-set against MySQL with rcov"
|
60
|
+
add_task :postgresql, "Run feature-set against PostgreSQL with rcov"
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Build cucumber.yml file"
|
64
|
+
task :cucumber_defaults do
|
65
|
+
steps = FileList["features/step_definitions/**.rb"].collect { |path|
|
66
|
+
"--require #{path}"
|
67
|
+
}.join(" ")
|
68
|
+
|
69
|
+
File.open('cucumber.yml', 'w') { |f|
|
70
|
+
f.write "default: \"--require features/support/env.rb #{steps}\"\n"
|
71
|
+
}
|
72
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
test.sqlite3
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module AfterCommit
|
2
|
+
module ActiveRecord
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
class << self
|
6
|
+
def establish_connection_with_after_commit(spec = nil)
|
7
|
+
establish_connection_without_after_commit spec
|
8
|
+
include_after_commit_extensions
|
9
|
+
end
|
10
|
+
alias_method_chain :establish_connection, :after_commit
|
11
|
+
|
12
|
+
def include_after_commit_extensions
|
13
|
+
base = ::ActiveRecord::ConnectionAdapters::AbstractAdapter
|
14
|
+
Object.subclasses_of(base).each do |klass|
|
15
|
+
include_after_commit_extension klass
|
16
|
+
end
|
17
|
+
|
18
|
+
if defined?(JRUBY_VERSION) and defined?(JdbcSpec::MySQL)
|
19
|
+
include_after_commit_extension JdbcSpec::MySQL
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def include_after_commit_extension(adapter)
|
26
|
+
additions = AfterCommit::ConnectionAdapters
|
27
|
+
unless adapter.included_modules.include?(additions)
|
28
|
+
adapter.send :include, additions
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# The define_callbacks method was added post Rails 2.0.2 - if it
|
34
|
+
# doesn't exist, we define the callback manually
|
35
|
+
if respond_to?(:define_callbacks)
|
36
|
+
define_callbacks :after_commit,
|
37
|
+
:after_commit_on_create,
|
38
|
+
:after_commit_on_update,
|
39
|
+
:after_commit_on_destroy,
|
40
|
+
:after_rollback,
|
41
|
+
:before_commit,
|
42
|
+
:before_commit_on_create,
|
43
|
+
:before_commit_on_update,
|
44
|
+
:before_commit_on_destroy,
|
45
|
+
:before_rollback
|
46
|
+
else
|
47
|
+
class << self
|
48
|
+
# Handle after_commit callbacks - call all the registered callbacks.
|
49
|
+
def after_commit(*callbacks, &block)
|
50
|
+
callbacks << block if block_given?
|
51
|
+
write_inheritable_array(:after_commit, callbacks)
|
52
|
+
end
|
53
|
+
|
54
|
+
def after_commit_on_create(*callbacks, &block)
|
55
|
+
callbacks << block if block_given?
|
56
|
+
write_inheritable_array(:after_commit_on_create, callbacks)
|
57
|
+
end
|
58
|
+
|
59
|
+
def after_commit_on_update(*callbacks, &block)
|
60
|
+
callbacks << block if block_given?
|
61
|
+
write_inheritable_array(:after_commit_on_update, callbacks)
|
62
|
+
end
|
63
|
+
|
64
|
+
def after_commit_on_destroy(*callbacks, &block)
|
65
|
+
callbacks << block if block_given?
|
66
|
+
write_inheritable_array(:after_commit_on_destroy, callbacks)
|
67
|
+
end
|
68
|
+
|
69
|
+
def after_rollback(*callbacks, &block)
|
70
|
+
callbacks << block if block_given?
|
71
|
+
write_inheritable_array(:after_commit, callbacks)
|
72
|
+
end
|
73
|
+
|
74
|
+
def before_commit(*callbacks, &block)
|
75
|
+
callbacks << block if block_given?
|
76
|
+
write_inheritable_array(:before_commit, callbacks)
|
77
|
+
end
|
78
|
+
|
79
|
+
def before_commit_on_create(*callbacks, &block)
|
80
|
+
callbacks << block if block_given?
|
81
|
+
write_inheritable_array(:before_commit_on_create, callbacks)
|
82
|
+
end
|
83
|
+
|
84
|
+
def before_commit_on_update(*callbacks, &block)
|
85
|
+
callbacks << block if block_given?
|
86
|
+
write_inheritable_array(:before_commit_on_update, callbacks)
|
87
|
+
end
|
88
|
+
|
89
|
+
def before_commit_on_destroy(*callbacks, &block)
|
90
|
+
callbacks << block if block_given?
|
91
|
+
write_inheritable_array(:before_commit_on_destroy, callbacks)
|
92
|
+
end
|
93
|
+
|
94
|
+
def before_rollback(*callbacks, &block)
|
95
|
+
callbacks << block if block_given?
|
96
|
+
write_inheritable_array(:before_commit, callbacks)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
after_create :add_committed_record_on_create
|
102
|
+
after_update :add_committed_record_on_update
|
103
|
+
after_destroy :add_committed_record_on_destroy
|
104
|
+
|
105
|
+
def add_committed_record_on_create
|
106
|
+
AfterCommit.record(self.class.connection, self)
|
107
|
+
AfterCommit.record_created(self.class.connection, self)
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_committed_record_on_update
|
111
|
+
AfterCommit.record(self.class.connection, self)
|
112
|
+
AfterCommit.record_updated(self.class.connection, self)
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_committed_record_on_destroy
|
116
|
+
AfterCommit.record(self.class.connection, self)
|
117
|
+
AfterCommit.record_destroyed(self.class.connection, self)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|