thinking-sphinx 1.4.6 → 1.4.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/README.textile +6 -1
  2. data/features/searching_by_model.feature +24 -30
  3. data/features/thinking_sphinx/db/.gitignore +1 -0
  4. data/features/thinking_sphinx/db/fixtures/post_keywords.txt +1 -0
  5. data/lib/cucumber/thinking_sphinx/internal_world.rb +26 -26
  6. data/lib/thinking_sphinx.rb +17 -26
  7. data/lib/thinking_sphinx/active_record.rb +69 -74
  8. data/lib/thinking_sphinx/active_record/attribute_updates.rb +11 -10
  9. data/lib/thinking_sphinx/active_record/has_many_association.rb +2 -1
  10. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +11 -11
  11. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +34 -20
  12. data/lib/thinking_sphinx/association.rb +12 -7
  13. data/lib/thinking_sphinx/attribute.rb +64 -61
  14. data/lib/thinking_sphinx/configuration.rb +32 -36
  15. data/lib/thinking_sphinx/context.rb +3 -2
  16. data/lib/thinking_sphinx/deploy/capistrano.rb +7 -9
  17. data/lib/thinking_sphinx/search.rb +201 -178
  18. data/lib/thinking_sphinx/source/sql.rb +1 -1
  19. data/lib/thinking_sphinx/tasks.rb +21 -19
  20. data/lib/thinking_sphinx/version.rb +3 -0
  21. data/spec/fixtures/data.sql +32 -0
  22. data/spec/fixtures/database.yml.default +3 -0
  23. data/spec/fixtures/models.rb +161 -0
  24. data/spec/fixtures/structure.sql +146 -0
  25. data/spec/spec_helper.rb +57 -0
  26. data/spec/sphinx_helper.rb +61 -0
  27. data/spec/thinking_sphinx/active_record/delta_spec.rb +24 -24
  28. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +22 -0
  29. data/spec/thinking_sphinx/active_record/scopes_spec.rb +25 -25
  30. data/spec/thinking_sphinx/active_record_spec.rb +110 -109
  31. data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +38 -38
  32. data/spec/thinking_sphinx/association_spec.rb +20 -2
  33. data/spec/thinking_sphinx/context_spec.rb +61 -64
  34. data/spec/thinking_sphinx/search_spec.rb +7 -0
  35. data/spec/thinking_sphinx_spec.rb +47 -46
  36. metadata +50 -98
  37. data/VERSION +0 -1
  38. data/tasks/distribution.rb +0 -34
  39. data/tasks/testing.rb +0 -80
@@ -122,7 +122,6 @@ Since I first released this library, there's been quite a few people who have su
122
122
  * Andrei Bocan
123
123
  * László Bácsi
124
124
  * Peter Wagenet
125
- * Max Lapshin
126
125
  * Martin Emde
127
126
  * David Wennergren
128
127
  * Mark Lane
@@ -192,3 +191,9 @@ Since I first released this library, there's been quite a few people who have su
192
191
  * Ryan Mohr
193
192
  * Alex Chee
194
193
  * Bruno Santschi
194
+ * Lars Weiler
195
+ * Andrey Deryabin
196
+ * Andrew White
197
+ * Rémi Prévost
198
+ * Justin Tanner
199
+ * Josh Goebel
@@ -2,19 +2,19 @@ Feature: Searching on a single model
2
2
  In order to use Thinking Sphinx's core functionality
3
3
  A developer
4
4
  Should be able to search on a single model
5
-
5
+
6
6
  Scenario: Searching using a basic query
7
7
  Given Sphinx is running
8
8
  And I am searching on people
9
9
  When I search for James
10
10
  Then I should get 3 results
11
-
11
+
12
12
  Scenario: Searching on a specific field
13
13
  Given Sphinx is running
14
14
  And I am searching on people
15
15
  When I search for James on first_name
16
16
  Then I should get 2 results
17
-
17
+
18
18
  Scenario: Searching on multiple fields
19
19
  Given Sphinx is running
20
20
  And I am searching on people
@@ -25,32 +25,32 @@ Feature: Searching on a single model
25
25
  Scenario: Searching on association content
26
26
  Given Sphinx is running
27
27
  And I am searching on posts
28
-
28
+
29
29
  When I search for "Waffles"
30
30
  Then I should get 1 result
31
31
 
32
32
  When I search for "Turtle"
33
33
  Then I should get 1 result
34
-
34
+
35
35
  Scenario: Searching with a filter
36
36
  Given Sphinx is running
37
37
  And I am searching on alphas
38
38
  When I filter by 1 on value
39
39
  Then I should get 1 result
40
-
40
+
41
41
  Scenario: Searching with multiple filters
42
42
  Given Sphinx is running
43
43
  And I am searching on boxes
44
44
  When I filter by 2 on width
