thinking-sphinx 4.1.0 → 4.2.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 +4 -4
- data/.travis.yml +9 -6
- data/Appraisals +7 -1
- data/CHANGELOG.markdown +20 -0
- data/README.textile +7 -7
- data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +3 -1
- data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +3 -1
- data/lib/thinking_sphinx/active_record/database_adapters/mysql_adapter.rb +7 -1
- data/lib/thinking_sphinx/active_record/depolymorph/overridden_reflection.rb +17 -2
- data/lib/thinking_sphinx/active_record/property_query.rb +2 -1
- data/lib/thinking_sphinx/active_record/source_joins.rb +12 -1
- data/lib/thinking_sphinx/middlewares/glazier.rb +12 -1
- data/lib/thinking_sphinx/middlewares/sphinxql.rb +13 -13
- data/lib/thinking_sphinx/railtie.rb +4 -0
- data/lib/thinking_sphinx/scopes.rb +4 -0
- data/lib/thinking_sphinx/search.rb +5 -4
- data/lib/thinking_sphinx/settings.rb +2 -1
- data/spec/acceptance/attribute_access_spec.rb +9 -0
- data/spec/acceptance/remove_deleted_records_spec.rb +12 -0
- data/spec/acceptance/specifying_sql_spec.rb +36 -0
- data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +2 -2
- data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +1 -1
- data/spec/thinking_sphinx/active_record/database_adapters/mysql_adapter_spec.rb +13 -1
- data/spec/thinking_sphinx/active_record/filter_reflection_spec.rb +14 -2
- data/spec/thinking_sphinx/middlewares/glazier_spec.rb +6 -5
- data/spec/thinking_sphinx/scopes_spec.rb +4 -0
- data/thinking-sphinx.gemspec +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02fc0ce9894c728fcc2b8bdb3bcb867a6ef9a40653269cbc213d2a7d25ee94d3
|
4
|
+
data.tar.gz: 230c83de8b1a5cdbdbb2667b5823ffb6707ad8dfdda15c4c1f8b396642ed1c15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f679238131cebcfa2eda04479696065205505e211d583c70c70efe18059d8ddfee29bf6e129070cb82e7b52928dc6f60d88662e6f1e0298e0e5eb6613ff7682e
|
7
|
+
data.tar.gz: 2f09c08fc40e1a0052e06b790c5bbcc48a8ff3e3d700debcf2089e1504b4d04652fa4d23bd27f2354d8bd29bf2cca3aae9dd86b96aeed12e49036b7542ba8d4b
|
data/.travis.yml
CHANGED
@@ -3,7 +3,7 @@ rvm:
|
|
3
3
|
- 2.3.8
|
4
4
|
- 2.4.5
|
5
5
|
- 2.5.3
|
6
|
-
- 2.6.
|
6
|
+
- 2.6.1
|
7
7
|
addons:
|
8
8
|
apt:
|
9
9
|
packages:
|
@@ -13,7 +13,8 @@ addons:
|
|
13
13
|
before_install:
|
14
14
|
- pip install --upgrade --user awscli
|
15
15
|
- gem update --system
|
16
|
-
- gem
|
16
|
+
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
17
|
+
- gem install bundler -v '< 2'
|
17
18
|
before_script:
|
18
19
|
- mysql -e 'create database thinking_sphinx;' > /dev/null
|
19
20
|
- psql -c 'create database thinking_sphinx;' -U postgres >/dev/null
|
@@ -32,10 +33,12 @@ env:
|
|
32
33
|
- DATABASE=mysql2 SPHINX_VERSION=3.0.3 SPHINX_ENGINE=sphinx
|
33
34
|
- DATABASE=postgresql SPHINX_VERSION=3.0.3 SPHINX_ENGINE=sphinx
|
34
35
|
- DATABASE=mysql2 SPHINX_VERSION=3.1.1 SPHINX_ENGINE=sphinx
|
35
|
-
- DATABASE=mysql2 SPHINX_VERSION=2.6.
|
36
|
-
- DATABASE=postgresql SPHINX_VERSION=2.6.
|
37
|
-
- DATABASE=mysql2 SPHINX_VERSION=2.7.
|
38
|
-
- DATABASE=postgresql SPHINX_VERSION=2.7.
|
36
|
+
- DATABASE=mysql2 SPHINX_VERSION=2.6.4 SPHINX_ENGINE=manticore
|
37
|
+
- DATABASE=postgresql SPHINX_VERSION=2.6.4 SPHINX_ENGINE=manticore
|
38
|
+
- DATABASE=mysql2 SPHINX_VERSION=2.7.5 SPHINX_ENGINE=manticore
|
39
|
+
- DATABASE=postgresql SPHINX_VERSION=2.7.5 SPHINX_ENGINE=manticore
|
40
|
+
- DATABASE=mysql2 SPHINX_VERSION=2.8.1 SPHINX_ENGINE=manticore
|
41
|
+
- DATABASE=postgresql SPHINX_VERSION=2.8.1 SPHINX_ENGINE=manticore
|
39
42
|
# - DATABASE=postgresql SPHINX_VERSION=3.1.1 SPHINX_ENGINE=sphinx
|
40
43
|
sudo: false
|
41
44
|
addons:
|
data/Appraisals
CHANGED
@@ -41,4 +41,10 @@ appraise 'rails_5_2' do
|
|
41
41
|
gem 'rails', '~> 5.2.0'
|
42
42
|
gem 'mysql2', '~> 0.5.0', :platform => :ruby
|
43
43
|
gem 'pg', '~> 1.0', :platform => :ruby
|
44
|
-
end if RUBY_PLATFORM != 'java'
|
44
|
+
end if RUBY_PLATFORM != 'java'
|
45
|
+
|
46
|
+
appraise 'rails_6_0' do
|
47
|
+
gem 'rails', '~> 6.0.0.beta1'
|
48
|
+
gem 'mysql2', '~> 0.5.0', :platform => :ruby
|
49
|
+
gem 'pg', '~> 1.0', :platform => :ruby
|
50
|
+
end if RUBY_PLATFORM != 'java' && RUBY_VERSION.to_f >= 2.5
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,26 @@
|
|
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
|
+
## 4.2.0 - 2019-03-09
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* Allow changing the default encoding for MySQL database connections from utf8 to something else via the `mysql_encoding` setting in `config/thinking_sphinx.yml`. In the next significant release, the default will change to utf8mb4 (which is supported in MySQL 5.5.3 and newer).
|
10
|
+
* Added Rails 6.0 and Manticore 2.8 to the test matrix.
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
* Use Arel's SQL literals for generated order clauses, to avoid warnings from Rails 6.
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
|
18
|
+
* Fix usage of alternative primary keys in update and deletion callbacks and attribute access.
|
19
|
+
* Ensure `respond_to?` takes Sphinx scopes into account ([Jonathan del Strother](https://github.com/jdelstrother) in [#1124](https://github.com/pat/thinking-sphinx/pull/1124)).
|
20
|
+
* Add `:excerpts` as a known option for search requests.
|
21
|
+
* Fix depolymorphed association join construction with Rails 6.0.0.beta2.
|
22
|
+
* Reset ThinkingSphinx::Configuration's cached values when Rails reloads, to avoid holding onto stale references to ActiveRecord models ([#1125](https://github.com/pat/thinking-sphinx/issues/1125)).
|
23
|
+
* Don't join against associations in `sql_query` if they're only used by query-sourced properties ([Hans de Graaff](https://github.com/graaff) in [#1127](https://github.com/pat/thinking-sphinx/pull/1127)).
|
24
|
+
|
5
25
|
## 4.1.0 - 2018-12-28
|
6
26
|
|
7
27
|
[Release Notes](https://github.com/pat/thinking-sphinx/releases/tag/v4.1.0)
|
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 v4.
|
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 v4.2.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.3', :platform => :ruby
|
16
16
|
gem 'jdbc-mysql', '~> 5.1.35', :platform => :jruby
|
17
|
-
gem 'thinking-sphinx', '~> 4.
|
17
|
+
gem 'thinking-sphinx', '~> 4.2'</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. If you're using JRuby with a version of Sphinx prior to 2.2.11, there is "currently an issue with Sphinx and jdbc-mysql 5.1.36 or newer":http://sphinxsearch.com/forum/view.html?id=13939, so you'll need to stick to nothing more recent than 5.1.35, or upgrade Sphinx.
|
20
20
|
|
@@ -29,10 +29,10 @@ 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.3 | v2.3.8, v2.4.5, v2.5.3, v2.6.
|
32
|
+
| Ruby | v2.3 | v2.3.8, v2.4.5, v2.5.3, v2.6.1 |
|
33
33
|
| Sphinx | v2.1.2 | v2.1.9, v2.2.11, v3.0.3, v3.1.1 |
|
34
|
-
| Manticore | v2.6.3 | v2.6.
|
35
|
-
| ActiveRecord | v3.2 | v3.2
|
34
|
+
| Manticore | v2.6.3 | v2.6.4, v2.7.5, v2.8.1 |
|
35
|
+
| ActiveRecord | v3.2 | v3.2..v6.0 |
|
36
36
|
|
37
37
|
It _might_ work with older versions of Ruby, but it's highly recommended to update to a supported release.
|
38
38
|
|
@@ -52,7 +52,7 @@ If you want ActiveRecord 3.1 support, then refer to the 3.0.x releases of Thinki
|
|
52
52
|
|
53
53
|
h3. Ruby
|
54
54
|
|
55
|
-
You'll need either the standard Ruby (v2.
|
55
|
+
You'll need either the standard Ruby (v2.3 or newer) or JRuby (9.1 or newer).
|
56
56
|
|
57
57
|
h3. Database Versions
|
58
58
|
|
@@ -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-
|
84
|
+
Copyright (c) 2007-2019, 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.
|
@@ -19,7 +19,9 @@ class ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks <
|
|
19
19
|
return if ThinkingSphinx::Callbacks.suspended? || instance.new_record?
|
20
20
|
|
21
21
|
indices.each { |index|
|
22
|
-
ThinkingSphinx::Deletion.perform
|
22
|
+
ThinkingSphinx::Deletion.perform(
|
23
|
+
index, instance.public_send(index.primary_key)
|
24
|
+
)
|
23
25
|
}
|
24
26
|
end
|
25
27
|
|
@@ -55,7 +55,9 @@ class ThinkingSphinx::ActiveRecord::Callbacks::UpdateCallbacks <
|
|
55
55
|
return if attributes.empty?
|
56
56
|
|
57
57
|
sphinxql = Riddle::Query.update(
|
58
|
-
index.name,
|
58
|
+
index.name,
|
59
|
+
index.document_id_for_key(instance.public_send(index.primary_key)),
|
60
|
+
attributes
|
59
61
|
)
|
60
62
|
ThinkingSphinx::Connection.take do |connection|
|
61
63
|
connection.execute(sphinxql)
|
@@ -40,6 +40,12 @@ class ThinkingSphinx::ActiveRecord::DatabaseAdapters::MySQLAdapter <
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def utf8_query_pre
|
43
|
-
[
|
43
|
+
["SET NAMES #{settings['mysql_encoding']}"]
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def settings
|
49
|
+
ThinkingSphinx::Configuration.instance.settings
|
44
50
|
end
|
45
51
|
end
|
@@ -5,7 +5,7 @@
|
|
5
5
|
class ThinkingSphinx::ActiveRecord::Depolymorph::OverriddenReflection <
|
6
6
|
ThinkingSphinx::ActiveRecord::Depolymorph::BaseReflection
|
7
7
|
|
8
|
-
module
|
8
|
+
module BuildJoinConstraint
|
9
9
|
def build_join_constraint(table, foreign_table)
|
10
10
|
super.and(
|
11
11
|
foreign_table[options[:foreign_type]].eq(
|
@@ -15,6 +15,16 @@ class ThinkingSphinx::ActiveRecord::Depolymorph::OverriddenReflection <
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
module JoinScope
|
19
|
+
def join_scope(table, foreign_table, foreign_klass)
|
20
|
+
super.where(
|
21
|
+
foreign_table[options[:foreign_type]].eq(
|
22
|
+
options[:class_name].constantize.base_class.name
|
23
|
+
)
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
18
28
|
def self.overridden_classes
|
19
29
|
@overridden_classes ||= {}
|
20
30
|
end
|
@@ -28,8 +38,13 @@ class ThinkingSphinx::ActiveRecord::Depolymorph::OverriddenReflection <
|
|
28
38
|
def klass
|
29
39
|
self.class.overridden_classes[reflection.class] ||= begin
|
30
40
|
subclass = Class.new reflection.class
|
31
|
-
subclass.include
|
41
|
+
subclass.include extension(reflection)
|
32
42
|
subclass
|
33
43
|
end
|
34
44
|
end
|
45
|
+
|
46
|
+
def extension(reflection)
|
47
|
+
reflection.respond_to?(:build_join_constraint) ?
|
48
|
+
BuildJoinConstraint : JoinScope
|
49
|
+
end
|
35
50
|
end
|
@@ -27,6 +27,7 @@ primary key.
|
|
27
27
|
attr_reader :property, :source, :type
|
28
28
|
|
29
29
|
delegate :unscoped, :to => :base_association_class, :prefix => true
|
30
|
+
delegate :sql, :to => Arel
|
30
31
|
|
31
32
|
def base_association
|
32
33
|
reflections.first
|
@@ -135,7 +136,7 @@ primary key.
|
|
135
136
|
relation = relation.joins(joins) if joins.present?
|
136
137
|
relation = relation.where("#{quoted_foreign_key} BETWEEN $start AND $end") if ranged?
|
137
138
|
relation = relation.where("#{quoted_foreign_key} IS NOT NULL")
|
138
|
-
relation = relation.order("#{quoted_foreign_key} ASC") if type.nil?
|
139
|
+
relation = relation.order(sql("#{quoted_foreign_key} ASC")) if type.nil?
|
139
140
|
|
140
141
|
relation.to_sql
|
141
142
|
end
|
@@ -27,7 +27,7 @@ class ThinkingSphinx::ActiveRecord::SourceJoins
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def append_column_associations(column)
|
30
|
-
return if column.__stack.empty?
|
30
|
+
return if column.__stack.empty? or column_included_in_queries?(column)
|
31
31
|
|
32
32
|
joins.add_join_to column.__stack if column_exists?(column)
|
33
33
|
end
|
@@ -54,4 +54,15 @@ class ThinkingSphinx::ActiveRecord::SourceJoins
|
|
54
54
|
joins
|
55
55
|
end
|
56
56
|
end
|
57
|
+
|
58
|
+
def source_query_properties
|
59
|
+
source.properties.select { |field| field.source_type == :query }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Use "first" here instead of a more intuitive flatten because flatten
|
63
|
+
# will also ask each column to become an Array and that will start
|
64
|
+
# to retrieve data.
|
65
|
+
def column_included_in_queries?(column)
|
66
|
+
source_query_properties.collect(&:columns).collect(&:first).include?(column)
|
67
|
+
end
|
57
68
|
end
|
@@ -16,6 +16,7 @@ class ThinkingSphinx::Middlewares::Glazier <
|
|
16
16
|
class Inner
|
17
17
|
def initialize(context)
|
18
18
|
@context = context
|
19
|
+
@indices = {}
|
19
20
|
end
|
20
21
|
|
21
22
|
def call
|
@@ -31,10 +32,20 @@ class ThinkingSphinx::Middlewares::Glazier <
|
|
31
32
|
|
32
33
|
attr_reader :context
|
33
34
|
|
35
|
+
def indices_for(model)
|
36
|
+
@indices[model] ||= context[:indices].select do |index|
|
37
|
+
index.model == model
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
34
41
|
def row_for(result)
|
42
|
+
ids = indices_for(result.class).collect do |index|
|
43
|
+
result.send index.primary_key
|
44
|
+
end
|
45
|
+
|
35
46
|
context[:raw].detect { |row|
|
36
47
|
row['sphinx_internal_class'] == result.class.name &&
|
37
|
-
row['sphinx_internal_id']
|
48
|
+
ids.include?(row['sphinx_internal_id'])
|
38
49
|
}
|
39
50
|
end
|
40
51
|
end
|
@@ -82,19 +82,6 @@ class ThinkingSphinx::Middlewares::SphinxQL <
|
|
82
82
|
end.flatten
|
83
83
|
end
|
84
84
|
|
85
|
-
def indices_match_classes?
|
86
|
-
indices.collect(&:reference).uniq.sort == classes.collect { |klass|
|
87
|
-
ThinkingSphinx::IndexSet.reference_name(klass)
|
88
|
-
}.sort
|
89
|
-
end
|
90
|
-
|
91
|
-
def inheritance_column_select(klass)
|
92
|
-
<<-SQL
|
93
|
-
SELECT DISTINCT #{klass.inheritance_column}
|
94
|
-
FROM #{klass.table_name}
|
95
|
-
SQL
|
96
|
-
end
|
97
|
-
|
98
85
|
def exclusive_filters
|
99
86
|
@exclusive_filters ||= (options[:without] || {}).tap do |without|
|
100
87
|
without[:sphinx_internal_id] = options[:without_ids] if options[:without_ids].present?
|
@@ -144,6 +131,19 @@ SQL
|
|
144
131
|
end
|
145
132
|
end
|
146
133
|
|
134
|
+
def indices_match_classes?
|
135
|
+
indices.collect(&:reference).uniq.sort == classes.collect { |klass|
|
136
|
+
ThinkingSphinx::IndexSet.reference_name(klass)
|
137
|
+
}.sort
|
138
|
+
end
|
139
|
+
|
140
|
+
def inheritance_column_select(klass)
|
141
|
+
<<-SQL
|
142
|
+
SELECT DISTINCT #{klass.inheritance_column}
|
143
|
+
FROM #{klass.table_name}
|
144
|
+
SQL
|
145
|
+
end
|
146
|
+
|
147
147
|
def order_clause
|
148
148
|
order_by = options[:order]
|
149
149
|
order_by = "#{order_by} ASC" if order_by.is_a? Symbol
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ThinkingSphinx::Railtie < Rails::Railtie
|
4
|
+
config.to_prepare do
|
5
|
+
ThinkingSphinx::Configuration.reset
|
6
|
+
end
|
7
|
+
|
4
8
|
initializer 'thinking_sphinx.initialisation' do
|
5
9
|
ActiveSupport.on_load(:active_record) do
|
6
10
|
ActiveRecord::Base.send :include, ThinkingSphinx::ActiveRecord::Base
|
@@ -10,10 +10,11 @@ class ThinkingSphinx::Search < Array
|
|
10
10
|
send class )
|
11
11
|
KNOWN_OPTIONS = (
|
12
12
|
[
|
13
|
-
:classes, :conditions, :geo, :group_by, :ids_only,
|
14
|
-
:indices, :limit, :masks, :max_matches, :middleware,
|
15
|
-
:
|
16
|
-
:skip_sti, :sql, :star, :with, :with_all, :without,
|
13
|
+
:classes, :conditions, :excerpts, :geo, :group_by, :ids_only,
|
14
|
+
:ignore_scopes, :indices, :limit, :masks, :max_matches, :middleware,
|
15
|
+
:offset, :order, :order_group_by, :page, :per_page, :populate,
|
16
|
+
:retry_stale, :select, :skip_sti, :sql, :star, :with, :with_all, :without,
|
17
|
+
:without_ids
|
17
18
|
] +
|
18
19
|
ThinkingSphinx::Middlewares::SphinxQL::SELECT_OPTIONS
|
19
20
|
).uniq
|
@@ -17,7 +17,8 @@ class ThinkingSphinx::Settings
|
|
17
17
|
"log" => "log/ENVIRONMENT.searchd.log",
|
18
18
|
"query_log" => "log/ENVIRONMENT.searchd.query.log",
|
19
19
|
"binlog_path" => "tmp/binlog/ENVIRONMENT",
|
20
|
-
"workers" => "threads"
|
20
|
+
"workers" => "threads",
|
21
|
+
"mysql_encoding" => "utf8"
|
21
22
|
}.freeze
|
22
23
|
|
23
24
|
def self.call(configuration)
|
@@ -23,6 +23,15 @@ describe 'Accessing attributes directly via search results', :live => true do
|
|
23
23
|
expect(search.first.weight).to eq(2500)
|
24
24
|
end
|
25
25
|
|
26
|
+
it "provides direct access to the weight with alternative primary keys" do
|
27
|
+
album = Album.create! :name => 'Sing to the Moon', :artist => 'Laura Mvula'
|
28
|
+
|
29
|
+
search = Album.search 'sing', :select => "*, weight()"
|
30
|
+
search.context[:panes] << ThinkingSphinx::Panes::WeightPane
|
31
|
+
|
32
|
+
expect(search.first.weight).to be >= 1000
|
33
|
+
end
|
34
|
+
|
26
35
|
it "can enumerate with the weight" do
|
27
36
|
gods = Book.create! :title => 'American Gods', :year => 2001
|
28
37
|
index
|
@@ -35,6 +35,18 @@ describe 'Hiding deleted records from search results', :live => true do
|
|
35
35
|
to be_empty
|
36
36
|
end
|
37
37
|
|
38
|
+
it "removes records from real-time index results with alternate ids" do
|
39
|
+
album = Album.create! :name => 'Sing to the Moon', :artist => 'Laura Mvula'
|
40
|
+
|
41
|
+
expect(Album.search('Sing', :indices => ['album_real_core']).to_a).
|
42
|
+
to eq([album])
|
43
|
+
|
44
|
+
album.destroy
|
45
|
+
|
46
|
+
expect(Album.search_for_ids('Sing', :indices => ['album_real_core'])).
|
47
|
+
to be_empty
|
48
|
+
end
|
49
|
+
|
38
50
|
it "does not remove real-time results when callbacks are disabled" do
|
39
51
|
original = ThinkingSphinx::Configuration.instance.
|
40
52
|
settings['real_time_callbacks']
|
@@ -198,6 +198,31 @@ describe 'separate queries for MVAs' do
|
|
198
198
|
expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)$/)
|
199
199
|
end
|
200
200
|
|
201
|
+
it "does not include attributes sourced via separate queries" do
|
202
|
+
index.definition_block = Proc.new {
|
203
|
+
indexes title
|
204
|
+
has taggings.tag_id, :as => :tag_ids, :source => :query
|
205
|
+
}
|
206
|
+
index.render
|
207
|
+
|
208
|
+
# We don't want it in the SELECT, JOIN or GROUP clauses. This should catch
|
209
|
+
# them all.
|
210
|
+
expect(source.sql_query).not_to include('taggings')
|
211
|
+
end
|
212
|
+
|
213
|
+
it "keeps the joins in for separately queried tables if they're used elsewhere" do
|
214
|
+
index.definition_block = Proc.new {
|
215
|
+
indexes taggings.tag.name, :as => :tag_names
|
216
|
+
has taggings.tag.created_at, :as => :tag_dates, :source => :query
|
217
|
+
}
|
218
|
+
index.render
|
219
|
+
|
220
|
+
expect(source.sql_query).to include('taggings')
|
221
|
+
expect(source.sql_query).to include('tags')
|
222
|
+
expect(source.sql_query).to_not match(/.tags.\..created_at./)
|
223
|
+
expect(source.sql_query).to match(/.tags.\..name./)
|
224
|
+
end
|
225
|
+
|
201
226
|
it "generates a SQL query with joins when appropriate for MVAs" do
|
202
227
|
index.definition_block = Proc.new {
|
203
228
|
indexes title
|
@@ -434,6 +459,17 @@ describe 'separate queries for field' do
|
|
434
459
|
expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
|
435
460
|
end
|
436
461
|
|
462
|
+
it "does not include fields sourced via separate queries" do
|
463
|
+
index.definition_block = Proc.new {
|
464
|
+
indexes taggings.tag.name, :as => :tags, :source => :query
|
465
|
+
}
|
466
|
+
index.render
|
467
|
+
|
468
|
+
# We don't want it in the SELECT, JOIN or GROUP clauses. This should catch
|
469
|
+
# them all.
|
470
|
+
expect(source.sql_query).not_to include('tags')
|
471
|
+
end
|
472
|
+
|
437
473
|
it "respects custom SQL snippets as the query value" do
|
438
474
|
index.definition_block = Proc.new {
|
439
475
|
indexes 'My Custom SQL Query', :as => :tags, :source => :query
|
@@ -34,7 +34,7 @@ describe ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks do
|
|
34
34
|
|
35
35
|
describe '#after_destroy' do
|
36
36
|
let(:index_set) { double 'index set', :to_a => [index] }
|
37
|
-
let(:index) { double('index', :name => 'foo_core',
|
37
|
+
let(:index) { double('index', :name => 'foo_core', :primary_key => :id,
|
38
38
|
:document_id_for_key => 14, :type => 'plain', :distributed? => false) }
|
39
39
|
let(:instance) { double('instance', :id => 7, :new_record? => false) }
|
40
40
|
|
@@ -93,7 +93,7 @@ describe ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks do
|
|
93
93
|
|
94
94
|
describe '#after_rollback' do
|
95
95
|
let(:index_set) { double 'index set', :to_a => [index] }
|
96
|
-
let(:index) { double('index', :name => 'foo_core',
|
96
|
+
let(:index) { double('index', :name => 'foo_core', :primary_key => :id,
|
97
97
|
:document_id_for_key => 14, :type => 'plain', :distributed? => false) }
|
98
98
|
let(:instance) { double('instance', :id => 7, :new_record? => false) }
|
99
99
|
|
@@ -23,7 +23,7 @@ describe ThinkingSphinx::ActiveRecord::Callbacks::UpdateCallbacks do
|
|
23
23
|
let(:connection) { double('connection', :execute => '') }
|
24
24
|
let(:index) { double 'index', :name => 'article_core',
|
25
25
|
:sources => [source], :document_id_for_key => 3, :distributed? => false,
|
26
|
-
:type => 'plain'}
|
26
|
+
:type => 'plain', :primary_key => :id}
|
27
27
|
let(:source) { double('source', :attributes => []) }
|
28
28
|
|
29
29
|
before :each do
|
@@ -48,11 +48,23 @@ describe ThinkingSphinx::ActiveRecord::DatabaseAdapters::MySQLAdapter do
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
51
|
describe '#group_concatenate' do
|
53
52
|
it "group concatenates the clause with the given separator" do
|
54
53
|
expect(adapter.group_concatenate('foo', ',')).
|
55
54
|
to eq("GROUP_CONCAT(DISTINCT foo SEPARATOR ',')")
|
56
55
|
end
|
57
56
|
end
|
57
|
+
|
58
|
+
describe '#utf8_query_pre' do
|
59
|
+
it "defaults to using utf8" do
|
60
|
+
expect(adapter.utf8_query_pre).to eq(["SET NAMES utf8"])
|
61
|
+
end
|
62
|
+
|
63
|
+
it "allows custom values" do
|
64
|
+
ThinkingSphinx::Configuration.instance.settings['mysql_encoding'] =
|
65
|
+
'utf8mb4'
|
66
|
+
|
67
|
+
expect(adapter.utf8_query_pre).to eq(["SET NAMES utf8mb4"])
|
68
|
+
end
|
69
|
+
end
|
58
70
|
end
|
@@ -6,7 +6,8 @@ describe ThinkingSphinx::ActiveRecord::FilterReflection do
|
|
6
6
|
describe '.call' do
|
7
7
|
let(:reflection) { double('Reflection', :macro => :has_some,
|
8
8
|
:options => options, :active_record => double, :name => 'baz',
|
9
|
-
:foreign_type => :foo_type, :class => original_klass
|
9
|
+
:foreign_type => :foo_type, :class => original_klass,
|
10
|
+
:build_join_constraint => nil) }
|
10
11
|
let(:options) { {:polymorphic => true} }
|
11
12
|
let(:filtered_reflection) { double 'filtered reflection' }
|
12
13
|
let(:original_klass) { double }
|
@@ -179,13 +180,24 @@ describe ThinkingSphinx::ActiveRecord::FilterReflection do
|
|
179
180
|
end
|
180
181
|
|
181
182
|
it "includes custom behaviour in the subclass" do
|
182
|
-
expect(subclass).to receive(:include).with(ThinkingSphinx::ActiveRecord::Depolymorph::OverriddenReflection::
|
183
|
+
expect(subclass).to receive(:include).with(ThinkingSphinx::ActiveRecord::Depolymorph::OverriddenReflection::BuildJoinConstraint)
|
183
184
|
|
184
185
|
ThinkingSphinx::ActiveRecord::FilterReflection.call(
|
185
186
|
reflection, 'foo_bar', 'Bar'
|
186
187
|
)
|
187
188
|
end if ActiveRecord::VERSION::STRING.to_f > 5.1
|
188
189
|
|
190
|
+
it "includes custom behaviour in the subclass" do
|
191
|
+
allow(reflection).to receive(:respond_to?).with(:build_join_constraint).
|
192
|
+
and_return(false)
|
193
|
+
|
194
|
+
expect(subclass).to receive(:include).with(ThinkingSphinx::ActiveRecord::Depolymorph::OverriddenReflection::JoinScope)
|
195
|
+
|
196
|
+
ThinkingSphinx::ActiveRecord::FilterReflection.call(
|
197
|
+
reflection, 'foo_bar', 'Bar'
|
198
|
+
)
|
199
|
+
end if ActiveRecord::VERSION::STRING.to_f >= 6.0
|
200
|
+
|
189
201
|
it "returns the new reflection" do
|
190
202
|
expect(ThinkingSphinx::ActiveRecord::FilterReflection.call(
|
191
203
|
reflection, 'foo_bar', 'Bar'
|
@@ -12,11 +12,12 @@ describe ThinkingSphinx::Middlewares::Glazier do
|
|
12
12
|
let(:middleware) { ThinkingSphinx::Middlewares::Glazier.new app }
|
13
13
|
let(:context) { {:results => [result], :indices => [index],
|
14
14
|
:meta => {}, :raw => [raw_result], :panes => []} }
|
15
|
-
let(:result) { double
|
16
|
-
|
17
|
-
let(:index) { double
|
18
|
-
|
19
|
-
let(:
|
15
|
+
let(:result) { double 'result', :id => 10, :class => model }
|
16
|
+
let(:model) { double 'model', :name => 'Article' }
|
17
|
+
let(:index) { double 'index', :name => 'foo_core', :model => model,
|
18
|
+
:primary_key => :id }
|
19
|
+
let(:search) { double 'search', :options => {} }
|
20
|
+
let(:glazed_result) { double 'glazed result' }
|
20
21
|
let(:raw_result) {
|
21
22
|
{'sphinx_internal_class' => 'Article', 'sphinx_internal_id' => 10} }
|
22
23
|
|
@@ -18,6 +18,10 @@ describe ThinkingSphinx::Scopes do
|
|
18
18
|
model.sphinx_scopes[:foo] = Proc.new { {:with => {:foo => :bar}} }
|
19
19
|
end
|
20
20
|
|
21
|
+
it "implements respond_to" do
|
22
|
+
expect(model).to respond_to(:foo)
|
23
|
+
end
|
24
|
+
|
21
25
|
it "creates new search" do
|
22
26
|
expect(model.foo.class).to eq(ThinkingSphinx::Search)
|
23
27
|
end
|
data/thinking-sphinx.gemspec
CHANGED
@@ -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 = '4.
|
8
|
+
s.version = '4.2.0'
|
9
9
|
s.platform = Gem::Platform::RUBY
|
10
10
|
s.authors = ["Pat Allan"]
|
11
11
|
s.email = ["pat@freelancing-gods.com"]
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.add_runtime_dependency 'riddle', '~> 2.3'
|
32
32
|
|
33
33
|
s.add_development_dependency 'appraisal', '~> 1.0.2'
|
34
|
-
s.add_development_dependency 'combustion', '~>
|
34
|
+
s.add_development_dependency 'combustion', '~> 1.1'
|
35
35
|
s.add_development_dependency 'database_cleaner', '~> 1.6.0'
|
36
36
|
s.add_development_dependency 'rspec', '~> 3.7.0'
|
37
37
|
s.add_development_dependency 'rspec-retry', '~> 0.5.6'
|
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: 4.
|
4
|
+
version: 4.2.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:
|
11
|
+
date: 2019-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: '1.1'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: '1.1'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: database_cleaner
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -520,7 +520,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
520
520
|
- !ruby/object:Gem::Version
|
521
521
|
version: '0'
|
522
522
|
requirements: []
|
523
|
-
rubygems_version: 3.0.
|
523
|
+
rubygems_version: 3.0.3
|
524
524
|
signing_key:
|
525
525
|
specification_version: 4
|
526
526
|
summary: A smart wrapper over Sphinx for ActiveRecord
|