thinking-sphinx 2.0.5 → 2.0.6

Sign up to get free protection for your applications and to get access to all the features.
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