thinking-sphinx 5.4.0 → 5.5.0

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