thinking-sphinx 5.4.0 → 5.5.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4829363e45789cd8824b01645737455277dff8ce8d3ab4dd7ea9cd6bd748179b
4
- data.tar.gz: c605d34504bef55fcb03d92d42e86348296689697df8fc0cd0fc2fb36ac7f097
3
+ metadata.gz: 329b223375314de077fdec7d3cd62296d2adfe4a8e55edb8e69277c0b7c87d85
4
+ data.tar.gz: 4cbe73eb983ecc5f381f9acb381ad65df467804165f821d3a9b4214c236c6de6
5
5
  SHA512:
6
- metadata.gz: 2e768c63a2df5057432a0e28ab5fdb335cd28cf47fe3f2ac115e34eb7c10b4abe62721543c36ffe29aeaca013434fb069262b9fda5d752b2396f2df43d0d1c17
7
- data.tar.gz: 5ab46830963db408b4789b5c3a694cd13b6c0cece4be23b23e68e589d4e54561c1c597ffa2b579324fa3e825a335cc611ecde17cc9d4e13f0117f6cd31a6b4fc
6
+ metadata.gz: 1f7d91602bbe643ae99c2c9cfd70c9fb0aa446948eb2dfb19afbf78ed9b879ec2a817e59e7965051147e94fe574c4df398e68256a720f5f0946f0f474e1e671e
7
+ data.tar.gz: 97ab152f9f16acb69a59f0a3935882306923658ef628873b0ec7913bd3a872f8f8a2739c6ed31d1b73907ed746149f23f925e1fdace06b7688a202920ab96dad
data/.circleci/config.yml CHANGED
@@ -16,111 +16,6 @@ workflows:
16
16
  parameters:
17
17
  database: [ 'mysql2', 'postgresql' ]
18
18
  rails: [ '4_2', '5_0', '5_1', '5_2' ]
19
- - test:
20
- name: "Sphinx 3.4"
21
- sphinx_version: 3.4.1
22
- sphinx_engine: sphinx
23
- debian: buster
24
- matrix:
25
- parameters:
26
- database: [ 'mysql2' ]
27
- ruby: [ '2.4.10', '2.5.9', '2.6.9', '2.7.5', '3.0.3' ]
28
- rails: [ '4_2', '5_0', '5_1', '5_2' ]
29
- exclude:
30
- - rails: '4_2'
31
- ruby: '2.5.9'
32
- - rails: '4_2'
33
- ruby: '2.6.9'
34
- - rails: '4_2'
35
- ruby: '2.7.5'
36
- - rails: '4_2'
37
- ruby: '3.0.3'
38
- - rails: '5_0'
39
- ruby: '3.0.3'
40
- - rails: '5_1'
41
- ruby: '3.0.3'
42
- - rails: '5_2'
43
- ruby: '3.0.3'
44
- - rails: '6_0'
45
- ruby: '2.4.10'
46
- - rails: '6_1'
47
- ruby: '2.4.10'
48
- - rails: '7_0'
49
- ruby: '2.4.10'
50
- - rails: '7_0'
51
- ruby: '2.5.9'
52
- - rails: '7_0'
53
- ruby: '2.6.9'
54
- - test:
55
- name: "Manticore 3.5"
56
- sphinx_version: 3.5.4
57
- sphinx_engine: manticore
58
- debian: buster
59
- matrix:
60
- parameters:
61
- database: [ 'mysql2', 'postgresql' ]
62
- ruby: [ '2.4.10', '2.5.9', '2.6.9', '2.7.5', '3.0.3' ]
63
- rails: [ '4_2', '5_0', '5_1', '5_2' ]
64
- exclude:
65
- - rails: '4_2'
66
- ruby: '2.5.9'
67
- - rails: '4_2'
68
- ruby: '2.6.9'
69
- - rails: '4_2'
70
- ruby: '2.7.5'
71
- - rails: '4_2'
72
- ruby: '3.0.3'
73
- - rails: '5_0'
74
- ruby: '3.0.3'
75
- - rails: '5_1'
76
- ruby: '3.0.3'
77
- - rails: '5_2'
78
- ruby: '3.0.3'
79
- - rails: '6_0'
80
- ruby: '2.4.10'
81
- - rails: '6_1'
82
- ruby: '2.4.10'
83
- - rails: '7_0'
84
- ruby: '2.4.10'
85
- - rails: '7_0'
86
- ruby: '2.5.9'
87
- - rails: '7_0'
88
- ruby: '2.6.9'
89
- - test:
90
- name: "Manticore 4.0"
91
- sphinx_version: 4.0.2
92
- sphinx_engine: manticore
93
- debian: buster
94
- matrix:
95
- parameters:
96
- database: [ 'mysql2', 'postgresql' ]
97
- ruby: [ '2.4.10', '2.5.9', '2.6.9', '2.7.5', '3.0.3' ]
98
- rails: [ '4_2', '5_0', '5_1', '5_2' ]
99
- exclude:
100
- - rails: '4_2'
101
- ruby: '2.5.9'
102
- - rails: '4_2'
103
- ruby: '2.6.9'
104
- - rails: '4_2'
105
- ruby: '2.7.5'
106
- - rails: '4_2'
107
- ruby: '3.0.3'
108
- - rails: '5_0'
109
- ruby: '3.0.3'
110
- - rails: '5_1'
111
- ruby: '3.0.3'
112
- - rails: '5_2'
113
- ruby: '3.0.3'
114
- - rails: '6_0'
115
- ruby: '2.4.10'
116
- - rails: '6_1'
117
- ruby: '2.4.10'
118
- - rails: '7_0'
119
- ruby: '2.4.10'
120
- - rails: '7_0'
121
- ruby: '2.5.9'
122
- - rails: '7_0'
123
- ruby: '2.6.9'
124
19
 
