thinking-sphinx 4.3.2 → 5.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/.circleci/config.yml +152 -0
- data/.travis.yml +16 -21
- data/Appraisals +11 -20
- data/CHANGELOG.markdown +79 -0
- data/README.textile +15 -17
- data/bin/loadsphinx +30 -7
- data/lib/thinking_sphinx.rb +5 -4
- data/lib/thinking_sphinx/active_record.rb +1 -0
- data/lib/thinking_sphinx/active_record/association_proxy.rb +1 -2
- data/lib/thinking_sphinx/active_record/association_proxy/attribute_finder.rb +1 -1
- data/lib/thinking_sphinx/active_record/attribute/sphinx_presenter.rb +1 -1
- data/lib/thinking_sphinx/active_record/base.rb +17 -6
- data/lib/thinking_sphinx/active_record/callbacks/association_delta_callbacks.rb +21 -0
- data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +1 -1
- data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +3 -2
- data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +1 -1
- data/lib/thinking_sphinx/active_record/interpreter.rb +4 -4
- data/lib/thinking_sphinx/active_record/sql_source.rb +12 -0
- data/lib/thinking_sphinx/active_record/sql_source/template.rb +2 -2
- data/lib/thinking_sphinx/callbacks.rb +9 -0
- data/lib/thinking_sphinx/callbacks/appender.rb +59 -0
- data/lib/thinking_sphinx/commands/index_real_time.rb +1 -3
- data/lib/thinking_sphinx/connection.rb +4 -0
- data/lib/thinking_sphinx/connection/client.rb +6 -1
- data/lib/thinking_sphinx/core/index.rb +5 -2
- data/lib/thinking_sphinx/deletion.rb +18 -17
- data/lib/thinking_sphinx/errors.rb +1 -1
- data/lib/thinking_sphinx/index_set.rb +7 -3
- data/lib/thinking_sphinx/middlewares/sphinxql.rb +1 -1
- data/lib/thinking_sphinx/railtie.rb +14 -1
- data/lib/thinking_sphinx/real_time.rb +17 -0
- data/lib/thinking_sphinx/real_time/index.rb +5 -3
- data/lib/thinking_sphinx/real_time/index/template.rb +12 -0
- data/lib/thinking_sphinx/real_time/interpreter.rb +8 -6
- data/lib/thinking_sphinx/real_time/populator.rb +5 -2
- data/lib/thinking_sphinx/real_time/processor.rb +36 -0
- data/lib/thinking_sphinx/real_time/transcriber.rb +41 -19
- data/lib/thinking_sphinx/real_time/translator.rb +1 -0
- data/lib/thinking_sphinx/settings.rb +13 -9
- data/lib/thinking_sphinx/subscribers/populator_subscriber.rb +0 -4
- data/spec/acceptance/big_integers_spec.rb +1 -1
- data/spec/acceptance/geosearching_spec.rb +13 -3
- data/spec/acceptance/merging_spec.rb +1 -1
- data/spec/acceptance/real_time_updates_spec.rb +2 -2
- data/spec/acceptance/sql_deltas_spec.rb +15 -3
- data/spec/acceptance/support/sphinx_helpers.rb +4 -4
- data/spec/acceptance/suspended_deltas_spec.rb +3 -3
- data/spec/internal/app/indices/article_index.rb +0 -1
- data/spec/internal/app/indices/colour_index.rb +7 -0
- data/spec/internal/app/models/admin/person.rb +3 -1
- data/spec/internal/app/models/album.rb +3 -1
- data/spec/internal/app/models/animal.rb +1 -0
- data/spec/internal/app/models/article.rb +2 -0
- data/spec/internal/app/models/bird.rb +1 -0
- data/spec/internal/app/models/book.rb +2 -0
- data/spec/internal/app/models/car.rb +1 -1
- data/spec/internal/app/models/city.rb +2 -0
- data/spec/internal/app/models/colour.rb +2 -0
- data/spec/internal/app/models/product.rb +1 -1
- data/spec/internal/app/models/tee.rb +5 -0
- data/spec/internal/app/models/user.rb +2 -0
- data/spec/internal/config/database.yml +6 -1
- data/spec/internal/db/schema.rb +1 -0
- data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +2 -1
- data/spec/thinking_sphinx/active_record/index_spec.rb +0 -12
- data/spec/thinking_sphinx/active_record/interpreter_spec.rb +15 -14
- data/spec/thinking_sphinx/active_record/sql_source_spec.rb +41 -3
- data/spec/thinking_sphinx/connection/mri_spec.rb +49 -0
- data/spec/thinking_sphinx/deletion_spec.rb +5 -4
- data/spec/thinking_sphinx/index_set_spec.rb +28 -12
- data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +2 -1
- data/spec/thinking_sphinx/real_time/index_spec.rb +51 -13
- data/spec/thinking_sphinx/real_time/interpreter_spec.rb +14 -14
- data/spec/thinking_sphinx/real_time/transcriber_spec.rb +9 -1
- data/thinking-sphinx.gemspec +3 -5
- metadata +17 -11
- data/spec/acceptance/connection_spec.rb +0 -25
@@ -133,7 +133,7 @@ class ThinkingSphinx::Middlewares::SphinxQL <
|
|
133
133
|
|
134
134
|
def indices_match_classes?
|
135
135
|
indices.collect(&:reference).uniq.sort == classes.collect { |klass|
|
136
|
-
|
136
|
+
configuration.index_set_class.reference_name(klass)
|
137
137
|
}.sort
|
138
138
|
end
|
139
139
|
|
@@ -7,7 +7,20 @@ class ThinkingSphinx::Railtie < Rails::Railtie
|
|
7
7
|
|
8
8
|
initializer 'thinking_sphinx.initialisation' do
|
9
9
|
ActiveSupport.on_load(:active_record) do
|
10
|
-
|
10
|
+
require 'thinking_sphinx/active_record'
|
11
|
+
ActiveRecord::Base.include ThinkingSphinx::ActiveRecord::Base
|
12
|
+
end
|
13
|
+
|
14
|
+
if ActiveSupport::VERSION::MAJOR > 5
|
15
|
+
if Rails.application.config.autoloader == :zeitwerk
|
16
|
+
ActiveSupport::Dependencies.autoload_paths.delete(
|
17
|
+
Rails.root.join("app", "indices").to_s
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
Rails.application.config.eager_load_paths -=
|
22
|
+
ThinkingSphinx::Configuration.instance.index_paths
|
23
|
+
Rails.application.config.eager_load_paths.freeze
|
11
24
|
end
|
12
25
|
end
|
13
26
|
|
@@ -8,6 +8,22 @@ module ThinkingSphinx::RealTime
|
|
8
8
|
def self.callback_for(reference, path = [], &block)
|
9
9
|
Callbacks::RealTimeCallbacks.new reference.to_sym, path, &block
|
10
10
|
end
|
11
|
+
|
12
|
+
def self.populator
|
13
|
+
@populator ||= ThinkingSphinx::RealTime::Populator
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.populator=(value)
|
17
|
+
@populator = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.processor
|
21
|
+
@processor ||= ThinkingSphinx::RealTime::Processor
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.processor=(value)
|
25
|
+
@processor = value
|
26
|
+
end
|
11
27
|
end
|
12
28
|
|
13
29
|
require 'thinking_sphinx/real_time/property'
|
@@ -16,6 +32,7 @@ require 'thinking_sphinx/real_time/field'
|
|
16
32
|
require 'thinking_sphinx/real_time/index'
|
17
33
|
require 'thinking_sphinx/real_time/interpreter'
|
18
34
|
require 'thinking_sphinx/real_time/populator'
|
35
|
+
require 'thinking_sphinx/real_time/processor'
|
19
36
|
require 'thinking_sphinx/real_time/transcribe_instance'
|
20
37
|
require 'thinking_sphinx/real_time/transcriber'
|
21
38
|
require 'thinking_sphinx/real_time/translator'
|
@@ -16,10 +16,14 @@ class ThinkingSphinx::RealTime::Index < Riddle::Configuration::RealtimeIndex
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def add_attribute(attribute)
|
19
|
+
@attributes.delete_if { |existing| existing.name == attribute.name }
|
20
|
+
|
19
21
|
@attributes << attribute
|
20
22
|
end
|
21
23
|
|
22
24
|
def add_field(field)
|
25
|
+
@fields.delete_if { |existing| existing.name == field.name }
|
26
|
+
|
23
27
|
@fields << field
|
24
28
|
end
|
25
29
|
|
@@ -61,12 +65,10 @@ class ThinkingSphinx::RealTime::Index < Riddle::Configuration::RealtimeIndex
|
|
61
65
|
|
62
66
|
def collection_for(attribute)
|
63
67
|
case attribute.type
|
64
|
-
when :integer, :boolean
|
68
|
+
when :integer, :boolean, :timestamp
|
65
69
|
attribute.multi? ? @rt_attr_multi : @rt_attr_uint
|
66
70
|
when :string
|
67
71
|
@rt_attr_string
|
68
|
-
when :timestamp
|
69
|
-
@rt_attr_timestamp
|
70
72
|
when :float
|
71
73
|
@rt_attr_float
|
72
74
|
when :bigint
|
@@ -13,6 +13,10 @@ class ThinkingSphinx::RealTime::Index::Template
|
|
13
13
|
add_attribute primary_key, :sphinx_internal_id, :bigint
|
14
14
|
add_attribute class_column, :sphinx_internal_class, :string, :facet => true
|
15
15
|
add_attribute 0, :sphinx_deleted, :integer
|
16
|
+
|
17
|
+
if tidying?
|
18
|
+
add_attribute -> (_) { Time.current.to_i }, :sphinx_updated_at, :timestamp
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
private
|
@@ -34,7 +38,15 @@ class ThinkingSphinx::RealTime::Index::Template
|
|
34
38
|
[:class, :name]
|
35
39
|
end
|
36
40
|
|
41
|
+
def config
|
42
|
+
ThinkingSphinx::Configuration.instance
|
43
|
+
end
|
44
|
+
|
37
45
|
def primary_key
|
38
46
|
index.primary_key.to_sym
|
39
47
|
end
|
48
|
+
|
49
|
+
def tidying?
|
50
|
+
config.settings["real_time_tidy"]
|
51
|
+
end
|
40
52
|
end
|
@@ -5,16 +5,18 @@ class ThinkingSphinx::RealTime::Interpreter <
|
|
5
5
|
|
6
6
|
def has(*columns)
|
7
7
|
options = columns.extract_options!
|
8
|
-
|
8
|
+
|
9
|
+
columns.collect { |column|
|
9
10
|
::ThinkingSphinx::RealTime::Attribute.new column, options
|
10
|
-
}
|
11
|
+
}.each { |attribute| @index.add_attribute attribute }
|
11
12
|
end
|
12
13
|
|
13
14
|
def indexes(*columns)
|
14
15
|
options = columns.extract_options!
|
15
|
-
|
16
|
+
|
17
|
+
columns.collect { |column|
|
16
18
|
::ThinkingSphinx::RealTime::Field.new column, options
|
17
|
-
}
|
19
|
+
}.each { |field| @index.add_field field }
|
18
20
|
|
19
21
|
append_sortable_attributes columns, options if options[:sortable]
|
20
22
|
end
|
@@ -39,7 +41,7 @@ class ThinkingSphinx::RealTime::Interpreter <
|
|
39
41
|
def append_sortable_attributes(columns, options)
|
40
42
|
options = options.except(:sortable).merge(:type => :string)
|
41
43
|
|
42
|
-
|
44
|
+
columns.collect { |column|
|
43
45
|
aliased_name = options[:as]
|
44
46
|
aliased_name ||= column.__name.to_sym if column.respond_to?(:__name)
|
45
47
|
aliased_name ||= column
|
@@ -47,6 +49,6 @@ class ThinkingSphinx::RealTime::Interpreter <
|
|
47
49
|
options[:as] = "#{aliased_name}_sort".to_sym
|
48
50
|
|
49
51
|
::ThinkingSphinx::RealTime::Attribute.new column, options
|
50
|
-
}
|
52
|
+
}.each { |attribute| @index.add_attribute attribute }
|
51
53
|
end
|
52
54
|
end
|
@@ -7,9 +7,10 @@ class ThinkingSphinx::RealTime::Populator
|
|
7
7
|
|
8
8
|
def initialize(index)
|
9
9
|
@index = index
|
10
|
+
@started_at = Time.current
|
10
11
|
end
|
11
12
|
|
12
|
-
def populate
|
13
|
+
def populate
|
13
14
|
instrument 'start_populating'
|
14
15
|
|
15
16
|
scope.find_in_batches(:batch_size => batch_size) do |instances|
|
@@ -17,12 +18,14 @@ class ThinkingSphinx::RealTime::Populator
|
|
17
18
|
instrument 'populated', :instances => instances
|
18
19
|
end
|
19
20
|
|
21
|
+
transcriber.clear_before(started_at) if configuration.settings["real_time_tidy"]
|
22
|
+
|
20
23
|
instrument 'finish_populating'
|
21
24
|
end
|
22
25
|
|
23
26
|
private
|
24
27
|
|
25
|
-
attr_reader :index
|
28
|
+
attr_reader :index, :started_at
|
26
29
|
|
27
30
|
delegate :controller, :batch_size, :to => :configuration
|
28
31
|
delegate :scope, :to => :index
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ThinkingSphinx::RealTime::Processor
|
4
|
+
def self.call(indices, &block)
|
5
|
+
new(indices).call(&block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(indices)
|
9
|
+
@indices = indices
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(&block)
|
13
|
+
subscribe_to_progress
|
14
|
+
|
15
|
+
indices.each do |index|
|
16
|
+
ThinkingSphinx::RealTime.populator.populate index
|
17
|
+
|
18
|
+
block.call
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :indices
|
25
|
+
|
26
|
+
def command
|
27
|
+
ThinkingSphinx::Commander.call(
|
28
|
+
command, configuration, options, stream
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def subscribe_to_progress
|
33
|
+
ThinkingSphinx::Subscribers::PopulatorSubscriber.
|
34
|
+
attach_to 'thinking_sphinx.real_time'
|
35
|
+
end
|
36
|
+
end
|
@@ -5,31 +5,20 @@ class ThinkingSphinx::RealTime::Transcriber
|
|
5
5
|
@index = index
|
6
6
|
end
|
7
7
|
|
8
|
+
def clear_before(time)
|
9
|
+
execute <<~SQL.strip
|
10
|
+
DELETE FROM #{@index.name} WHERE sphinx_updated_at < #{time.to_i}
|
11
|
+
SQL
|
12
|
+
end
|
13
|
+
|
8
14
|
def copy(*instances)
|
9
15
|
items = instances.select { |instance|
|
10
16
|
instance.persisted? && copy?(instance)
|
11
17
|
}
|
12
18
|
return unless items.present?
|
13
19
|
|
14
|
-
|
15
|
-
items
|
16
|
-
begin
|
17
|
-
values << ThinkingSphinx::RealTime::TranscribeInstance.call(
|
18
|
-
instance, index, properties
|
19
|
-
)
|
20
|
-
rescue ThinkingSphinx::TranscriptionError => error
|
21
|
-
instrument 'error', :error => error
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
insert = Riddle::Query::Insert.new index.name, columns, values
|
26
|
-
sphinxql = insert.replace!.to_sql
|
27
|
-
|
28
|
-
ThinkingSphinx::Logger.log :query, sphinxql do
|
29
|
-
ThinkingSphinx::Connection.take do |connection|
|
30
|
-
connection.execute sphinxql
|
31
|
-
end
|
32
|
-
end
|
20
|
+
delete_existing items
|
21
|
+
insert_replacements items
|
33
22
|
end
|
34
23
|
|
35
24
|
private
|
@@ -55,6 +44,27 @@ class ThinkingSphinx::RealTime::Transcriber
|
|
55
44
|
}
|
56
45
|
end
|
57
46
|
|
47
|
+
def delete_existing(instances)
|
48
|
+
ids = instances.collect(&index.primary_key.to_sym)
|
49
|
+
|
50
|
+
execute <<~SQL.strip
|
51
|
+
DELETE FROM #{@index.name} WHERE sphinx_internal_id IN (#{ids.join(', ')})
|
52
|
+
SQL
|
53
|
+
end
|
54
|
+
|
55
|
+
def execute(sphinxql)
|
56
|
+
ThinkingSphinx::Logger.log :query, sphinxql do
|
57
|
+
ThinkingSphinx::Connection.take do |connection|
|
58
|
+
connection.execute sphinxql
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def insert_replacements(instances)
|
64
|
+
insert = Riddle::Query::Insert.new index.name, columns, values(instances)
|
65
|
+
execute insert.replace!.to_sql
|
66
|
+
end
|
67
|
+
|
58
68
|
def instrument(message, options = {})
|
59
69
|
ActiveSupport::Notifications.instrument(
|
60
70
|
"#{message}.thinking_sphinx.real_time", options.merge(:index => index)
|
@@ -64,4 +74,16 @@ class ThinkingSphinx::RealTime::Transcriber
|
|
64
74
|
def properties
|
65
75
|
@properties ||= index.fields + index.attributes
|
66
76
|
end
|
77
|
+
|
78
|
+
def values(instances)
|
79
|
+
instances.each_with_object([]) do |instance, array|
|
80
|
+
begin
|
81
|
+
array << ThinkingSphinx::RealTime::TranscribeInstance.call(
|
82
|
+
instance, index, properties
|
83
|
+
)
|
84
|
+
rescue ThinkingSphinx::TranscriptionError => error
|
85
|
+
instrument 'error', :error => error
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
67
89
|
end
|
@@ -11,14 +11,16 @@ class ThinkingSphinx::Settings
|
|
11
11
|
lemmatizer_base mysql_ssl_cert mysql_ssl_key mysql_ssl_ca
|
12
12
|
].freeze
|
13
13
|
DEFAULTS = {
|
14
|
-
"configuration_file"
|
15
|
-
"indices_location"
|
16
|
-
"pid_file"
|
17
|
-
"log"
|
18
|
-
"query_log"
|
19
|
-
"binlog_path"
|
20
|
-
"workers"
|
21
|
-
"mysql_encoding"
|
14
|
+
"configuration_file" => "config/ENVIRONMENT.sphinx.conf",
|
15
|
+
"indices_location" => "db/sphinx/ENVIRONMENT",
|
16
|
+
"pid_file" => "log/ENVIRONMENT.sphinx.pid",
|
17
|
+
"log" => "log/ENVIRONMENT.searchd.log",
|
18
|
+
"query_log" => "log/ENVIRONMENT.searchd.query.log",
|
19
|
+
"binlog_path" => "tmp/binlog/ENVIRONMENT",
|
20
|
+
"workers" => "threads",
|
21
|
+
"mysql_encoding" => "utf8",
|
22
|
+
"maximum_statement_length" => (2 ** 23) - 5,
|
23
|
+
"real_time_tidy" => false
|
22
24
|
}.freeze
|
23
25
|
|
24
26
|
def self.call(configuration)
|
@@ -62,7 +64,9 @@ class ThinkingSphinx::Settings
|
|
62
64
|
|
63
65
|
def defaults
|
64
66
|
DEFAULTS.inject({}) do |hash, (key, value)|
|
65
|
-
|
67
|
+
if value.is_a?(String)
|
68
|
+
value = value.gsub("ENVIRONMENT", framework.environment)
|
69
|
+
end
|
66
70
|
|
67
71
|
if FILE_KEYS.include?(key)
|
68
72
|
hash[key] = absolute value
|
@@ -52,7 +52,7 @@ describe '64 bit document ids', :live => true do
|
|
52
52
|
context 'with Real-Time' do
|
53
53
|
it 'handles large 32 bit integers with an offset multiplier' do
|
54
54
|
product = Product.create! :name => "Widget"
|
55
|
-
product.
|
55
|
+
product.update :id => 980190962
|
56
56
|
expect(
|
57
57
|
Product.search('widget', :indices => ['product_core']).to_a
|
58
58
|
).to eq([product])
|
@@ -38,10 +38,20 @@ describe 'Searching by latitude and longitude', :live => true do
|
|
38
38
|
expected = {:mysql => 250326.906250, :postgresql => 250331.234375}
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
41
|
+
adapter = nil
|
42
|
+
|
43
|
+
if ActiveRecord::VERSION::STRING.to_f > 6.0
|
44
|
+
adapter = ActiveRecord::Base.configurations.configs_for.first.adapter
|
45
|
+
elsif ActiveRecord::VERSION::STRING.to_f > 5.2
|
46
|
+
adapter = ActiveRecord::Base.configurations.configs_for.first.config["adapter"]
|
47
|
+
else
|
48
|
+
adapter = ActiveRecord::Base.configurations['test']['adapter']
|
49
|
+
end
|
50
|
+
|
51
|
+
if adapter[/postgres/]
|
52
|
+
expect(cities.first.geodist).to be_within(0.01).of(expected[:postgresql])
|
43
53
|
else # mysql
|
44
|
-
expect(cities.first.geodist).to
|
54
|
+
expect(cities.first.geodist).to be_within(0.01).of(expected[:mysql])
|
45
55
|
end
|
46
56
|
end
|
47
57
|
|
@@ -34,7 +34,7 @@ describe "Merging deltas", :live => true do
|
|
34
34
|
Book.search("Space", :indices => ["book_core"]).to_a
|
35
35
|
).to eq([race])
|
36
36
|
|
37
|
-
race.reload.
|
37
|
+
race.reload.update :title => "The Hate Race"
|
38
38
|
sleep 0.25
|
39
39
|
expect(
|
40
40
|
Book.search("Race", :indices => ["book_delta"]).to_a
|
@@ -11,7 +11,7 @@ describe 'Updates to records in real-time indices', :live => true do
|
|
11
11
|
|
12
12
|
it "handles attributes for sortable fields accordingly" do
|
13
13
|
product = Product.create! :name => 'Red Fish'
|
14
|
-
product.
|
14
|
+
product.update :name => 'Blue Fish'
|
15
15
|
|
16
16
|
expect(Product.search('blue fish', :indices => ['product_core']).to_a).
|
17
17
|
to eq([product])
|
@@ -22,7 +22,7 @@ describe 'Updates to records in real-time indices', :live => true do
|
|
22
22
|
|
23
23
|
expect(Admin::Person.search('Death').to_a).to eq([person])
|
24
24
|
|
25
|
-
person.
|
25
|
+
person.update :name => 'Mort'
|
26
26
|
|
27
27
|
expect(Admin::Person.search('Death').to_a).to be_empty
|
28
28
|
expect(Admin::Person.search('Mort').to_a).to eq([person])
|
@@ -25,7 +25,7 @@ describe 'SQL delta indexing', :live => true do
|
|
25
25
|
|
26
26
|
expect(Book.search('Harry').to_a).to eq([book])
|
27
27
|
|
28
|
-
book.reload.
|
28
|
+
book.reload.update(:author => 'Terry Pratchett')
|
29
29
|
sleep 0.25
|
30
30
|
|
31
31
|
expect(Book.search('Terry').to_a).to eq([book])
|
@@ -37,7 +37,7 @@ describe 'SQL delta indexing', :live => true do
|
|
37
37
|
|
38
38
|
expect(Book.search('Harry').to_a).to eq([book])
|
39
39
|
|
40
|
-
book.reload.
|
40
|
+
book.reload.update(:author => 'Terry Pratchett')
|
41
41
|
sleep 0.25
|
42
42
|
|
43
43
|
expect(Book.search('Harry')).to be_empty
|
@@ -49,7 +49,7 @@ describe 'SQL delta indexing', :live => true do
|
|
49
49
|
|
50
50
|
expect(Album.search('Whitloms').to_a).to eq([album])
|
51
51
|
|
52
|
-
album.reload.
|
52
|
+
album.reload.update(:artist => 'The Whitlams')
|
53
53
|
sleep 0.25
|
54
54
|
|
55
55
|
expect(Book.search('Whitloms')).to be_empty
|
@@ -63,4 +63,16 @@ describe 'SQL delta indexing', :live => true do
|
|
63
63
|
|
64
64
|
expect(Book.search('Gaiman').to_a).to eq([book])
|
65
65
|
end
|
66
|
+
|
67
|
+
it "updates associated models" do
|
68
|
+
colour = Colour.create(:name => 'green')
|
69
|
+
sleep 0.25
|
70
|
+
|
71
|
+
expect(Colour.search('green').to_a).to eq([colour])
|
72
|
+
|
73
|
+
tee = colour.tees.create
|
74
|
+
sleep 0.25
|
75
|
+
|
76
|
+
expect(Colour.search(:with => {:tee_ids => tee.id}).to_a).to eq([colour])
|
77
|
+
end
|
66
78
|
end
|