45
45
  And I filter by 2 on length
46
46
  Then I should get 1 result
47
-
47
+
48
48
  Scenario: Searching with a ranged time filter
49
49
  Given Sphinx is running
50
50
  And I am searching on people
51
51
  When I filter by birthday between 1975 and 1976
52
52
  Then I should get 16 results
53
-
53
+
54
54
  Scenario: Searching to filter multiple values on an MVA
55
55
  Given Sphinx is running
56
56
  And I am searching on boxes
@@ -59,31 +59,25 @@ Feature: Searching on a single model
59
59
  When I clear existing filters
60
60
  And I filter by both 11 and 12 on dimensions
61
61
  Then I should get 1 result
62
-
62
+
63
63
  Scenario: Filtering on timestamp MVAs
64
64
  Given Sphinx is running
65
65
  And I am searching on posts
66
66
  When I filter by 2001-01-01 on comments_created_at
67
67
  Then I should get 1 result
68
-
69
- Scenario: Filtering on a wordcount attribute
70
- Given Sphinx is running
71
- And I am searching on developers
72
- When I filter between 0 and 1 on state_wordcount
73
- Then I should get 5 results
74
-
68
+
75
69
  Scenario: Searching by NULL/0 values in MVAs
76
70
  Given Sphinx is running
77
71
  And I am searching on boxes
78
72
  When I filter by 0 on dimensions
79
73
  Then I should get 1 result
80
-
74
+
81
75
  Given Sphinx is running
82
76
  And I am searching on developers
83
77
  When I clear existing filters
84
78
  And I filter by 0 on tag_ids
85
79
  Then I should get 1 result
86
-
80
+
87
81
  Scenario: Searching on a MVA configured as ranged_query
88
82
  Given Sphinx is running
89
83
  And I am searching on posts
@@ -95,59 +89,59 @@ Feature: Searching on a single model
95
89
  When I clear existing filters
96
90
  And I filter by 10 on comment_ids
97
91
  Then I should get 0 results
98
-
92
+
99
93
  Scenario: Searching with ordering by attribute
100
94
  Given Sphinx is running
101
95
  And I am searching on alphas
102
96
  When I order by value
103
97
  Then I should get 10 results
104
98
  And the value of each result should indicate order
105
-
99
+
106
100
  Scenario: Intepreting Sphinx Internal Identifiers
107
101
  Given Sphinx is running
108
102
  And I am searching on people
109
103
  Then I should get 20 results
110
104
  And each result id should match the corresponding sphinx internal id
111
-
105
+
112
106
  Scenario: Retrieving weightings
113
107
  Given Sphinx is running
114
108
  And I am searching on people
115
109
  When I search for "Ellie Ford"
116
110
  And I set match mode to any
117
111
  Then I can iterate by result and weighting
118
-
112
+
119
113
  Scenario: Retrieving group counts
120
114
  Given Sphinx is running
121
115
  And I am searching on people
122
116
  When I group results by the birthday attribute
123
117
  Then I can iterate by result and count
124
-
118
+
125
119
  Scenario: Retrieving group values
126
120
  Given Sphinx is running
127
121
  And I am searching on people
128
122
  When I group results by the birthday attribute
129
123
  Then I can iterate by result and group
130
-
124
+
131
125
  Scenario: Retrieving both group values and counts
132
126
  Given Sphinx is running
133
127
  And I am searching on people
134
128
  When I group results by the birthday attribute
135
129
  Then I can iterate by result and group and count
136
-
130
+
137
131
  Scenario: Searching for ids
138
132
  Given Sphinx is running
139
133
  And I am searching on people
140
134
  When I search for Ellie
141
135
  And I am searching for ids
142
136
  Then I should have an array of integers
143
-
137
+
144
138
  Scenario: Search results should match Sphinx's order
145
139
  Given Sphinx is running
146
140
  And I am searching on people
147
141
  When I search for Ellie
148
142
  And I order by "sphinx_internal_id DESC"
149
143
  Then searching for ids should match the record ids of the normal search results
150
-
144
+
151
145
  Scenario: Retrieving total result count when total is less than a page
152
146
  Given Sphinx is running
153
147
  And I am searching on people
@@ -160,7 +154,7 @@ Feature: Searching on a single model
160
154
  And I am searching on people
161
155
  When I am retrieving the result count
162
156
  Then I should get a value of 1000
163
-
157
+
164
158
  Scenario: Searching with Unicode Characters
165
159
  Given Sphinx is running
166
160
  And I am searching on people
@@ -172,10 +166,10 @@ Feature: Searching on a single model
172
166
  And I am searching on posts
173
167
  When I search for "Shakespeare"
174
168
  Then I should get 1 result
175
-
169
+
176
170
  Scenario: Searching on content from file field
177
171
  Given Sphinx is running