125
20
  jobs:
126
21
  test:
@@ -164,13 +59,7 @@ jobs:
164
59
  - run:
165
60
  name: install bundler
166
61
  command: |
167
- if [ "<< parameters.ruby >>" == "2.7.5" ]; then
168
- export BUNDLER_VERSION=2.1.4
169
- elif [ "<< parameters.ruby >>" == "3.0.3" ]; then
170
- export BUNDLER_VERSION=2.1.4
171
- else
172
- export BUNDLER_VERSION=1.17.3
173
- fi
62
+ export BUNDLER_VERSION=1.17.3
174
63
  export BUNDLE_PATH=vendor/bundle
175
64
  gem install bundler:$BUNDLER_VERSION
176
65
 
@@ -188,11 +77,7 @@ jobs:
188
77
  name: update gems
189
78
  environment:
190
79
  BUNDLE_GEMFILE: "./gemfiles/rails_<< parameters.rails >>.gemfile"
191
- command: |
192
- if [[ -f $BUNDLE_GEMFILE ]]
193
- then
194
- bundle update
195
- fi
80
+ command: bundle update
196
81
 
197
82
  - save_cache:
198
83
  paths:
@@ -211,8 +96,4 @@ jobs:
211
96
  SPHINX_VERSION: << parameters.sphinx_version >>
212
97
  SPHINX_ENGINE: << parameters.sphinx_engine >>
213
98
  BUNDLE_GEMFILE: "./gemfiles/rails_<< parameters.rails >>.gemfile"
