Skip to content

Commit 494bb10

Browse files
committed
Merge branch 'release/v5.6.0'
2 parents be5e48b + 6bb0866 commit 494bb10

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+357
-149
lines changed

.github/workflows/ci.yml

+6-7
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ on: [push, pull_request]
44

55
jobs:
66
sphinx:
7-
runs-on: ${{ matrix.os }}
7+
runs-on: ubuntu-22.04
88

99
strategy:
1010
fail-fast: false
1111
matrix:
12-
os: [ 'ubuntu-18.04' ]
1312
ruby: [ '2.7', '3.0', '3.1', '3.2' ]
14-
rails: [ '5_0', '5_1', '5_2', '6_0', '6_1', '7_0' ]
13+
rails: [ '5_0', '5_1', '5_2', '6_0', '6_1', '7_0', '7_1' ]
1514
database: [ 'mysql2', 'postgresql' ]
1615
sphinx_version: [ '2.2.11', '3.4.1' ]
1716
sphinx_engine: [ 'sphinx' ]
@@ -58,7 +57,7 @@ jobs:
5857
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
5958

6059
steps:
61-
- uses: actions/checkout@v2
60+
- uses: actions/checkout@v4
6261
- uses: ./.github/actions/test
6362
with:
6463
ruby-version: ${{ matrix.ruby }}
@@ -69,15 +68,15 @@ jobs:
6968
timeout-minutes: 12
7069

7170
manticore:
72-
runs-on: ubuntu-20.04
71+
runs-on: ubuntu-22.04
7372

7473
strategy:
7574
fail-fast: false
7675
matrix:
7776
ruby: [ '2.7', '3.0', '3.1', '3.2' ]
78-
rails: [ '5_0', '5_1', '5_2', '6_0', '6_1', '7_0' ]
77+
rails: [ '5_0', '5_1', '5_2', '6_0', '6_1', '7_0', '7_1' ]
7978
database: [ 'mysql2', 'postgresql' ]
80-
sphinx_version: [ '3.5.4', '4.0.2' ]
79+
sphinx_version: [ '4.0.2', '6.0.0' ]
8180
sphinx_engine: [ 'manticore' ]
8281
exclude:
8382
- ruby: '3.0'

Appraisals

+6
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,9 @@ appraise 'rails_7_0' do
4545
gem 'mysql2', '~> 0.5.0', :platform => :ruby
4646
gem 'pg', '~> 1.0', :platform => :ruby
4747
end if RUBY_PLATFORM != 'java' && RUBY_VERSION.to_f >= 2.7
48+
49+
appraise 'rails_7_1' do
50+
gem 'rails', '~> 7.1.0'
51+
gem 'mysql2', '~> 0.5.0', :platform => :ruby
52+
gem 'pg', '~> 1.0', :platform => :ruby
53+
end if RUBY_PLATFORM != 'java' && RUBY_VERSION.to_f >= 2.7

CHANGELOG.markdown

+19
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22

33
All notable changes to this project (at least, from v3.0.0 onwards) are documented in this file.
44