178
172
  And I am searching on posts
179
173
  When I search for "foo bar baz"
180
174
  Then I should get 1 result
181
-
175
+
@@ -0,0 +1 @@
1
+ database.yml
@@ -7,7 +7,7 @@ module Cucumber
7
7
  :models_directory, :fixtures_directory, :database_file
8
8
  attr_accessor :adapter, :database, :username,
9
9
  :password, :host
10
-
10
+
11
11
  def initialize
12
12
  pwd = Dir.pwd
13
13
  @temporary_directory = "#{pwd}/tmp"
@@ -15,55 +15,55 @@ module Cucumber
15
15
  @models_directory = "#{pwd}/features/thinking_sphinx/models"
16
16
  @fixtures_directory = "#{pwd}/features/thinking_sphinx/db/fixtures"
17
17
  @database_file = "#{pwd}/features/thinking_sphinx/database.yml"
18
-
19
- @adapter = ENV['DATABASE'] || 'mysql'
18
+
19
+ @adapter = (ENV['DATABASE'] || 'mysql').gsub /^mysql$/, 'mysql2'
20
20
  @database = 'thinking_sphinx'
21
- @username = 'thinking_sphinx'
21
+ @username = @adapter[/mysql/] ? 'root' : 'postgres'
22
22
  # @password = 'thinking_sphinx'
23
23
  @host = 'localhost'
24
24
  end
25
-
25
+
26
26
  def setup
27
27
  make_temporary_directory
28
-
28
+
29
29
  configure_cleanup
30
30
  configure_thinking_sphinx
31
31
  configure_active_record
32
-
32
+
33
33
  prepare_data
34
34
  setup_sphinx
35
-
35
+
36
36
  self
37
37
  end
38
-
38
+
39
39
  def configure_database
40
40
  ActiveRecord::Base.establish_connection database_settings
41
41
  self
42
42
  end
43
-
43
+
44
44
  private
45
-
45
+
46
46
  def config
47
47
  @config ||= ::ThinkingSphinx::Configuration.instance
48
48
  end
49
-
49
+
50
50
  def make_temporary_directory
51
51
  FileUtils.mkdir_p temporary_directory
52
52
  Dir["#{temporary_directory}/*"].each do |file|
53
53
  FileUtils.rm_rf file
54
54
  end
55
55
  end
56
-
56
+
57
57
  def configure_thinking_sphinx
58
58
  config.config_file = "#{temporary_directory}/sphinx.conf"
59
59
  config.searchd_log_file = "#{temporary_directory}/searchd.log"
60
60
  config.query_log_file = "#{temporary_directory}/searchd.query.log"
61
61
  config.pid_file = "#{temporary_directory}/searchd.pid"
62
62
  config.searchd_file_path = "#{temporary_directory}/indexes/"
63
-
63
+
64
64
  ::ThinkingSphinx.suppress_delta_output = true
65
65
  end
66
-
66
+
67
67
  def configure_cleanup
68
68
  Kernel.at_exit do
69
69
  ::ThinkingSphinx::Configuration.instance.controller.stop
@@ -71,13 +71,13 @@ module Cucumber
71
71
  ActiveRecord::Base.logger.close
72
72
  end
73
73
  end
74
-
74
+
75
75
  def yaml_database_settings
76
76
  return {} unless File.exist?(@database_file)
77
-
77
+
78
78
  YAML.load open(@database_file)
79
79
  end
80
-
80
+
81
81
  def database_settings
82
82
  {
83
83
  'adapter' => @adapter,
@@ -87,37 +87,37 @@ module Cucumber
87
87
  'host' => @host
88
88
  }.merge yaml_database_settings
89
89
  end
90
-
90
+
91
91
  def configure_active_record
92
92
  ActiveRecord::Base.logger = Logger.new(
93
93
  open("#{temporary_directory}/active_record.log", "a")
94
94
  )
95
-
95
+
96
96
  ActiveRecord::Base.connection.class.send(
97
97
  :include, Cucumber::ThinkingSphinx::SqlLogger
98
98
  )
99
99
  end
100
-
100
+
101
101
  def prepare_data
102
102
  ::ThinkingSphinx.deltas_enabled = false
103
-
103
+
104
104
  load_files migrations_directory
105
105
  load_files models_directory
106
106
  load_files fixtures_directory
107
-
107
+
108
108
  ::ThinkingSphinx.deltas_enabled = true
109
109
  end
110
-
110
+
111
111
  def load_files(path)
112
112
  files = Dir["#{path}/*.rb"].sort!
113
113
  files.each do |file|
114
114
  require file.gsub(/\.rb$/, '')
115
115
  end
116
116
  end
117
-
117
+
118
118
  def setup_sphinx
119
119
  FileUtils.mkdir_p config.searchd_file_path