214
- command: |
215
- if [[ -f $BUNDLE_GEMFILE ]]
216
- then
217
- bundle exec rspec
218
- fi
99
+ command: bundle exec rspec
@@ -0,0 +1,46 @@
1
+ name: "Test"
2
+ description: "Run RSpec in given environment"
3
+ inputs:
4
+ ruby-version:
5
+ description: "Ruby version"
6
+ required: true
7
+ rails-version:
8
+ description: "Rails version"
9
+ required: true
10
+ sphinx-version:
11
+ description: "Sphinx version"
12
+ required: true
13
+ sphinx-engine:
14
+ description: "Sphinx engine"
15
+ required: true
16
+ database:
17
+ description: "Database engine"
18
+ required: true
19
+ runs:
20
+ using: "composite"
21
+ steps:
22
+ - uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ inputs.ruby-version }}
25
+ bundler-cache: true
26
+ - name: Set up Sphinx
27
+ shell: bash
28
+ run: |
29
+ ./bin/loadsphinx ${{ inputs.sphinx-version }} ${{ inputs.sphinx-engine }}
30
+ - name: Set up Appraisal
31
+ shell: bash
32
+ run: "bundle exec appraisal generate"
33
+ - name: Install Appraisal's gems
34
+ shell: bash
35
+ env:
36
+ BUNDLE_GEMFILE: "gemfiles/rails_${{ inputs.rails-version }}.gemfile"
37
+ run: bundle install
38
+ - name: Test
39
+ shell: bash
40
+ env:
41
+ CI: "true"
42
+ DATABASE: ${{ inputs.database }}
43
+ SPHINX_VERSION: ${{ inputs.sphinx-version }}
44
+ SPHINX_ENGINE: ${{ inputs.sphinx-engine }}
45
+ BUNDLE_GEMFILE: "gemfiles/rails_${{ inputs.rails-version }}.gemfile"
46
+ run: "bundle exec rspec"
@@ -0,0 +1,122 @@
1
+ name: test
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ sphinx:
7
+ runs-on: ${{ matrix.os }}
8
+
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ os: [ 'ubuntu-18.04' ]
13
+ ruby: [ '2.7', '3.0', '3.1', '3.2' ]
14
+ rails: [ '5_0', '5_1', '5_2', '6_0', '6_1', '7_0' ]
15
+ database: [ 'mysql2', 'postgresql' ]
16
+ sphinx_version: [ '3.4.1' ]
17
+ sphinx_engine: [ 'sphinx' ]
18
+ exclude:
19
+ - database: 'postgresql'
20
+ sphinx_version: '3.4.1'
21
+ sphinx_engine: 'sphinx'
22
+ - ruby: '3.0'
23
+ rails: '5_0'
24
+ - ruby: '3.0'
25
+ rails: '5_1'
26
+ - ruby: '3.0'
27
+ rails: '5_2'
28
+ - ruby: '3.1'
29
+ rails: '5_0'
30
+ - ruby: '3.1'
31
+ rails: '5_1'
32
+ - ruby: '3.1'
33
+ rails: '5_2'
34
+ - ruby: '3.2'
35
+ rails: '5_0'
36
+ - ruby: '3.2'
37
+ rails: '5_1'
38
+ - ruby: '3.2'
39
+ rails: '5_2'
40
+
41
+ services:
42
+ postgres:
43
+ image: postgres:10
44
+ env:
45
+ POSTGRES_USER: postgres
46
+ POSTGRES_PASSWORD: thinking_sphinx
47
+ POSTGRES_DB: thinking_sphinx
48
+ ports: ['5432:5432']
49
+ # needed because the postgres container does not provide a healthcheck
50
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
51
+
52
+ mysql:
53
+ image: mysql:5.7
54
+ env:
55
+ MYSQL_ROOT_PASSWORD: thinking_sphinx
56
+ MYSQL_DATABASE: thinking_sphinx
57
+ ports: ['3306:3306']
58
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
59
+
60
+ steps:
61
+ - uses: actions/checkout@v2
62
+ - uses: ./.github/actions/test
63
+ with:
64
+ ruby-version: ${{ matrix.ruby }}
65
+ rails-version: ${{ matrix.rails }}
66
+ sphinx-version: ${{ matrix.sphinx_version }}
67
+ sphinx-engine: ${{ matrix.sphinx_engine }}
68
+ database: ${{ matrix.database }}
69
+ timeout-minutes: 12
70
+
71
+ manticore:
72
+ runs-on: ubuntu-20.04
73
+
74
+ strategy:
75
+ fail-fast: false
76
+ matrix:
77
+ ruby: [ '2.5', '2.6', '2.7', '3.0' ]
78
+ rails: [ '5_0', '5_1', '5_2', '6_0', '6_1', '7_0' ]
79
+ database: [ 'mysql2', 'postgresql' ]
80
+ sphinx_version: [ '3.5.4', '4.0.2' ]
81
+ sphinx_engine: [ 'manticore' ]
82
+ exclude:
83
+ - ruby: '2.5'
84
+ rails: '7_0'
85
+ - ruby: '2.6'
86
+ rails: '7_0'
87
+ - ruby: '3.0'
88
+ rails: '5_0'
89
+ - ruby: '3.0'
90
+ rails: '5_1'
91
+ - ruby: '3.0'
92
+ rails: '5_2'
93
+
94
+ services:
95
+ postgres:
96
+ image: postgres:10
97
+ env:
98
+ POSTGRES_USER: postgres
99
+ POSTGRES_PASSWORD: thinking_sphinx
100
+ POSTGRES_DB: thinking_sphinx
101
+ ports: ['5432:5432']
102
+ # needed because the postgres container does not provide a healthcheck
103
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
104
+
105
+ mysql:
106
+ image: mysql:8.0
107
+ env:
108
+ MYSQL_ROOT_PASSWORD: thinking_sphinx
109
+ MYSQL_DATABASE: thinking_sphinx
110
+ ports: ['3306:3306']
111
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
112
+
113
+ steps:
114
+ - uses: actions/checkout@v2
115
+ - uses: ./.github/actions/test
116
+ with:
117
+ ruby-version: ${{ matrix.ruby }}
118
+ rails-version: ${{ matrix.rails }}
119
+ sphinx-version: ${{ matrix.sphinx_version }}
120
+ sphinx-engine: ${{ matrix.sphinx_engine }}
121
+ database: ${{ matrix.database }}
122
+ timeout-minutes: 12
data/.gitignore CHANGED
@@ -1,11 +1,13 @@
1
1
  *.gem
2
+ *.sublime-*
2
3
  .bundle
4
+ .overmind.env
3
5
  .rbx
4
6
  .rspec
5
7
  .tool-versions
