thinking-sphinx 2.0.5 → 2.0.6

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.
Files changed (70) hide show
  1. data/README.textile +7 -1
  2. data/features/searching_by_model.feature +24 -30
  3. data/features/step_definitions/common_steps.rb +5 -5
  4. data/features/thinking_sphinx/db/.gitignore +1 -0
  5. data/features/thinking_sphinx/db/fixtures/post_keywords.txt +1 -0
  6. data/spec/fixtures/data.sql +32 -0
  7. data/spec/fixtures/database.yml.default +3 -0
  8. data/spec/fixtures/models.rb +161 -0
  9. data/spec/fixtures/structure.sql +146 -0
  10. data/spec/spec_helper.rb +62 -0
  11. data/spec/sphinx_helper.rb +61 -0
  12. data/spec/support/rails.rb +18 -0
  13. data/spec/thinking_sphinx/active_record/delta_spec.rb +24 -24
  14. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +27 -0
  15. data/spec/thinking_sphinx/active_record/scopes_spec.rb +25 -25
  16. data/spec/thinking_sphinx/active_record_spec.rb +108 -107
  17. data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +38 -38
  18. data/spec/thinking_sphinx/association_spec.rb +69 -35
  19. data/spec/thinking_sphinx/context_spec.rb +61 -64
  20. data/spec/thinking_sphinx/search_spec.rb +7 -0
  21. data/spec/thinking_sphinx_spec.rb +47 -46
  22. metadata +49 -141
  23. data/VERSION +0 -1
  24. data/lib/cucumber/thinking_sphinx/external_world.rb +0 -12
  25. data/lib/cucumber/thinking_sphinx/internal_world.rb +0 -127
  26. data/lib/cucumber/thinking_sphinx/sql_logger.rb +0 -20
  27. data/lib/thinking-sphinx.rb +0 -1
  28. data/lib/thinking_sphinx.rb +0 -301
  29. data/lib/thinking_sphinx/action_controller.rb +0 -31
  30. data/lib/thinking_sphinx/active_record.rb +0 -384
  31. data/lib/thinking_sphinx/active_record/attribute_updates.rb +0 -52
  32. data/lib/thinking_sphinx/active_record/delta.rb +0 -65
  33. data/lib/thinking_sphinx/active_record/has_many_association.rb +0 -36
  34. data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +0 -21
  35. data/lib/thinking_sphinx/active_record/log_subscriber.rb +0 -61
  36. data/lib/thinking_sphinx/active_record/scopes.rb +0 -93
  37. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +0 -87
  38. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +0 -62
  39. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +0 -157
  40. data/lib/thinking_sphinx/association.rb +0 -219
  41. data/lib/thinking_sphinx/attribute.rb +0 -396
  42. data/lib/thinking_sphinx/auto_version.rb +0 -38
  43. data/lib/thinking_sphinx/bundled_search.rb +0 -44
  44. data/lib/thinking_sphinx/class_facet.rb +0 -20
  45. data/lib/thinking_sphinx/configuration.rb +0 -339
  46. data/lib/thinking_sphinx/context.rb +0 -76
  47. data/lib/thinking_sphinx/core/string.rb +0 -15
  48. data/lib/thinking_sphinx/deltas.rb +0 -28
  49. data/lib/thinking_sphinx/deltas/default_delta.rb +0 -62
  50. data/lib/thinking_sphinx/deploy/capistrano.rb +0 -101
  51. data/lib/thinking_sphinx/excerpter.rb +0 -23
  52. data/lib/thinking_sphinx/facet.rb +0 -128
  53. data/lib/thinking_sphinx/facet_search.rb +0 -170
  54. data/lib/thinking_sphinx/field.rb +0 -98
  55. data/lib/thinking_sphinx/index.rb +0 -157
  56. data/lib/thinking_sphinx/index/builder.rb +0 -312
  57. data/lib/thinking_sphinx/index/faux_column.rb +0 -118
  58. data/lib/thinking_sphinx/join.rb +0 -37
  59. data/lib/thinking_sphinx/property.rb +0 -185
  60. data/lib/thinking_sphinx/railtie.rb +0 -46
  61. data/lib/thinking_sphinx/search.rb +0 -972
  62. data/lib/thinking_sphinx/search_methods.rb +0 -439
  63. data/lib/thinking_sphinx/sinatra.rb +0 -7
  64. data/lib/thinking_sphinx/source.rb +0 -194
  65. data/lib/thinking_sphinx/source/internal_properties.rb +0 -51
  66. data/lib/thinking_sphinx/source/sql.rb +0 -157
  67. data/lib/thinking_sphinx/tasks.rb +0 -130
  68. data/lib/thinking_sphinx/test.rb +0 -55
  69. data/tasks/distribution.rb +0 -33
  70. data/tasks/testing.rb +0 -80