120
-
120
+
121
121
  config.build
122
122
  config.controller.index
123
123
  config.controller.start
@@ -38,7 +38,7 @@ Merb::Plugins.add_rakefiles(
38
38
 
39
39
  module ThinkingSphinx
40
40
  mattr_accessor :database_adapter
41
-
41
+
42
42
  # A ConnectionError will get thrown when a connection to Sphinx can't be
43
43
  # made.
44
44
  class ConnectionError < StandardError
@@ -52,7 +52,7 @@ module ThinkingSphinx
52
52
  self.ids = ids
53
53
  end
54
54
  end
55
-
55
+
56
56
  # A SphinxError occurs when Sphinx responds with an error due to problematic
57
57
  # queries or indexes.
58
58
  class SphinxError < RuntimeError
@@ -62,17 +62,7 @@ module ThinkingSphinx
62
62
  self.results = results
63
63
  end
64
64
  end
65
-
66
- # The current version of Thinking Sphinx.
67
- #
68
- # @return [String] The version number as a string
69
- #
70
- def self.version
71
- open(File.join(File.dirname(__FILE__), '../VERSION')) { |f|
72
- f.read.strip
73
- }
74
- end
75
-
65
+
76
66
  # The collection of indexed models. Keep in mind that Rails lazily loads
77
67
  # its classes, so this may not actually be populated with _all_ the models
78
68
  # that have Sphinx indexes.
@@ -84,11 +74,11 @@ module ThinkingSphinx
84
74
  @@suppress_delta_output = false
85
75
  @@remote_sphinx = false
86
76
  @@use_group_by_shortcut = nil
87
-
77
+
88
78
  def self.mutex
89
79
  @@sphinx_mutex
90
80
  end
91
-
81
+
92
82
  def self.context
93
83
  if @@context.nil?
94
84
  mutex.synchronize do
@@ -98,10 +88,10 @@ module ThinkingSphinx
98
88
  end
99
89
  end
100
90
  end
101
-
91
+
102
92
  @@context
103
93
  end
104
-
94
+
105
95
  def self.reset_context!(context = nil)
106
96
  mutex.synchronize do
107
97
  @@context = context
@@ -127,7 +117,7 @@ module ThinkingSphinx
127
117
  @@define_indexes = value
128
118
  end
129
119
  end
130
-
120
+
131
121
  # Check if delta indexing is enabled/disabled.
132
122
  #
133
123
  def self.deltas_enabled?
@@ -140,10 +130,10 @@ module ThinkingSphinx
140
130
  end
141
131
  end
142
132
  end
143
-
133
+
144
134
  @@deltas_enabled && !deltas_suspended?
145
135
  end
146
-
136
+
147
137
  # Enable/disable delta indexing.
148
138
  #
149
139
  # ThinkingSphinx.deltas_enabled = false
@@ -160,7 +150,7 @@ module ThinkingSphinx
160
150
  if Thread.current[:thinking_sphinx_deltas_suspended].nil?
161
151
  Thread.current[:thinking_sphinx_deltas_suspended] = false
162
152
  end
163
-
153
+
164
154
  Thread.current[:thinking_sphinx_deltas_suspended]
165
155
  end
166
156
 
@@ -185,7 +175,7 @@ module ThinkingSphinx
185
175
  end
186
176
  end
187
177
  end
188
-
178
+
189
179
  @@updates_enabled
190
180
  end
191
181
 
@@ -208,7 +198,7 @@ module ThinkingSphinx
208
198
  @@suppress_delta_output = value
209
199
  end
210
200
  end
211
-
201
+
212
202
  # Checks to see if MySQL will allow simplistic GROUP BY statements. If not,
213
203
  # or if not using MySQL, this will return false.
214
204
  #
@@ -226,10 +216,10 @@ module ThinkingSphinx
226
216
  end
227
217
  end
228
218
  end
229
-
219
+
230
220
  @@use_group_by_shortcut
231
221
  end
232
-
222
+
233
223
  def self.reset_use_group_by_shortcut
234
224
  mutex.synchronize do
235
225
  @@use_group_by_shortcut = nil
@@ -298,11 +288,12 @@ module ThinkingSphinx
298
288
 
299
289
  def self.mysql?
300
290
  ::ActiveRecord::Base.connection.class.name.demodulize == "MysqlAdapter" ||
291
+ ::ActiveRecord::Base.connection.class.name.demodulize == "Mysql2Adapter" ||
301
292
  ::ActiveRecord::Base.connection.class.name.demodulize == "MysqlplusAdapter" || (
302
293
  jruby? && ::ActiveRecord::Base.connection.config[:adapter] == "jdbcmysql"
303
294
  )
304
295
  end
305
-
296
+
306
297
  extend ThinkingSphinx::SearchMethods::ClassMethods
307
298
  end
308
299