8
+ data/*
6
9
  gemfiles
7
10
  Gemfile.lock
8
- *.sublime-*
9
11
  pkg/*
10
12
  spec/internal/config/test.sphinx.conf
11
13
  spec/internal/db/sphinx
data/CHANGELOG.markdown CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to this project (at least, from v3.0.0 onwards) are documented in this file.
4
4
 
5
+ ## 5.5.0 - 2022-12-30
6
+
7
+ [Release Notes](https://github.com/pat/thinking-sphinx/releases/tag/v5.5.0)
8
+
9
+ ### Added
10
+
11
+ * ThinkingSphinx::Processor, a public interface to perform index-related operations on model instances or model name/id combinations. In collaboration with @akostadinov ([#1215](https://github.com/pat/thinking-sphinx/issues/1215)).
12
+
13
+ ### Changed
14
+
15
+ * Confirmed support by testing against Ruby 3.1 and 3.2 by @jdelStrother ([#1237](https://github.com/pat/thinking-sphinx/pull/1237)).
16
+
17
+ ### Fixed
18
+
19
+ * Fix YAML loading, by @aepyornis ([#1217](https://github.com/pat/thinking-sphinx/pull/1217)).
20
+ * Further fixes for File.exist? instead of the deprecated File.exists?, by @funsim ([#1221](https://github.com/pat/thinking-sphinx/pull/1221)) and @graaf ([1233](https://github.com/pat/thinking-sphinx/pull/1233)).
21
+ * Treat unknown column errors as QueryErrors, so retrying the query occurs automatically.
22
+ * Fix MariaDB error handling.
23
+
5
24
  ## 5.4.0 - 2021-12-21
6
25
 
7
26
  [Release Notes](https://github.com/pat/thinking-sphinx/releases/tag/v5.4.0)
data/Gemfile CHANGED
@@ -7,6 +7,8 @@ gemspec
7
7
  gem 'mysql2', '~> 0.5.0', :platform => :ruby
8
8
  gem 'pg', '~> 0.18.4', :platform => :ruby
9
9
 
10
+ gem 'activerecord', '< 7' if RUBY_VERSION.to_f <= 2.4
11
+
10
12
  if RUBY_PLATFORM == 'java'
11
13
  gem 'jdbc-mysql', '5.1.35', :platform => :jruby
12
14
  gem 'activerecord-jdbcmysql-adapter', '>= 1.3.23', :platform => :jruby
data/Procfile.support ADDED
@@ -0,0 +1,2 @@
1
+ postgres: postgres -D data/postgres -p ${POSTGRES_PORT:-5432}
2
+ mysql: $(brew --prefix mysql@5.7)/bin/mysqld --datadir=$(PWD)/data/mysql --port ${MYSQL_PORT:-3306} --socket=mysql.sock
data/README.textile CHANGED
@@ -1,6 +1,6 @@
1
1
  h1. Thinking Sphinx
2
2
 
3
- Thinking Sphinx is a library for connecting ActiveRecord to the Sphinx full-text search tool, and integrates closely with Rails (but also works with other Ruby web frameworks). The current release is v5.4.0.
3
+ Thinking Sphinx is a library for connecting ActiveRecord to the Sphinx full-text search tool, and integrates closely with Rails (but also works with other Ruby web frameworks). The current release is v5.5.0.
4
4
 
5
5
  h2. Upgrading
6
6
 
@@ -14,7 +14,7 @@ It's a gem, so install it like you would any other gem. You will also need to sp
14
14
 
15
15
  <pre><code>gem 'mysql2', '~> 0.4', :platform => :ruby
16
16
  gem 'jdbc-mysql', '~> 5.1.35', :platform => :jruby
17
- gem 'thinking-sphinx', '~> 5.4'</code></pre>
17
+ gem 'thinking-sphinx', '~> 5.5'</code></pre>
18
18
 
19
19
  The MySQL gems mentioned are required for connecting to Sphinx, so please include it even when you're using PostgreSQL for your database.
20
20
 
@@ -29,8 +29,8 @@ h2. Requirements
29
29
  The current release of Thinking Sphinx works with the following versions of its dependencies:
30
30
 
31
31
  |_. Library |_. Minimum |_. Tested Against |
32
- | Ruby | v2.4 | v2.4, v2.5, v2.6, v2.7, v3.0 |
33
- | Sphinx | v2.2.11 | v2.2.11, v3.3.1 |
32
+ | Ruby | v2.4 | v2.4, v2.5, v2.6, v2.7, v3.0, v3.1, v3.2 |
33
+ | Sphinx | v2.2.11 | v2.2.11, v3.4.1 |
34
34
  | Manticore | v2.8 | v3.5, v4.0 |
35
35
  | ActiveRecord | v4.2 | v4.2..v7.0 |
36
36
 
@@ -81,4 +81,4 @@ You can then run the unit tests with @rake spec:unit@, the acceptance tests with
81
81
 
82
82
  h2. Licence
83
83
 
84
- Copyright (c) 2007-2021, Thinking Sphinx is developed and maintained by Pat Allan, and is released under the open MIT Licence. Many thanks to "all who have contributed patches":https://github.com/pat/thinking-sphinx/contributors.
84
+ Copyright (c) 2007-2022, Thinking Sphinx is developed and maintained by Pat Allan, and is released under the open MIT Licence. Many thanks to "all who have contributed patches":https://github.com/pat/thinking-sphinx/contributors.
data/bin/loadsphinx CHANGED
@@ -66,14 +66,15 @@ load_manticore () {
66
66
  3.4.2)
67
67
  url="https://github.com/manticoresoftware/manticoresearch/releases/download/3.4.2/manticore_3.4.2-200410-6903305-release.xenial_amd64-bin.deb";;
68
68
  3.5.4)
69
- url="https://repo.manticoresearch.com/repository/manticoresearch_buster/pool/m/manticore/manticore_3.5.4-201211-13f8d08d_amd64.deb";;
69
+ url="https://repo.manticoresearch.com/repository/manticoresearch_focal/dists/focal/main/binary-amd64/manticore_3.5.4-210107-f70faec5_amd64.deb";;
70
70
  4.0.2)
71
- url="https://repo.manticoresearch.com/repository/manticoresearch_buster/pool/m/manticore/manticore_4.0.2-210921-af497f245_amd64.deb";;
71
+ url="https://repo.manticoresearch.com/repository/manticoresearch_focal/dists/focal/main/binary-amd64/manticore_4.0.2-210921-af497f245_amd64.deb";;
72
72
  *)
73
73
  echo "No Manticore version $version available"
74
74
  exit 1;;
75
75
  esac
76
76
 
77
+ sudo apt-get install default-libmysqlclient-dev
77
78
  curl --location $url -o manticore.deb
78
79
  sudo dpkg -i ./manticore.deb
79
80
  sudo apt-get install -f
@@ -20,18 +20,8 @@ class ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks <
20
20
  private
21
21
 
22
22
  def delete_from_sphinx
23
- return if ThinkingSphinx::Callbacks.suspended? || instance.new_record?
23
+ return if ThinkingSphinx::Callbacks.suspended?
24
24
 
25
- indices.each { |index|
26
- ThinkingSphinx::Deletion.perform(
27
- index, instance.public_send(index.primary_key)
28
- )
29
- }
30
- end
31
-
32
- def indices
33
- ThinkingSphinx::Configuration.instance.index_set_class.new(
34
- :instances => [instance], :classes => [instance.class]
35
- ).to_a
25
+ ThinkingSphinx::Processor.new(instance: instance).delete
36
26
  end
37
27
  end
@@ -7,7 +7,7 @@ class ThinkingSphinx::Commands::ClearRealTime < ThinkingSphinx::Commands::Base
7
7
  Dir["#{index.path}.*"].each { |path| FileUtils.rm path }
8
8
  end
9
9
 
10
- FileUtils.rm_r(binlog_path) if File.exists?(binlog_path)
10
+ FileUtils.rm_r(binlog_path) if File.exist?(binlog_path)
11
11
  end
12
12
 
13
13
  private
@@ -6,8 +6,6 @@ class ThinkingSphinx::Configuration::MinimumFields
6
6
  end
7
7
 
8
8
  def reconcile
9
- return unless no_inheritance_columns?
10
-
11
9
  field_collections.each do |collection|
12
10
  collection.fields.delete_if do |field|
13
11
  field.name == 'sphinx_internal_class_name'
@@ -20,7 +18,7 @@ class ThinkingSphinx::Configuration::MinimumFields
20
18
  attr_reader :indices
21
19
 
22
20
  def field_collections
23
- indices_of_type('plain').collect(&:sources).flatten +
21
+ plain_indices_without_inheritance.collect(&:sources).flatten +
24
22
  indices_of_type('rt')
25
23
  end
26
24
 
@@ -28,10 +26,11 @@ class ThinkingSphinx::Configuration::MinimumFields
28
26
  indices.select { |index| index.type == type }
29
27
  end
30
28
 
31
- def no_inheritance_columns?
32
- indices.select { |index|
33
- index.model.table_exists? &&
34
- index.model.column_names.include?(index.model.inheritance_column)
35
- }.empty?
29
+ def inheritance_columns?(index)
30
+ index.model.table_exists? && index.model.column_names.include?(index.model.inheritance_column)
31
+ end
32
+
33
+ def plain_indices_without_inheritance
34
+ indices_of_type('plain').reject(&method(:inheritance_columns?))
36
35
  end
37
36
  end
@@ -9,11 +9,11 @@ class ThinkingSphinx::SphinxError < StandardError
9
9
  replacement = ThinkingSphinx::ParseError.new(error.message)
10
10
  when /syntax error/
11
11
  replacement = ThinkingSphinx::SyntaxError.new(error.message)
12
- when /query error/
12
+ when /query error/, /unknown column/
13
13
  replacement = ThinkingSphinx::QueryError.new(error.message)
14
- when /Can't connect to MySQL server/,
14
+ when /Can't connect to( MySQL)? server/,
15
15
  /Communications link failure/,
16
- /Lost connection to MySQL server/
16
+ /Lost connection to( MySQL)? server/
17
17
  replacement = ThinkingSphinx::ConnectionError.new(
18
18
  "Error connecting to Sphinx via the MySQL protocol. #{error.message}"
19
19
  )
@@ -12,7 +12,7 @@ class ThinkingSphinx::Guard::File
12
12
  end
13
13
 
14
14
  def locked?
15
- File.exists? path
15
+ File.exist? path
16
16
  end
17
17
 
18
18
  def path
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Processor
4
+ def initialize(instance: nil, model: nil, id: nil)
5
+ raise ArgumentError if instance.nil? && (model.nil? || id.nil?)
6
+
7
+ @instance = instance
8
+ @model = model || instance.class
9
+ @id = id
10
+ end
11
+
12
+ def delete
13
+ return if instance&.new_record?
14
+
15
+ indices.each { |index|
16
+ ThinkingSphinx::Deletion.perform(
17
+ index, id || instance.public_send(index.primary_key)
18
+ )
19
+ }
20
+ end
21
+
22
+ def upsert
23
+ real_time_indices.each do |index|
24
+ ThinkingSphinx::RealTime::Transcriber.new(index).copy loaded_instance
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :instance, :model, :id
31
+
32
+ def indices
33
+ ThinkingSphinx::Configuration.instance.index_set_class.new(
34
+ :instances => [instance].compact, :classes => [model]
35
+ ).to_a
36
+ end
37
+
38
+ def loaded_instance
39
+ @loaded_instance ||= instance || model.find(id)
40
+ end
41
+
42
+ def real_time_indices
43
+ indices.select { |index| index.is_a? ThinkingSphinx::RealTime::Index }
44
+ end
45
+ end
@@ -22,6 +22,9 @@ class ThinkingSphinx::Settings
22
22
  "maximum_statement_length" => (2 ** 23) - 5,
23
23
  "real_time_tidy" => false
24
24
  }.freeze
25
+ YAML_SAFE_LOAD = YAML.method(:safe_load).parameters.any? do |parameter|
26
+ parameter == [:key, :aliases]
27
+ end
25
28
 
26
29
  def self.call(configuration)
27
30
  new(configuration).call
@@ -32,7 +35,7 @@ class ThinkingSphinx::Settings
32
35
  end
33
36
 
34
37
  def call
35
- return defaults unless File.exists? file
38
+ return defaults unless File.exist? file
36
39
 
37
40
  merged.inject({}) do |hash, (key, value)|
38
41
  if absolute_key?(key)
@@ -97,11 +100,7 @@ class ThinkingSphinx::Settings
97
100
  end
98
101
 
99
102
  def original
100
- input = File.read file
101
- input = ERB.new(input).result if defined?(ERB)
102
-
103
- contents = YAML.load input
104
- contents && contents[framework.environment] || {}
103
+ yaml_contents && yaml_contents[framework.environment] || {}
105
104
  end
106
105
 
107
106
  def real_path(base, nonexistent = nil)
@@ -112,4 +111,17 @@ class ThinkingSphinx::Settings
112
111
  real_path components.first, join(components.last, nonexistent)
113
112
  end
114
113
  end
114
+
115
+ def yaml_contents
116
+ @yaml_contents ||= begin
117
+ input = File.read file
118
+ input = ERB.new(input).result if defined?(ERB)
119
+
120
+ if YAML_SAFE_LOAD
121
+ YAML.safe_load(input, aliases: true)
122
+ else
123
+ YAML.load(input)
124
+ end
125
+ end
126
+ end
115
127
  end
@@ -86,6 +86,7 @@ require 'thinking_sphinx/interfaces'
86
86
  require 'thinking_sphinx/masks'
87
87
  require 'thinking_sphinx/middlewares'
88
88
  require 'thinking_sphinx/panes'
89
+ require 'thinking_sphinx/processor'
89
90
  require 'thinking_sphinx/query'
90
91
  require 'thinking_sphinx/rake_interface'
91
92
  require 'thinking_sphinx/scopes'
@@ -27,4 +27,29 @@ describe 'Updates to records in real-time indices', :live => true do
27
27
  expect(Admin::Person.search('Death').to_a).to be_empty
28
28
  expect(Admin::Person.search('Mort').to_a).to eq([person])
29
29
  end
30
+
31
+ it "can use a direct interface for processing records" do
32
+ Admin::Person.connection.execute <<~SQL
33
+ INSERT INTO admin_people (name, created_at, updated_at)
34
+ VALUES ('Pat', now(), now());
35
+ SQL
36
+
37
+ expect(Admin::Person.search('Pat').to_a).to be_empty
38
+
39
+ instance = Admin::Person.find_by(:name => 'Pat')
40
+ ThinkingSphinx::Processor.new(instance: instance).upsert
41
+
42
+ expect(Admin::Person.search('Pat').to_a).to eq([instance])
43
+
44
+ Admin::Person.connection.execute <<~SQL
45
+ UPDATE admin_people SET name = 'Patrick' WHERE name = 'Pat';
46
+ SQL
47
+
48
+ expect(Admin::Person.search('Patrick').to_a).to be_empty
49
+
50
+ instance.reload
51
+ ThinkingSphinx::Processor.new(model: Admin::Person, id: instance.id).upsert
52
+
53
+ expect(Admin::Person.search('Patrick').to_a).to eq([instance])
54
+ end
30
55
  end
@@ -72,4 +72,28 @@ describe 'Hiding deleted records from search results', :live => true do
72
72
 
73
73
  expect(Bird.search_for_ids('duck')).to be_empty
74
74
  end
75
+
76
+ it "can use a direct interface for processing records" do
77
+ pancakes = Article.create! :title => 'Pancakes'
78
+ index
79
+ expect(Article.search('pancakes')).not_to be_empty
80
+
81
+ Article.connection.execute "DELETE FROM articles WHERE id = #{pancakes.id}"
82
+ expect(Article.search_for_ids('pancakes')).not_to be_empty
83
+
84
+ ThinkingSphinx::Processor.new(instance: pancakes).delete
85
+ expect(Article.search_for_ids('pancakes')).to be_empty
86
+ end
87
+
88
+ it "can use a direct interface for processing records without an instance" do
89
+ pancakes = Article.create! :title => 'Pancakes'
90
+ index
91
+ expect(Article.search('pancakes')).not_to be_empty
92
+
93
+ Article.connection.execute "DELETE FROM articles WHERE id = #{pancakes.id}"
94
+ expect(Article.search_for_ids('pancakes')).not_to be_empty
95
+
96
+ ThinkingSphinx::Processor.new(model: Article, id: pancakes.id).delete
97
+ expect(Article.search_for_ids('pancakes')).to be_empty
98
+ end
75
99
  end
@@ -1,4 +1,4 @@
1
1
  username: root
2
- password:
2
+ password: thinking_sphinx
3
3
  host: localhost
4
4
  database: thinking_sphinx
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ThinkingSphinx::Index.define :tee, :with => :active_record do
4
- index colour.name
4
+ indexes colour.name
5
5
  has colour_id, :facet => true
6
6
  end
@@ -2,7 +2,13 @@ test:
2
2
  adapter: <%= ENV['DATABASE'] || 'mysql2' %>
3
3
  database: thinking_sphinx
4
4
  username: <%= ENV['DATABASE'] == 'postgresql' ? 'postgres' : 'root' %>
5
- <% if ENV["CI"] %>
5
+ <% if ENV["DATABASE_PASSWORD"] %>
6
+ password: <%= ENV["DATABASE_PASSWORD"] %>
7
+ <% end %>
8
+ <% if ENV["DATABASE_PORT"] %>
9
+ host: 127.0.0.1
10
+ port: <%= ENV["DATABASE_PORT"] %>
11
+ <% elsif ENV["CI"] %>
6
12
  password: thinking_sphinx
7
13
  host: 127.0.0.1
8
14
  port: <%= ENV['DATABASE'] == 'postgresql' ? 5432 : 3306 %>
@@ -2,7 +2,12 @@
2
2
 
3
3
  module SphinxYamlHelpers
4
4
  def write_configuration(hash)
5
- allow(File).to receive_messages :read => {'test' => hash}.to_yaml, :exists? => true
5
+ allow(File).to receive(:read).and_return({'test' => hash}.to_yaml)
6
+ allow(File).to receive(:exist?).and_wrap_original do |original, path|
7
+ next true if path.to_s == File.absolute_path("config/thinking_sphinx.yml", Rails.root.to_s)
8
+
9
+ original.call(path)
10
+ end
6
11
  end
7
12
  end
8
13
 
@@ -19,7 +19,7 @@ RSpec.describe ThinkingSphinx::Commands::ClearRealTime do
19
19
 
20
20
  allow(FileUtils).to receive_messages :rm_r => true,
21
21
  :rm => true
22
- allow(File).to receive_messages :exists? => true
22
+ allow(File).to receive_messages :exist? => true
23
23
  end
24
24
 
25
25
  it 'finds each file for real-time indices' do
@@ -25,7 +25,7 @@ RSpec.describe ThinkingSphinx::Commands::ClearSQL do
25
25
  and_return(['/path/to/indices/ts-foo.tmp'])
26
26
 
27
27
  allow(FileUtils).to receive_messages :rm_r => true, :rm => true
28
- allow(File).to receive_messages :exists? => true
28
+ allow(File).to receive_messages :exist? => true
29
29
  end
30
30
 
31
31
  it 'finds each file for sql-backed indices' do
@@ -38,13 +38,13 @@ RSpec.describe ThinkingSphinx::Configuration::MinimumFields do
38
38
  expect(index_b.fields).to eq([field_b2])
39
39
  end
40
40
 
41
- it 'keeps the class name fields when one index model has a type column' do
41
+ it 'removes the class name fields only for the indices without type column' do
42
42
  allow(model_a).to receive(:column_names).and_return(['id', 'name', 'type'])
43
43
  allow(model_b).to receive(:column_names).and_return(['id', 'name'])
44
44
 
45
45
  subject.reconcile
46
46
 
47
47
  expect(index_a.sources.first.fields).to eq([field_a1, field_a2])
48
- expect(index_b.fields).to eq([field_b1, field_b2])
48
+ expect(index_b.fields).to eq([field_b2])
49
49
  end
50
50
  end
@@ -38,7 +38,12 @@ describe ThinkingSphinx::Configuration do
38
38
  end
39
39
 
40
40
  it 'does not cache settings after reset' do
41
- allow(File).to receive_messages :exists? => true
41
+ allow(File).to receive(:exist?).and_wrap_original do |original, path|
42
+ next true if path.to_s == File.absolute_path("config/thinking_sphinx.yml", Rails.root)
43
+
44
+ original.call(path)
45
+ end
46
+
42
47
  allow(File).to receive_messages :read => {
43
48
  'test' => {'foo' => 'bugs'},
44
49
  'production' => {'foo' => 'bar'}
@@ -165,8 +170,8 @@ describe ThinkingSphinx::Configuration do
165
170
  File.join(config.framework.root, "my/index/files")
166
171
  )
167
172
 
168
- FileUtils.rm local_path
169
- FileUtils.rmdir linked_path
173
+ FileUtils.rm_rf local_path
174
+ FileUtils.rm_rf linked_path
170
175
  end
171
176
  end
172
177
 
@@ -504,7 +509,11 @@ describe ThinkingSphinx::Configuration do
504
509
  describe '#settings' do
505
510
  context 'YAML file exists' do
506
511
  before :each do
507
- allow(File).to receive_messages :exists? => true
512
+ allow(File).to receive(:exist?).and_wrap_original do |original, path|
513
+ next true if path.to_s == File.absolute_path("config/thinking_sphinx.yml", Rails.root)
514
+
515
+ original.call(path)
516
+ end
508
517
  end
509
518
 
510
519
  it "reads from the YAML file" do
@@ -540,7 +549,11 @@ describe ThinkingSphinx::Configuration do
540
549
 
541
550
  context 'YAML file does not exist' do
542
551
  before :each do
543
- allow(File).to receive_messages :exists? => false
552
+ allow(File).to receive(:exist?).and_wrap_original do |original, path|
553
+ next false if path.to_s == File.absolute_path("config/thinking_sphinx.yml", Rails.root)
554
+
555
+ original.call(path)
556
+ end
544
557
  end
545
558
 
546
559
  it "does not read the file" do
@@ -47,6 +47,15 @@ describe ThinkingSphinx::SphinxError do
47
47
  allow(error).to receive_messages :message => "Lost connection to MySQL server"
48
48
  expect(ThinkingSphinx::SphinxError.new_from_mysql(error)).
49
49
  to be_a(ThinkingSphinx::ConnectionError)
50
+
51
+ # MariaDB has removed mention of MySQL in error messages:
52
+ allow(error).to receive_messages :message => "Can't connect to server on '127.0.0.1' (61)"
53
+ expect(ThinkingSphinx::SphinxError.new_from_mysql(error)).
54
+ to be_a(ThinkingSphinx::ConnectionError)
55
+
56
+ allow(error).to receive_messages :message => "Lost connection to server"
57
+ expect(ThinkingSphinx::SphinxError.new_from_mysql(error)).
58
+ to be_a(ThinkingSphinx::ConnectionError)
50
59
  end
51
60
 
52
61
  it 'translates out-of-bounds errors' do
@@ -5,7 +5,7 @@ $:.push File.expand_path('../lib', __FILE__)
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = 'thinking-sphinx'
8
- s.version = '5.4.0'
8
+ s.version = '5.5.0'
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.authors = ["Pat Allan"]
11
11
  s.email = ["pat@freelancing-gods.com"]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thinking-sphinx
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.0
4
+ version: 5.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Allan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-21 00:00:00.000000000 Z
11
+ date: 2022-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -175,12 +175,15 @@ extensions: []
175
175
  extra_rdoc_files: []
176
176
  files:
177
177
  - ".circleci/config.yml"
178
+ - ".github/actions/test/action.yml"
179
+ - ".github/workflows/ci.yml"
178
180
  - ".gitignore"
179
181
  - ".travis.yml"
180
182
  - Appraisals
181
183
  - CHANGELOG.markdown
182
184
  - Gemfile
183
185
  - LICENCE
186
+ - Procfile.support
184
187
  - README.textile
185
188
  - Rakefile
186
189
  - bin/console
@@ -321,6 +324,7 @@ files:
321
324
  - lib/thinking_sphinx/panes/distance_pane.rb
322
325
  - lib/thinking_sphinx/panes/excerpts_pane.rb
323
326
  - lib/thinking_sphinx/panes/weight_pane.rb
327
+ - lib/thinking_sphinx/processor.rb
324
328
  - lib/thinking_sphinx/query.rb
325
329
  - lib/thinking_sphinx/railtie.rb
326
330
  - lib/thinking_sphinx/rake_interface.rb
@@ -526,7 +530,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
526
530
  - !ruby/object:Gem::Version
527
531
  version: '0'
528
532
  requirements: []
529
- rubygems_version: 3.0.3
533
+ rubygems_version: 3.3.26
530
534
  signing_key:
531
535
  specification_version: 4
532
536
  summary: A smart wrapper over Sphinx for ActiveRecord