5+
## 5.6.0 - 2024-07-07
6+
7+
### Added
8+
9+
* Support for Manticore 6.0 ([#1242](https://github.com/pat/thinking-sphinx/pull/1242))
10+
* `sphinx`-prefixed search methods, in case the standard `search` is overridden from something unrelated. ([#1265](https://github.com/pat/thinking-sphinx/pull/1265))
11+
* `none` / `search_none` scopes that can be chained to searches and will return no results.
12+
* Added `ThinkingSphinx::Processor#sync` to synchronise updates/deletions based on a real-time index's scope, by @akostadinov in [@1258](https://github.com/pat/thinking-sphinx/pull/1258).
13+
14+
### Changed
15+
16+
* Improved Rails 7.1 support, by @jdelstrother in [#1252](https://github.com/pat/thinking-sphinx/pull/1252).
17+
18+
### Fixed
19+
20+
* Handle both SQL and RT indices correctly for inheritance column checks, by @akostadinov in [#1249](https://github.com/pat/thinking-sphinx/pull/1249).
21+
* Ensure tests and CI work with recent Manticore versions, by @jdelstrother in [#1263](https://github.com/pat/thinking-sphinx/pull/1263).
22+
* Use `rm -rf` to delete test and temporary directories (instead of `rm -r`).
23+
524
## 5.5.1 - 2022-12-31
625

726
[Release Notes](https://github.com/pat/thinking-sphinx/releases/tag/v5.5.1)

README.textile

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
h1. Thinking Sphinx
22

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.1.
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.6.0.
44

55
h2. Upgrading
66

@@ -31,7 +31,7 @@ The current release of Thinking Sphinx works with the following versions of its
3131
|_. Library |_. Minimum |_. Tested Against |
3232
| Ruby | v2.4 | v2.4, v2.5, v2.6, v2.7, v3.0, v3.1, v3.2 |
3333
| Sphinx | v2.2.11 | v2.2.11, v3.4.1 |
34-
| Manticore | v2.8 | v3.5, v4.0 |
34+
| Manticore | v2.8 | v4.0, v6.0 |
3535
| ActiveRecord | v4.2 | v4.2..v7.0 |
3636

3737
It _might_ work with older versions of Ruby, but it's highly recommended to update to a supported release.
@@ -42,7 +42,7 @@ h3. Sphinx or Manticore
4242

4343
If you're using Sphinx, v2.2.11 is recommended even though it's quite old, as it works well with PostgreSQL databases (but if you're using MySQL - or real-time indices - then v3.3.1 should also be fine).
4444

45-
If you're opting for Manticore instead, v2.8 or newer works, but v3 or newer is recommended as that's what is actively tested against.
45+
If you're opting for Manticore instead, v2.8 or newer works, but v4 or newer is recommended as that's what is actively tested against. The v4.2 and 5.0 releases had bugs with facet searching, but that's been fixed in Manticore v6.0.
4646

4747
h3. Rails and ActiveRecord
4848

@@ -81,4 +81,4 @@ You can then run the unit tests with @rake spec:unit@, the acceptance tests with
8181

8282
h2. Licence
8383

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.
84+
Copyright (c) 2007-2024, 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.

bin/loadsphinx

+15-4
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,26 @@ load_manticore () {
7070
url="https://repo.manticoresearch.com/repository/manticoresearch_focal/dists/focal/main/binary-amd64/manticore_3.5.4-210107-f70faec5_amd64.deb";;
7171
4.0.2)
7272
url="https://repo.manticoresearch.com/repository/manticoresearch_focal/dists/focal/main/binary-amd64/manticore_4.0.2-210921-af497f245_amd64.deb";;
73+
4.2.0)
74+
url="https://repo.manticoresearch.com/repository/manticoresearch_focal/dists/focal/main/binary-amd64/manticore_4.2.0-211223-15e927b28_amd64.deb";;
75+
6.0.0)
76+
url="skipped";;
7377
*)
7478
echo "No Manticore version $version available"
7579
exit 1;;
7680
esac
7781

78-
sudo apt-get install default-libmysqlclient-dev
79-
curl --location $url -o manticore.deb
80-
sudo dpkg -i ./manticore.deb
81-
sudo apt-get install -f
82+
if [ "$version" == "6.0.0" ]; then
83+
curl --location https://repo.manticoresearch.com/manticore-repo.noarch.deb -o repo.deb
84+
sudo dpkg -i repo.deb
85+
sudo apt update
86+
sudo apt install manticore
87+
else
88+
sudo apt-get install default-libmysqlclient-dev
89+
curl --location $url -o manticore.deb
90+
sudo dpkg -i ./manticore.deb
91+
sudo apt-get install -f
92+
fi
8293
}
8394

8495
if [ "$engine" == "sphinx" ]; then

lib/thinking_sphinx.rb

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ def self.search_for_ids(query = '', options = {})
3434
ThinkingSphinx::Search::Merger.new(search).merge! nil, :ids_only => true
3535
end
3636

37+
def self.none
38+
ThinkingSphinx::Search.new nil, :none => true
39+
end
40+
3741
def self.before_index_hooks
3842
@before_index_hooks
3943
end

lib/thinking_sphinx/active_record/base.rb

+23-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ module ThinkingSphinx::ActiveRecord::Base
44
extend ActiveSupport::Concern
55

66
included do
7+
# Avoid method collisions for public Thinking Sphinx methods added to all
8+
# ActiveRecord models. The `sphinx_`-prefixed versions will always exist,
9+
# and the non-prefixed versions will be added if a method of that name
10+
# doesn't already exist.
11+
#
12+
# If a method is overwritten later by something else, that's also fine - the
13+
# prefixed versions will still be there.
14+
class_module = ThinkingSphinx::ActiveRecord::Base::ClassMethods
15+
class_module.public_instance_methods.each do |method_name|
16+
short_method = method_name.to_s.delete_prefix("sphinx_").to_sym
17+
next if methods.include?(short_method)
18+
19+
define_singleton_method(short_method, method(method_name))
20+
end
21+
722
if ActiveRecord::VERSION::STRING.to_i >= 5
823
[
924
::ActiveRecord::Reflection::HasManyReflection,
@@ -25,24 +40,28 @@ def extensions
2540
end
2641

2742
module ClassMethods
28-
def facets(query = nil, options = {})
43+
def sphinx_facets(query = nil, options = {})
2944
merge_search ThinkingSphinx.facets, query, options
3045
end
3146

32-
def search(query = nil, options = {})
47+
def sphinx_search(query = nil, options = {})
3348
merge_search ThinkingSphinx.search, query, options
3449
end
3550

36-
def search_count(query = nil, options = {})
51+
def sphinx_search_count(query = nil, options = {})
3752
search_for_ids(query, options).total_entries
3853
end
3954

40-
def search_for_ids(query = nil, options = {})
55+
def sphinx_search_for_ids(query = nil, options = {})
4156
ThinkingSphinx::Search::Merger.new(
4257
search(query, options)
4358
).merge! nil, :ids_only => true
4459
end
4560

61+
def sphinx_search_none
62+
merge_search ThinkingSphinx.search, nil, none: true
63+
end
64+
4665
private
4766

4867
def default_sphinx_scope?

lib/thinking_sphinx/active_record/filter_reflection.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
class ThinkingSphinx::ActiveRecord::FilterReflection
44
ReflectionGenerator = case ActiveRecord::VERSION::STRING.to_f
5-
when 5.2..7.0
5+
when 5.2..7.1
66
ThinkingSphinx::ActiveRecord::Depolymorph::OverriddenReflection
77
when 4.1..5.1
88
ThinkingSphinx::ActiveRecord::Depolymorph::AssociationReflection

lib/thinking_sphinx/active_record/log_subscriber.rb

+16-4
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,36 @@
22

33
class ThinkingSphinx::ActiveRecord::LogSubscriber < ActiveSupport::LogSubscriber
44
def guard(event)
5-
identifier = color 'Sphinx', GREEN, true
5+
identifier = colored_text "Sphinx"
66
warn " #{identifier} #{event.payload[:guard]}"
77
end
88

99
def message(event)
10-
identifier = color 'Sphinx', GREEN, true
10+
identifier = colored_text "Sphinx"
1111
debug " #{identifier} #{event.payload[:message]}"
1212
end
1313

1414
def query(event)
15-
identifier = color('Sphinx Query (%.1fms)' % event.duration, GREEN, true)
15+
identifier = colored_text("Sphinx Query (%.1fms)" % event.duration)
1616
debug " #{identifier} #{event.payload[:query]}"
1717
end
1818

1919
def caution(event)
20-
identifier = color 'Sphinx', GREEN, true
20+
identifier = colored_text "Sphinx"
2121
warn " #{identifier} #{event.payload[:caution]}"
2222
end
23+
24+
private
25+
26+
if Rails.gem_version >= Gem::Version.new("7.1.0")
27+
def colored_text(text)
28+
color text, GREEN, bold: true
29+
end
30+
else
31+
def colored_text(text)
32+
color text, GREEN, true
33+
end
34+
end
2335
end
2436

2537
ThinkingSphinx::ActiveRecord::LogSubscriber.attach_to :thinking_sphinx

lib/thinking_sphinx/commands/clear_real_time.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def call
77
Dir["#{index.path}.*"].each { |path| FileUtils.rm path }
88
end
99

10-
FileUtils.rm_r(binlog_path) if File.exist?(binlog_path)
10+
FileUtils.rm_rf(binlog_path) if File.exist?(binlog_path)
1111
end
1212

1313
private

lib/thinking_sphinx/commands/clear_sql.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def call
77
Dir["#{index.path}.*"].each { |path| FileUtils.rm path }
88
end
99

10-
FileUtils.rm_r Dir["#{configuration.indices_location}/ts-*.tmp"]
10+
FileUtils.rm_rf Dir["#{configuration.indices_location}/ts-*.tmp"]
1111
end
1212

1313
private

lib/thinking_sphinx/configuration/minimum_fields.rb

+8-8
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ def reconcile
1818
attr_reader :indices
1919

2020
def field_collections
21-
plain_indices_without_inheritance.collect(&:sources).flatten +
22-
indices_of_type('rt')
23-
end
24-
25-
def indices_of_type(type)
26-
indices.select { |index| index.type == type }
21+
indices_without_inheritance_of_type('plain').collect(&:sources).flatten +
22+
indices_without_inheritance_of_type('rt')
2723
end
2824

2925
def inheritance_columns?(index)
3026
index.model.table_exists? && index.model.column_names.include?(index.model.inheritance_column)
3127
end
3228

33-
def plain_indices_without_inheritance
34-
indices_of_type('plain').reject(&method(:inheritance_columns?))
29+
def indices_without_inheritance_of_type(type)
30+
indices_without_inheritance.select { |index| index.type == type }
31+
end
32+
33+
def indices_without_inheritance
34+
indices.reject(&method(:inheritance_columns?))
3535
end
3636
end

lib/thinking_sphinx/masks/scopes_mask.rb

+6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ def search_for_ids(query = nil, options = {})
2626
search query, options.merge(:ids_only => true)
2727
end
2828

29+
def none
30+
ThinkingSphinx::Search::Merger.new(@search).merge! nil, :none => true
31+
end
32+
33+
alias_method :search_none, :none
34+
2935
private
3036

3137
def apply_scope(scope, *args)

lib/thinking_sphinx/processor.rb

+34-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# frozen_string_literal: true
22

33
class ThinkingSphinx::Processor
4+
# @param instance [ActiveRecord::Base] an ActiveRecord object
5+
# @param model [Class] the ActiveRecord model of the instance
6+
# @param id [Integer] the instance indices primary key (might be different from model primary key)
47
def initialize(instance: nil, model: nil, id: nil)
58
raise ArgumentError if instance.nil? && (model.nil? || id.nil?)
69

@@ -12,16 +15,27 @@ def initialize(instance: nil, model: nil, id: nil)
1215
def delete
1316
return if instance&.new_record?
1417

15-
indices.each { |index|
16-
ThinkingSphinx::Deletion.perform(
17-
index, id || instance.public_send(index.primary_key)
18-
)
19-
}
18+
indices.each { |index| perform_deletion(index) }
2019
end
2120

21+
# Will insert instance into all matching indices
2222
def upsert
2323
real_time_indices.each do |index|
24-
ThinkingSphinx::RealTime::Transcriber.new(index).copy loaded_instance
24+
found = loaded_instance(index)
25+
ThinkingSphinx::RealTime::Transcriber.new(index).copy found if found
26+
end
27+
end
28+
29+
# Will upsert or delete instance into all matching indices based on index scope
30+
def sync
31+
real_time_indices.each do |index|
32+
found = find_in(index)
33+
34+
if found
35+
ThinkingSphinx::RealTime::Transcriber.new(index).copy found
36+
else
37+
ThinkingSphinx::Deletion.perform(index, index_id(index))
38+
end
2539
end
2640
end
2741

@@ -35,11 +49,23 @@ def indices
3549
).to_a
3650
end
3751

38-
def loaded_instance
39-
@loaded_instance ||= instance || model.find(id)
52+
def find_in(index)
53+
index.scope.find_by(index.primary_key => index_id(index))
54+
end
55+
56+
def loaded_instance(index)
57+
instance || find_in(index)
4058
end
4159

4260
def real_time_indices
4361
indices.select { |index| index.is_a? ThinkingSphinx::RealTime::Index }
4462
end
63+
64+
def perform_deletion(index)
65+
ThinkingSphinx::Deletion.perform(index, index_id(index))
66+
end
67+
68+
def index_id(index)
69+
id || instance.public_send(index.primary_key)
70+
end
4571
end

0 commit comments

Comments
 (0)