@@ -1,51 +0,0 @@
1
- module ThinkingSphinx
2
- class Source
3
- module InternalProperties
4
- def add_internal_attributes_and_facets
5
- add_internal_attribute :sphinx_internal_id, nil,
6
- @model.primary_key_for_sphinx.to_sym
7
- add_internal_attribute :sphinx_deleted, :integer, "0"
8
- add_internal_attribute :class_crc, :integer, crc_column, true
9
-
10
- unless Riddle.loaded_version.to_i < 2
11
- add_internal_attribute :sphinx_internal_class, :string, internal_class_column, true
12
- add_internal_facet :sphinx_internal_class
13
- else
14
- add_internal_facet :class_crc
15
- end
16
- end
17
-
18
- def add_internal_attribute(name, type, contents, facet = false)
19
- return unless attribute_by_alias(name).nil?
20
-
21
- Attribute.new(self,
22
- ThinkingSphinx::Index::FauxColumn.new(contents),
23
- :type => type,
24
- :as => name,
25
- :facet => facet,
26
- :admin => true
27
- )
28
- end
29
-
30
- def add_internal_facet(name)
31
- return unless facet_by_alias(name).nil?
32
-
33
- @model.sphinx_facets << ClassFacet.new(attribute_by_alias(name))
34
- end
35
-
36
- def attribute_by_alias(attr_alias)
37
- @attributes.detect { |attrib| attrib.alias == attr_alias }
38
- end
39
-
40
- def facet_by_alias(name)
41
- @model.sphinx_facets.detect { |facet| facet.name == name }
42
- end
43
-
44
- def subclasses_to_s
45
- "'" + (@model.send(:descendants).collect { |klass|
46
- klass.to_crc32.to_s
47
- } << @model.to_crc32.to_s).join(",") + "'"
48
- end
49
- end
50
- end
51
- end
@@ -1,157 +0,0 @@
1
- module ThinkingSphinx
2
- class Source
3
- module SQL
4
- # Generates the big SQL statement to get the data back for all the fields
5
- # and attributes, using all the relevant association joins. If you want
6
- # the version filtered for delta values, send through :delta => true in
7
- # the options. Won't do much though if the index isn't set up to support a
8
- # delta sibling.
9
- #
10
- # Examples:
11
- #
12
- # source.to_sql
13
- # source.to_sql(:delta => true)
14
- #
15
- def to_sql(options={})
16
- relation = @model.unscoped
17
- pre_select = 'SQL_NO_CACHE ' if adapter.sphinx_identifier == "mysql"
18
- relation = relation.select(
19
- pre_select.to_s + sql_select_clause(options[:offset])
20
- )
21
-
22
- all_associations.each do |assoc|
23
- relation = relation.joins(assoc.arel_join)
24
- end
25
-
26
- relation = relation.where(sql_where_clause(options))
27
- relation = relation.group(sql_group_clause)
28
- relation = relation.order('NULL') if adapter.sphinx_identifier == "mysql"
29
- relation.to_sql
30
- end
31
-
32
- # Simple helper method for the query range SQL - which is a statement that
33
- # returns minimum and maximum id values. These can be filtered by delta -
34
- # so pass in :delta => true to get the delta version of the SQL.
35
- #
36
- def to_sql_query_range(options={})
37
- return nil if @index.options[:disable_range]
38
-
39
- min_statement = adapter.convert_nulls(
40
- "MIN(#{quote_column(@model.primary_key_for_sphinx)})", 1
41
- )
42
- max_statement = adapter.convert_nulls(
43
- "MAX(#{quote_column(@model.primary_key_for_sphinx)})", 1
44
- )
45
-
46
- sql = "SELECT #{min_statement}, #{max_statement} " +
47
- "FROM #{@model.quoted_table_name} "
48
- if self.delta? && !@index.delta_object.clause(@model, options[:delta]).blank?
49
- sql << "WHERE #{@index.delta_object.clause(@model, options[:delta])}"
50
- end
51
-
52
- sql
53
- end
54
-
55
- # Simple helper method for the query info SQL - which is a statement that
56
- # returns the single row for a corresponding id.
57
- #
58
- def to_sql_query_info(offset)
59
- "SELECT * FROM #{@model.quoted_table_name} WHERE " +
60
- "#{quote_column(@model.primary_key_for_sphinx)} = (($id - #{offset}) / #{ThinkingSphinx.context.indexed_models.size})"
61
- end
62
-
63
- def sql_select_clause(offset)
64
- unique_id_expr = ThinkingSphinx.unique_id_expression(adapter, offset)
65
-
66
- (
67
- ["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} #{unique_id_expr} AS #{quote_column(@model.primary_key_for_sphinx)} "] +
68
- @fields.collect { |field| field.to_select_sql } +
69
- @attributes.collect { |attribute| attribute.to_select_sql }
70
- ).compact.join(", ")
71
- end
72
-
73
- def sql_where_clause(options)
74
- logic = []
75
- logic += [
76
- "#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} >= $start",
77
- "#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} <= $end"
78
- ] unless @index.options[:disable_range]
79
-
80
- if self.delta? && !@index.delta_object.clause(@model, options[:delta]).blank?
81
- logic << "#{@index.delta_object.clause(@model, options[:delta])}"
82
- end
83
-
84
- logic += (@conditions || [])
85
- logic.join(' AND ')
86
- end
87
-
88
- def sql_group_clause
89
- internal_groupings = []
90
- if @model.column_names.include?(@model.inheritance_column)
91
- internal_groupings << "#{@model.quoted_table_name}.#{quote_column(@model.inheritance_column)}"
92
- end
93
-
94
- (
95
- ["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)}"] +
96
- @fields.collect { |field| field.to_group_sql }.compact +
97
- @attributes.collect { |attribute| attribute.to_group_sql }.compact +
98
- @groupings + internal_groupings
99
- ).join(", ")
100
- end
101
-
102
- def sql_query_pre_for_core
103
- if self.delta? && !@index.delta_object.reset_query(@model).blank?
104
- [@index.delta_object.reset_query(@model)]
105
- else
106
- []
107
- end
108
- end
109
-
110
- def sql_query_pre_for_delta
111
- [""]
112
- end
113
-
114
- def quote_column(column)
115
- @model.connection.quote_column_name(column)
116
- end
117
-
118
- def crc_column
119
- if @model.table_exists? &&
120
- @model.column_names.include?(@model.inheritance_column)
121
-
122
- types = types_to_crcs
123
- return @model.to_crc32.to_s if types.empty?
124
-
125
- adapter.case(adapter.convert_nulls(
126
- adapter.quote_with_table(@model.inheritance_column)),
127
- types_to_crcs, @model.to_crc32)
128
- else
129
- @model.to_crc32.to_s
130
- end
131
- end
132
-
133
- def internal_class_column
134
- if @model.table_exists? &&
135
- @model.column_names.include?(@model.inheritance_column)
136
- adapter.quote_with_table(@model.inheritance_column)
137
- else
138
- "'#{@model.name}'"
139
- end
140
- end
141
-
142
- def type_values
143
- @model.connection.select_values <<-SQL
144
- SELECT DISTINCT #{@model.inheritance_column}
145
- FROM #{@model.table_name}
146
- SQL
147
- end
148
-
149
- def types_to_crcs
150
- type_values.compact.inject({}) { |hash, type|
151
- hash[type] = type.to_crc32
152
- hash
153
- }
154
- end
155
- end
156
- end
157
- end
@@ -1,130 +0,0 @@
1
- require 'fileutils'
2
- require 'timeout'
3
-
4
- namespace :thinking_sphinx do
5
- task :app_env do
6
- if defined?(Rails)
7
- Rails.application.require_environment!
8
- Rails.configuration.cache_classes = false
9
- elsif defined?(Merb)
10
- Rake::Task[:merb_env].invoke
11
- elsif defined?(Sinatra)
12
- Sinatra::Application.environment = ENV['RACK_ENV']
13
- end
14
- end
15
-
16
- desc "Output the current Thinking Sphinx version"
17
- task :version => :app_env do
18
- puts "Thinking Sphinx v" + ThinkingSphinx.version
19
- end
20
-
21
- desc "Stop if running, then start a Sphinx searchd daemon using Thinking Sphinx's settings"
22
- task :running_start => :app_env do
23
- Rake::Task["thinking_sphinx:stop"].invoke if sphinx_running?
24
- Rake::Task["thinking_sphinx:start"].invoke
25
- end
26
-
27
- desc "Start a Sphinx searchd daemon using Thinking Sphinx's settings"
28
- task :start => :app_env do
29
- config = ThinkingSphinx::Configuration.instance
30
-
31
- FileUtils.mkdir_p config.searchd_file_path
32
- raise RuntimeError, "searchd is already running." if sphinx_running?
33
-
34
- Dir["#{config.searchd_file_path}/*.spl"].each { |file| File.delete(file) }
35
-
36
- config.controller.start
37
-
38
- if sphinx_running?
39
- puts "Started successfully (pid #{sphinx_pid})."
40
- else
41
- puts "Failed to start searchd daemon. Check #{config.searchd_log_file}"
42
- end
43
- end
44
-
45
- desc "Stop Sphinx using Thinking Sphinx's settings"
46
- task :stop => :app_env do
47
- unless sphinx_running?
48
- puts "searchd is not running"
49
- else
50
- config = ThinkingSphinx::Configuration.instance
51
- pid = sphinx_pid
52
- config.controller.stop
53
-
54
- # Ensure searchd is stopped, but don't try too hard
55
- Timeout.timeout(5) do
56
- sleep(1) until config.controller.stop
57
- end
58
-
59
- puts "Stopped search daemon (pid #{pid})."
60
- end
61
- end
62
-
63
- desc "Restart Sphinx"
64
- task :restart => [:app_env, :stop, :start]
65
-
66
- desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
67
- task :configure => :app_env do
68
- config = ThinkingSphinx::Configuration.instance
69
- puts "Generating Configuration to #{config.config_file}"
70
- config.build
71
- end
72
-
73
- desc "Index data for Sphinx using Thinking Sphinx's settings"
74
- task :index => :app_env do
75
- config = ThinkingSphinx::Configuration.instance
76
- unless ENV["INDEX_ONLY"] == "true"
77
- puts "Generating Configuration to #{config.config_file}"
78
- config.build
79
- end
80
-
81
- FileUtils.mkdir_p config.searchd_file_path
82
- config.controller.index :verbose => true
83
- end
84
-
85
- desc "Reindex Sphinx without regenerating the configuration file"
86
- task :reindex => :app_env do
87
- config = ThinkingSphinx::Configuration.instance
88
- FileUtils.mkdir_p config.searchd_file_path
89
- puts config.controller.index
90
- end
91
-
92
- desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
93
- task :rebuild => :app_env do
94
- Rake::Task["thinking_sphinx:stop"].invoke if sphinx_running?
95
- Rake::Task["thinking_sphinx:index"].invoke
96
- Rake::Task["thinking_sphinx:start"].invoke
97
- end
98
- end
99
-
100
- namespace :ts do
101
- desc "Output the current Thinking Sphinx version"
102
- task :version => "thinking_sphinx:version"
103
- desc "Stop if running, then start a Sphinx searchd daemon using Thinking Sphinx's settings"
104
- task :run => "thinking_sphinx:running_start"
105
- desc "Start a Sphinx searchd daemon using Thinking Sphinx's settings"
106
- task :start => "thinking_sphinx:start"
107
- desc "Stop Sphinx using Thinking Sphinx's settings"
108
- task :stop => "thinking_sphinx:stop"
109
- desc "Index data for Sphinx using Thinking Sphinx's settings"
110
- task :in => "thinking_sphinx:index"
111
- task :index => "thinking_sphinx:index"
112
- desc "Reindex Sphinx without regenerating the configuration file"
113
- task :reindex => "thinking_sphinx:reindex"
114
- desc "Restart Sphinx"
115
- task :restart => "thinking_sphinx:restart"
116
- desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
117
- task :conf => "thinking_sphinx:configure"
118
- desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
119
- task :config => "thinking_sphinx:configure"
120
- desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
121
- task :rebuild => "thinking_sphinx:rebuild"
122
- end
123
-
124
- def sphinx_pid
125
- ThinkingSphinx.sphinx_pid
126
- end
127
-
128
- def sphinx_running?
129
- ThinkingSphinx.sphinx_running?
130
- end
@@ -1,55 +0,0 @@
1
- class ThinkingSphinx::Test
2
- def self.init(suppress_delta_output = true)
3
- set_flags suppress_delta_output
4
- create_indexes_folder
5
- end
6
-
7
- def self.start
8
- config.build
9
- config.controller.index
10
- config.controller.start
11
- end
12
-
13
- def self.start_with_autostop
14
- autostop
15
- start
16
- end
17
-
18
- def self.stop
19
- config.controller.stop
20
- sleep(0.5) # Ensure Sphinx has shut down completely
21
- end
22
-
23
- def self.autostop
24
- Kernel.at_exit do
25
- ThinkingSphinx::Test.stop
26
- end
27
- end
28
-
29
- def self.run(&block)
30
- begin
31
- start
32
- yield
33
- ensure
34
- stop
35
- end
36
- end
37
-
38
- def self.config
39
- @config ||= ::ThinkingSphinx::Configuration.instance
40
- end
41
-
42
- def self.index(*indexes)
43
- config.controller.index *indexes
44
- end
45
-
46
- def self.set_flags(suppress_delta_output)
47
- ::ThinkingSphinx.deltas_enabled = true
48
- ::ThinkingSphinx.updates_enabled = true
49
- ::ThinkingSphinx.suppress_delta_output = suppress_delta_output
50
- end
51
-
52
- def self.create_indexes_folder
53
- FileUtils.mkdir_p config.searchd_file_path
54
- end
55
- end
@@ -1,33 +0,0 @@
1
- desc 'Generate documentation'
2
- YARD::Rake::YardocTask.new
3
-
4
- Jeweler::Tasks.new do |gem|
5
- gem.name = "thinking-sphinx"
6
- gem.summary = "ActiveRecord/Rails Sphinx library"
7
- gem.description = "A concise and easy-to-use Ruby library that connects ActiveRecord to the Sphinx search daemon, managing configuration, indexing and searching."
8
- gem.author = "Pat Allan"
9
- gem.email = "pat@freelancing-gods.com"
10
- gem.homepage = "http://ts.freelancing-gods.com"
11
-
12
- # s.rubyforge_project = "thinking-sphinx"
13
- gem.files = FileList[
14
- "rails/*.rb",
15
- "lib/**/*.rb",
16
- "LICENCE",
17
- "README.textile",
18
- "tasks/**/*.rb",
19
- "VERSION"
20
- ]
21
- gem.test_files = FileList[
22
- "features/**/*.rb",
23
- "features/**/*.feature",
24
- "features/**/*.example.yml",
25
- "spec/**/*_spec.rb"
26
- ]
27
-
28
- gem.post_install_message = <<-MESSAGE
29
- If you're upgrading, you should read this:
30
- http://freelancing-god.github.com/ts/en/upgrading.html
31
-
32
- MESSAGE
33
- end
data/tasks/testing.rb DELETED
@@ -1,80 +0,0 @@
1
- require 'rubygems'
2
- require 'rspec/core/rake_task'
3
- require 'cucumber/rake/task'
4
-
5
- desc "Run the specs under spec"
6
- RSpec::Core::RakeTask.new do |t|
7
- t.pattern = 'spec/**/*_spec.rb'
8
- end
9
-
10
- desc "Run all feature-set configurations"
11
- task :features do |t|
12
- databases = ENV['DATABASES'] || 'mysql,postgresql'
13
- databases.split(',').each do |database|
14
- puts "rake features:#{database}"
15
- system "rake features:#{database}"
16
- end
17
- end
18
-
19
- namespace :features do
20
- def add_task(name, description)
21
- Cucumber::Rake::Task.new(name, description) do |t|
22
- t.cucumber_opts = "--format pretty features/*.feature DATABASE=#{name} --exclude features/thinking_sphinx"
23
- end
24
- end
25
-
26
- add_task :mysql, "Run feature-set against MySQL"
27
- add_task :postgresql, "Run feature-set against PostgreSQL"
28
- end
29
-
30
- namespace :rcov do
31
- desc "Generate RCov reports"
32
- RSpec::Core::RakeTask.new(:rspec) do |t|
33
- t.pattern = 'spec/**/*_spec.rb'
34
- t.rcov = true
35
- t.rcov_opts = [
36
- '--exclude', 'spec',
37
- '--exclude', 'gems',
38
- '--exclude', 'riddle',
39
- '--exclude', 'ruby',
40
- '--aggregate coverage.data'
41
- ]
42
- end
43
-
44
- def add_task(name, description)
45
- Cucumber::Rake::Task.new(name, description) do |t|
46
- t.cucumber_opts = "--format pretty features/*.feature DATABASE=#{name}"
47
- t.rcov = true
48
- t.rcov_opts = [
49
- '--exclude', 'spec',
50
- '--exclude', 'gems',
51
- '--exclude', 'riddle',
52
- '--exclude', 'features',
53
- '--aggregate coverage.data'
54
- ]
55
- end
56
- end
57
-
58
- add_task :mysql, "Run feature-set against MySQL with rcov"
59
- add_task :postgresql, "Run feature-set against PostgreSQL with rcov"
60
-
61
- task :all do
62
- rm 'coverage.data' if File.exist?('coverage.data')
63
- rm 'rerun.txt' if File.exist?('rerun.txt')
64
-
65
- Rake::Task['rcov:rspec'].invoke
66
- Rake::Task['rcov:mysql'].invoke
67
- Rake::Task['rcov:postgresql'].invoke
68
- end
69
- end
70
-
71
- desc "Build cucumber.yml file"
72
- task :cucumber_defaults do
73
- steps = FileList["features/step_definitions/**.rb"].collect { |path|
74
- "--require #{path}"
75
- }.join(" ")
76
-
77
- File.open('cucumber.yml', 'w') { |f|
78
- f.write "default: \"--require features/support/env.rb #{steps}\"\n"
79
- }
80
- end