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