elasticsearch-model 5.1.0 → 6.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -3
- data/Gemfile +5 -0
- data/README.md +18 -11
- data/Rakefile +27 -36
- data/elasticsearch-model.gemspec +6 -6
- data/examples/activerecord_custom_analyzer.rb +135 -0
- data/examples/activerecord_mapping_completion.rb +3 -18
- data/examples/datamapper_article.rb +11 -1
- data/gemfiles/3.0.gemfile +6 -1
- data/gemfiles/4.0.gemfile +8 -1
- data/gemfiles/5.0.gemfile +7 -1
- data/gemfiles/6.0.gemfile +18 -0
- data/lib/elasticsearch/model/adapters/active_record.rb +8 -24
- data/lib/elasticsearch/model/adapters/mongoid.rb +10 -3
- data/lib/elasticsearch/model/importing.rb +1 -1
- data/lib/elasticsearch/model/indexing.rb +6 -4
- data/lib/elasticsearch/model/naming.rb +9 -2
- data/lib/elasticsearch/model/response/aggregations.rb +1 -1
- data/lib/elasticsearch/model/response/base.rb +3 -2
- data/lib/elasticsearch/model/response/pagination/kaminari.rb +109 -0
- data/lib/elasticsearch/model/response/pagination/will_paginate.rb +95 -0
- data/lib/elasticsearch/model/response/pagination.rb +2 -192
- data/lib/elasticsearch/model/response/result.rb +1 -1
- data/lib/elasticsearch/model/response/suggestions.rb +1 -1
- data/lib/elasticsearch/model/response.rb +11 -10
- data/lib/elasticsearch/model/version.rb +1 -1
- data/lib/elasticsearch/model.rb +15 -8
- data/spec/elasticsearch/model/adapter_spec.rb +119 -0
- data/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +334 -0
- data/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +340 -0
- data/spec/elasticsearch/model/adapters/active_record/dynamic_index_name_spec.rb +18 -0
- data/spec/elasticsearch/model/adapters/active_record/import_spec.rb +187 -0
- data/spec/elasticsearch/model/adapters/active_record/multi_model_spec.rb +110 -0
- data/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +38 -0
- data/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +315 -0
- data/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +75 -0
- data/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +61 -0
- data/spec/elasticsearch/model/adapters/active_record_spec.rb +207 -0
- data/spec/elasticsearch/model/adapters/default_spec.rb +41 -0
- data/spec/elasticsearch/model/adapters/mongoid/basic_spec.rb +267 -0
- data/spec/elasticsearch/model/adapters/mongoid/multi_model_spec.rb +66 -0
- data/spec/elasticsearch/model/adapters/mongoid_spec.rb +235 -0
- data/spec/elasticsearch/model/adapters/multiple_spec.rb +125 -0
- data/spec/elasticsearch/model/callbacks_spec.rb +33 -0
- data/spec/elasticsearch/model/client_spec.rb +66 -0
- data/spec/elasticsearch/model/hash_wrapper_spec.rb +12 -0
- data/spec/elasticsearch/model/importing_spec.rb +214 -0
- data/spec/elasticsearch/model/indexing_spec.rb +918 -0
- data/spec/elasticsearch/model/module_spec.rb +101 -0
- data/spec/elasticsearch/model/multimodel_spec.rb +55 -0
- data/spec/elasticsearch/model/naming_inheritance_spec.rb +184 -0
- data/spec/elasticsearch/model/naming_spec.rb +186 -0
- data/spec/elasticsearch/model/proxy_spec.rb +107 -0
- data/spec/elasticsearch/model/response/aggregations_spec.rb +66 -0
- data/spec/elasticsearch/model/response/base_spec.rb +90 -0
- data/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +410 -0
- data/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +262 -0
- data/spec/elasticsearch/model/response/records_spec.rb +118 -0
- data/spec/elasticsearch/model/response/response_spec.rb +131 -0
- data/spec/elasticsearch/model/response/result_spec.rb +122 -0
- data/spec/elasticsearch/model/response/results_spec.rb +56 -0
- data/spec/elasticsearch/model/searching_search_request_spec.rb +112 -0
- data/spec/elasticsearch/model/searching_spec.rb +49 -0
- data/spec/elasticsearch/model/serializing_spec.rb +22 -0
- data/spec/spec_helper.rb +161 -0
- data/spec/support/app/answer.rb +33 -0
- data/spec/support/app/article.rb +22 -0
- data/spec/support/app/article_for_pagination.rb +12 -0
- data/spec/support/app/article_with_custom_serialization.rb +13 -0
- data/spec/support/app/article_with_dynamic_index_name.rb +15 -0
- data/spec/support/app/author.rb +9 -0
- data/spec/support/app/authorship.rb +4 -0
- data/spec/support/app/category.rb +3 -0
- data/spec/support/app/comment.rb +3 -0
- data/spec/support/app/episode.rb +11 -0
- data/spec/support/app/image.rb +19 -0
- data/spec/support/app/import_article.rb +12 -0
- data/spec/support/app/mongoid_article.rb +21 -0
- data/spec/support/app/namespaced_book.rb +10 -0
- data/spec/support/app/parent_and_child_searchable.rb +24 -0
- data/spec/support/app/post.rb +14 -0
- data/spec/support/app/question.rb +27 -0
- data/spec/support/app/searchable.rb +48 -0
- data/spec/support/app/series.rb +11 -0
- data/spec/support/app.rb +21 -0
- data/spec/support/model.json +1 -0
- data/{test → spec}/support/model.yml +0 -0
- metadata +134 -89
- data/test/integration/active_record_associations_parent_child_test.rb +0 -147
- data/test/integration/active_record_associations_test.rb +0 -339
- data/test/integration/active_record_basic_test.rb +0 -251
- data/test/integration/active_record_custom_serialization_test.rb +0 -67
- data/test/integration/active_record_import_test.rb +0 -115
- data/test/integration/active_record_namespaced_model_test.rb +0 -54
- data/test/integration/active_record_pagination_test.rb +0 -149
- data/test/integration/dynamic_index_name_test.rb +0 -52
- data/test/integration/mongoid_basic_test.rb +0 -176
- data/test/integration/multiple_models_test.rb +0 -176
- data/test/support/model.json +0 -1
- data/test/test_helper.rb +0 -92
- data/test/unit/adapter_active_record_test.rb +0 -157
- data/test/unit/adapter_default_test.rb +0 -41
- data/test/unit/adapter_mongoid_test.rb +0 -104
- data/test/unit/adapter_multiple_test.rb +0 -106
- data/test/unit/adapter_test.rb +0 -69
- data/test/unit/callbacks_test.rb +0 -31
- data/test/unit/client_test.rb +0 -27
- data/test/unit/hash_wrapper_test.rb +0 -13
- data/test/unit/importing_test.rb +0 -203
- data/test/unit/indexing_test.rb +0 -687
- data/test/unit/module_test.rb +0 -68
- data/test/unit/multimodel_test.rb +0 -38
- data/test/unit/naming_inheritance_test.rb +0 -94
- data/test/unit/naming_test.rb +0 -103
- data/test/unit/proxy_test.rb +0 -98
- data/test/unit/response_aggregations_test.rb +0 -46
- data/test/unit/response_base_test.rb +0 -40
- data/test/unit/response_pagination_kaminari_test.rb +0 -433
- data/test/unit/response_pagination_will_paginate_test.rb +0 -398
- data/test/unit/response_records_test.rb +0 -91
- data/test/unit/response_result_test.rb +0 -90
- data/test/unit/response_results_test.rb +0 -31
- data/test/unit/response_test.rb +0 -104
- data/test/unit/searching_search_request_test.rb +0 -78
- data/test/unit/searching_test.rb +0 -41
- data/test/unit/serializing_test.rb +0 -17
@@ -1,176 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'active_record'
|
3
|
-
|
4
|
-
# Needed for ActiveRecord 3.x ?
|
5
|
-
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ":memory:" ) unless ActiveRecord::Base.connected?
|
6
|
-
|
7
|
-
::ActiveRecord::Base.raise_in_transactional_callbacks = true if ::ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks) && ::ActiveRecord::VERSION::MAJOR.to_s < '5'
|
8
|
-
|
9
|
-
MongoDB.setup!
|
10
|
-
|
11
|
-
module Elasticsearch
|
12
|
-
module Model
|
13
|
-
class MultipleModelsIntegration < Elasticsearch::Test::IntegrationTestCase
|
14
|
-
module ::NameSearch
|
15
|
-
extend ActiveSupport::Concern
|
16
|
-
|
17
|
-
included do
|
18
|
-
include Elasticsearch::Model
|
19
|
-
include Elasticsearch::Model::Callbacks
|
20
|
-
|
21
|
-
settings index: {number_of_shards: 1, number_of_replicas: 0} do
|
22
|
-
mapping do
|
23
|
-
indexes :name, type: 'text', analyzer: 'snowball'
|
24
|
-
indexes :created_at, type: 'date'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class ::Episode < ActiveRecord::Base
|
31
|
-
include NameSearch
|
32
|
-
end
|
33
|
-
|
34
|
-
class ::Series < ActiveRecord::Base
|
35
|
-
include NameSearch
|
36
|
-
end
|
37
|
-
|
38
|
-
context "Multiple models" do
|
39
|
-
setup do
|
40
|
-
ActiveRecord::Schema.define(:version => 1) do
|
41
|
-
create_table :episodes do |t|
|
42
|
-
t.string :name
|
43
|
-
t.datetime :created_at, :default => 'NOW()'
|
44
|
-
end
|
45
|
-
|
46
|
-
create_table :series do |t|
|
47
|
-
t.string :name
|
48
|
-
t.datetime :created_at, :default => 'NOW()'
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
[::Episode, ::Series].each do |model|
|
53
|
-
model.delete_all
|
54
|
-
model.__elasticsearch__.create_index! force: true
|
55
|
-
model.create name: "The #{model.name}"
|
56
|
-
model.create name: "A great #{model.name}"
|
57
|
-
model.create name: "The greatest #{model.name}"
|
58
|
-
model.__elasticsearch__.refresh_index!
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
should "find matching documents across multiple models" do
|
63
|
-
response = Elasticsearch::Model.search(%q<"The greatest Episode"^2 OR "The greatest Series">, [Series, Episode])
|
64
|
-
|
65
|
-
assert response.any?, "Response should not be empty: #{response.to_a.inspect}"
|
66
|
-
|
67
|
-
assert_equal 2, response.results.size
|
68
|
-
assert_equal 2, response.records.size
|
69
|
-
|
70
|
-
assert_instance_of Elasticsearch::Model::Response::Result, response.results.first
|
71
|
-
assert_instance_of Episode, response.records.first
|
72
|
-
assert_instance_of Series, response.records.last
|
73
|
-
|
74
|
-
assert_equal 'The greatest Episode', response.results[0].name
|
75
|
-
assert_equal 'The greatest Episode', response.records[0].name
|
76
|
-
|
77
|
-
assert_equal 'The greatest Series', response.results[1].name
|
78
|
-
assert_equal 'The greatest Series', response.records[1].name
|
79
|
-
end
|
80
|
-
|
81
|
-
should "provide access to results" do
|
82
|
-
response = Elasticsearch::Model.search(%q<"A great Episode"^2 OR "A great Series">, [Series, Episode])
|
83
|
-
|
84
|
-
assert_equal 'A great Episode', response.results[0].name
|
85
|
-
assert_equal true, response.results[0].name?
|
86
|
-
assert_equal false, response.results[0].boo?
|
87
|
-
|
88
|
-
assert_equal 'A great Series', response.results[1].name
|
89
|
-
assert_equal true, response.results[1].name?
|
90
|
-
assert_equal false, response.results[1].boo?
|
91
|
-
end
|
92
|
-
|
93
|
-
should "only retrieve records for existing results" do
|
94
|
-
::Series.find_by_name("The greatest Series").delete
|
95
|
-
::Series.__elasticsearch__.refresh_index!
|
96
|
-
response = Elasticsearch::Model.search(%q<"The greatest Episode"^2 OR "The greatest Series">, [Series, Episode])
|
97
|
-
|
98
|
-
assert response.any?, "Response should not be empty: #{response.to_a.inspect}"
|
99
|
-
|
100
|
-
assert_equal 2, response.results.size
|
101
|
-
assert_equal 1, response.records.size
|
102
|
-
|
103
|
-
assert_instance_of Elasticsearch::Model::Response::Result, response.results.first
|
104
|
-
assert_instance_of Episode, response.records.first
|
105
|
-
|
106
|
-
assert_equal 'The greatest Episode', response.results[0].name
|
107
|
-
assert_equal 'The greatest Episode', response.records[0].name
|
108
|
-
end
|
109
|
-
|
110
|
-
should "paginate the results" do
|
111
|
-
response = Elasticsearch::Model.search('series OR episode', [Series, Episode])
|
112
|
-
|
113
|
-
assert_equal 3, response.page(1).per(3).results.size
|
114
|
-
assert_equal 3, response.page(2).per(3).results.size
|
115
|
-
assert_equal 0, response.page(3).per(3).results.size
|
116
|
-
end
|
117
|
-
|
118
|
-
if MongoDB.available?
|
119
|
-
MongoDB.connect_to 'mongoid_collections'
|
120
|
-
|
121
|
-
context "Across mongoid models" do
|
122
|
-
setup do
|
123
|
-
class ::Image
|
124
|
-
include Mongoid::Document
|
125
|
-
include Elasticsearch::Model
|
126
|
-
include Elasticsearch::Model::Callbacks
|
127
|
-
|
128
|
-
field :name, type: String
|
129
|
-
attr_accessible :name if respond_to? :attr_accessible
|
130
|
-
|
131
|
-
settings index: {number_of_shards: 1, number_of_replicas: 0} do
|
132
|
-
mapping do
|
133
|
-
indexes :name, type: 'text', analyzer: 'snowball'
|
134
|
-
indexes :created_at, type: 'date'
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def as_indexed_json(options={})
|
139
|
-
as_json(except: [:_id])
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
Image.delete_all
|
144
|
-
Image.__elasticsearch__.create_index! force: true
|
145
|
-
Image.create! name: "The Image"
|
146
|
-
Image.create! name: "A great Image"
|
147
|
-
Image.create! name: "The greatest Image"
|
148
|
-
Image.__elasticsearch__.refresh_index!
|
149
|
-
Image.__elasticsearch__.client.cluster.health wait_for_status: 'yellow'
|
150
|
-
end
|
151
|
-
|
152
|
-
should "find matching documents across multiple models" do
|
153
|
-
response = Elasticsearch::Model.search(%q<"greatest Episode" OR "greatest Image"^2>, [Episode, Image])
|
154
|
-
|
155
|
-
assert response.any?, "Response should not be empty: #{response.to_a.inspect}"
|
156
|
-
|
157
|
-
assert_equal 2, response.results.size
|
158
|
-
assert_equal 2, response.records.size
|
159
|
-
|
160
|
-
assert_instance_of Elasticsearch::Model::Response::Result, response.results.first
|
161
|
-
assert_instance_of Image, response.records.first
|
162
|
-
assert_instance_of Episode, response.records.last
|
163
|
-
|
164
|
-
assert_equal 'The greatest Image', response.results[0].name
|
165
|
-
assert_equal 'The greatest Image', response.records[0].name
|
166
|
-
|
167
|
-
assert_equal 'The greatest Episode', response.results[1].name
|
168
|
-
assert_equal 'The greatest Episode', response.records[1].name
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
data/test/support/model.json
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{ "baz": "qux" }
|
data/test/test_helper.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
RUBY_1_8 = defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
|
2
|
-
|
3
|
-
exit(0) if RUBY_1_8
|
4
|
-
|
5
|
-
require 'simplecov' and SimpleCov.start { add_filter "/test|test_/" } if ENV["COVERAGE"]
|
6
|
-
|
7
|
-
# Register `at_exit` handler for integration tests shutdown.
|
8
|
-
# MUST be called before requiring `test/unit`.
|
9
|
-
at_exit { Elasticsearch::Test::IntegrationTestCase.__run_at_exit_hooks }
|
10
|
-
|
11
|
-
puts '-'*80
|
12
|
-
|
13
|
-
if defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
|
14
|
-
require 'test-unit'
|
15
|
-
require 'mocha/test_unit'
|
16
|
-
else
|
17
|
-
require 'minitest/autorun'
|
18
|
-
require 'mocha/mini_test'
|
19
|
-
end
|
20
|
-
|
21
|
-
require 'shoulda-context'
|
22
|
-
|
23
|
-
require 'turn' unless ENV["TM_FILEPATH"] || ENV["NOTURN"] || defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
|
24
|
-
|
25
|
-
require 'ansi'
|
26
|
-
require 'oj'
|
27
|
-
|
28
|
-
require 'active_model'
|
29
|
-
|
30
|
-
require 'kaminari'
|
31
|
-
|
32
|
-
require 'elasticsearch/model'
|
33
|
-
|
34
|
-
require 'elasticsearch/extensions/test/cluster'
|
35
|
-
require 'elasticsearch/extensions/test/startup_shutdown'
|
36
|
-
|
37
|
-
module Elasticsearch
|
38
|
-
module Test
|
39
|
-
class IntegrationTestCase < ::Test::Unit::TestCase
|
40
|
-
extend Elasticsearch::Extensions::Test::StartupShutdown
|
41
|
-
|
42
|
-
startup { Elasticsearch::Extensions::Test::Cluster.start(nodes: 1) if ENV['SERVER'] and not Elasticsearch::Extensions::Test::Cluster.running? }
|
43
|
-
shutdown { Elasticsearch::Extensions::Test::Cluster.stop if ENV['SERVER'] && started? }
|
44
|
-
context "IntegrationTest" do; should "noop on Ruby 1.8" do; end; end if RUBY_1_8
|
45
|
-
|
46
|
-
def setup
|
47
|
-
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ":memory:" )
|
48
|
-
logger = ::Logger.new(STDERR)
|
49
|
-
logger.formatter = lambda { |s, d, p, m| "\e[2;36m#{m}\e[0m\n" }
|
50
|
-
ActiveRecord::Base.logger = logger unless ENV['QUIET']
|
51
|
-
|
52
|
-
ActiveRecord::LogSubscriber.colorize_logging = false
|
53
|
-
ActiveRecord::Migration.verbose = false
|
54
|
-
|
55
|
-
tracer = ::Logger.new(STDERR)
|
56
|
-
tracer.formatter = lambda { |s, d, p, m| "#{m.gsub(/^.*$/) { |n| ' ' + n }.ansi(:faint)}\n" }
|
57
|
-
|
58
|
-
Elasticsearch::Model.client = Elasticsearch::Client.new host: "localhost:#{(ENV['TEST_CLUSTER_PORT'] || 9250)}",
|
59
|
-
tracer: (ENV['QUIET'] ? nil : tracer)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
class MongoDB
|
66
|
-
def self.setup!
|
67
|
-
begin
|
68
|
-
require 'mongoid'
|
69
|
-
Mongo::Client.new(["localhost:27017"])
|
70
|
-
ENV['MONGODB_AVAILABLE'] = 'yes'
|
71
|
-
rescue LoadError, Mongo::Error => e
|
72
|
-
$stderr.puts "MongoDB not installed or running: #{e}"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def self.available?
|
77
|
-
!!ENV['MONGODB_AVAILABLE']
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.connect_to(source)
|
81
|
-
$stderr.puts "Mongoid #{Mongoid::VERSION}", '-'*80
|
82
|
-
|
83
|
-
logger = ::Logger.new($stderr)
|
84
|
-
logger.formatter = lambda { |s, d, p, m| " #{m.ansi(:faint, :cyan)}\n" }
|
85
|
-
logger.level = ::Logger::DEBUG
|
86
|
-
|
87
|
-
Mongoid.logger = logger unless ENV['QUIET']
|
88
|
-
Mongo::Logger.logger = logger unless ENV['QUIET']
|
89
|
-
|
90
|
-
Mongoid.connect_to source
|
91
|
-
end
|
92
|
-
end
|
@@ -1,157 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class Elasticsearch::Model::AdapterActiveRecordTest < Test::Unit::TestCase
|
4
|
-
context "Adapter ActiveRecord module: " do
|
5
|
-
class ::DummyClassForActiveRecord
|
6
|
-
RESPONSE = Struct.new('DummyActiveRecordResponse') do
|
7
|
-
def response
|
8
|
-
{ 'hits' => {'hits' => [ {'_id' => 2}, {'_id' => 1} ]} }
|
9
|
-
end
|
10
|
-
end.new
|
11
|
-
|
12
|
-
def response
|
13
|
-
RESPONSE
|
14
|
-
end
|
15
|
-
|
16
|
-
def ids
|
17
|
-
[2, 1]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
RESPONSE = { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [] } }
|
22
|
-
|
23
|
-
setup do
|
24
|
-
@records = [ stub(id: 1, inspect: '<Model-1>'), stub(id: 2, inspect: '<Model-2>') ]
|
25
|
-
@records.stubs(:load).returns(true)
|
26
|
-
@records.stubs(:exec_queries).returns(true)
|
27
|
-
end
|
28
|
-
|
29
|
-
should "have the register condition" do
|
30
|
-
assert_not_nil Elasticsearch::Model::Adapter.adapters[Elasticsearch::Model::Adapter::ActiveRecord]
|
31
|
-
assert_equal false, Elasticsearch::Model::Adapter.adapters[Elasticsearch::Model::Adapter::ActiveRecord].call(DummyClassForActiveRecord)
|
32
|
-
end
|
33
|
-
|
34
|
-
context "Records" do
|
35
|
-
setup do
|
36
|
-
DummyClassForActiveRecord.__send__ :include, Elasticsearch::Model::Adapter::ActiveRecord::Records
|
37
|
-
end
|
38
|
-
|
39
|
-
should "have the implementation" do
|
40
|
-
assert_instance_of Module, Elasticsearch::Model::Adapter::ActiveRecord::Records
|
41
|
-
|
42
|
-
instance = DummyClassForActiveRecord.new
|
43
|
-
instance.expects(:klass).returns(mock('class', primary_key: :some_key, where: @records)).at_least_once
|
44
|
-
|
45
|
-
assert_equal @records, instance.records
|
46
|
-
end
|
47
|
-
|
48
|
-
should "load the records" do
|
49
|
-
instance = DummyClassForActiveRecord.new
|
50
|
-
instance.expects(:records).returns(@records)
|
51
|
-
instance.load
|
52
|
-
end
|
53
|
-
|
54
|
-
should "load the records with its submodels when using :includes" do
|
55
|
-
klass = mock('class', primary_key: :some_key, where: @records)
|
56
|
-
@records.expects(:includes).with([:submodel]).at_least_once
|
57
|
-
|
58
|
-
instance = DummyClassForActiveRecord.new
|
59
|
-
instance.expects(:klass).returns(klass).at_least_once
|
60
|
-
instance.options[:includes] = [:submodel]
|
61
|
-
instance.records
|
62
|
-
end
|
63
|
-
|
64
|
-
should "reorder the records based on hits order" do
|
65
|
-
@records.instance_variable_set(:@records, @records)
|
66
|
-
|
67
|
-
instance = DummyClassForActiveRecord.new
|
68
|
-
instance.expects(:klass).returns(mock('class', primary_key: :some_key, where: @records)).at_least_once
|
69
|
-
|
70
|
-
assert_equal [1, 2], @records. to_a.map(&:id)
|
71
|
-
assert_equal [2, 1], instance.records.to_a.map(&:id)
|
72
|
-
end
|
73
|
-
|
74
|
-
should "not reorder records when SQL order is present" do
|
75
|
-
@records.instance_variable_set(:@records, @records)
|
76
|
-
|
77
|
-
instance = DummyClassForActiveRecord.new
|
78
|
-
instance.expects(:klass).returns(stub('class', primary_key: :some_key, where: @records)).at_least_once
|
79
|
-
instance.records.expects(:order).returns(@records)
|
80
|
-
|
81
|
-
assert_equal [2, 1], instance.records. to_a.map(&:id)
|
82
|
-
assert_equal [1, 2], instance.order(:foo).to_a.map(&:id)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context "Callbacks" do
|
87
|
-
should "register hooks for automatically updating the index" do
|
88
|
-
DummyClassForActiveRecord.expects(:after_commit).times(3)
|
89
|
-
|
90
|
-
Elasticsearch::Model::Adapter::ActiveRecord::Callbacks.included(DummyClassForActiveRecord)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context "Importing" do
|
95
|
-
setup do
|
96
|
-
DummyClassForActiveRecord.__send__ :extend, Elasticsearch::Model::Adapter::ActiveRecord::Importing
|
97
|
-
end
|
98
|
-
|
99
|
-
should "raise an exception when passing an invalid scope" do
|
100
|
-
assert_raise NoMethodError do
|
101
|
-
DummyClassForActiveRecord.__find_in_batches(scope: :not_found_method) do; end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
should "implement the __find_in_batches method" do
|
106
|
-
DummyClassForActiveRecord.expects(:find_in_batches).returns([])
|
107
|
-
DummyClassForActiveRecord.__find_in_batches do; end
|
108
|
-
end
|
109
|
-
|
110
|
-
should "limit the relation to a specific scope" do
|
111
|
-
DummyClassForActiveRecord.expects(:find_in_batches).returns([])
|
112
|
-
DummyClassForActiveRecord.expects(:published).returns(DummyClassForActiveRecord)
|
113
|
-
|
114
|
-
DummyClassForActiveRecord.__find_in_batches(scope: :published) do; end
|
115
|
-
end
|
116
|
-
|
117
|
-
should "limit the relation to a specific query" do
|
118
|
-
DummyClassForActiveRecord.expects(:find_in_batches).returns([])
|
119
|
-
DummyClassForActiveRecord.expects(:where).returns(DummyClassForActiveRecord)
|
120
|
-
|
121
|
-
DummyClassForActiveRecord.__find_in_batches(query: -> { where(color: "red") }) do; end
|
122
|
-
end
|
123
|
-
|
124
|
-
should "preprocess the batch if option provided" do
|
125
|
-
class << DummyClassForActiveRecord
|
126
|
-
# Updates/transforms the batch while fetching it from the database
|
127
|
-
# (eg. with information from an external system)
|
128
|
-
#
|
129
|
-
def update_batch(batch)
|
130
|
-
batch.collect { |b| b.to_s + '!' }
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
DummyClassForActiveRecord.expects(:__find_in_batches).returns( [:a, :b] )
|
135
|
-
|
136
|
-
DummyClassForActiveRecord.__find_in_batches(preprocess: :update_batch) do |batch|
|
137
|
-
assert_same_elements ["a!", "b!"], batch
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
context "when transforming models" do
|
142
|
-
setup do
|
143
|
-
@transform = DummyClassForActiveRecord.__transform
|
144
|
-
end
|
145
|
-
|
146
|
-
should "provide an object that responds to #call" do
|
147
|
-
assert_respond_to @transform, :call
|
148
|
-
end
|
149
|
-
|
150
|
-
should "provide default transformation" do
|
151
|
-
model = mock("model", id: 1, __elasticsearch__: stub(as_indexed_json: {}))
|
152
|
-
assert_equal @transform.call(model), { index: { _id: 1, data: {} } }
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class Elasticsearch::Model::AdapterDefaultTest < Test::Unit::TestCase
|
4
|
-
context "Adapter default module" do
|
5
|
-
class ::DummyClassForDefaultAdapter; end
|
6
|
-
|
7
|
-
should "have the default Records implementation" do
|
8
|
-
assert_instance_of Module, Elasticsearch::Model::Adapter::Default::Records
|
9
|
-
|
10
|
-
DummyClassForDefaultAdapter.__send__ :include, Elasticsearch::Model::Adapter::Default::Records
|
11
|
-
|
12
|
-
instance = DummyClassForDefaultAdapter.new
|
13
|
-
klass = mock('class', find: [1])
|
14
|
-
instance.expects(:klass).returns(klass)
|
15
|
-
instance.records
|
16
|
-
end
|
17
|
-
|
18
|
-
should "have the default Callbacks implementation" do
|
19
|
-
assert_instance_of Module, Elasticsearch::Model::Adapter::Default::Callbacks
|
20
|
-
end
|
21
|
-
|
22
|
-
context "concerning abstract methods" do
|
23
|
-
setup do
|
24
|
-
DummyClassForDefaultAdapter.__send__ :include, Elasticsearch::Model::Adapter::Default::Importing
|
25
|
-
end
|
26
|
-
|
27
|
-
should "have the default Importing implementation" do
|
28
|
-
assert_raise Elasticsearch::Model::NotImplemented do
|
29
|
-
DummyClassForDefaultAdapter.new.__find_in_batches
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
should "have the default transform implementation" do
|
34
|
-
assert_raise Elasticsearch::Model::NotImplemented do
|
35
|
-
DummyClassForDefaultAdapter.new.__transform
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
@@ -1,104 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class Elasticsearch::Model::AdapterMongoidTest < Test::Unit::TestCase
|
4
|
-
context "Adapter Mongoid module: " do
|
5
|
-
class ::DummyClassForMongoid
|
6
|
-
RESPONSE = Struct.new('DummyMongoidResponse') do
|
7
|
-
def response
|
8
|
-
{ 'hits' => {'hits' => [ {'_id' => 2}, {'_id' => 1} ]} }
|
9
|
-
end
|
10
|
-
end.new
|
11
|
-
|
12
|
-
def response
|
13
|
-
RESPONSE
|
14
|
-
end
|
15
|
-
|
16
|
-
def ids
|
17
|
-
[2, 1]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
setup do
|
22
|
-
@records = [ stub(id: 1, inspect: '<Model-1>'), stub(id: 2, inspect: '<Model-2>') ]
|
23
|
-
::Symbol.any_instance.stubs(:in).returns(@records)
|
24
|
-
end
|
25
|
-
|
26
|
-
should "have the register condition" do
|
27
|
-
assert_not_nil Elasticsearch::Model::Adapter.adapters[Elasticsearch::Model::Adapter::Mongoid]
|
28
|
-
assert_equal false, Elasticsearch::Model::Adapter.adapters[Elasticsearch::Model::Adapter::Mongoid].call(DummyClassForMongoid)
|
29
|
-
end
|
30
|
-
|
31
|
-
context "Records" do
|
32
|
-
setup do
|
33
|
-
DummyClassForMongoid.__send__ :include, Elasticsearch::Model::Adapter::Mongoid::Records
|
34
|
-
end
|
35
|
-
|
36
|
-
should "have the implementation" do
|
37
|
-
assert_instance_of Module, Elasticsearch::Model::Adapter::Mongoid::Records
|
38
|
-
|
39
|
-
instance = DummyClassForMongoid.new
|
40
|
-
instance.expects(:klass).returns(mock('class', where: @records))
|
41
|
-
|
42
|
-
assert_equal @records, instance.records
|
43
|
-
end
|
44
|
-
|
45
|
-
should "reorder the records based on hits order" do
|
46
|
-
@records.instance_variable_set(:@records, @records)
|
47
|
-
|
48
|
-
instance = DummyClassForMongoid.new
|
49
|
-
instance.expects(:klass).returns(mock('class', where: @records))
|
50
|
-
|
51
|
-
assert_equal [1, 2], @records. to_a.map(&:id)
|
52
|
-
assert_equal [2, 1], instance.records.to_a.map(&:id)
|
53
|
-
end
|
54
|
-
|
55
|
-
should "not reorder records when SQL order is present" do
|
56
|
-
@records.instance_variable_set(:@records, @records)
|
57
|
-
|
58
|
-
instance = DummyClassForMongoid.new
|
59
|
-
instance.expects(:klass).returns(stub('class', where: @records)).at_least_once
|
60
|
-
instance.records.expects(:asc).returns(@records)
|
61
|
-
|
62
|
-
assert_equal [2, 1], instance.records.to_a.map(&:id)
|
63
|
-
assert_equal [1, 2], instance.asc.to_a.map(&:id)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context "Callbacks" do
|
68
|
-
should "register hooks for automatically updating the index" do
|
69
|
-
DummyClassForMongoid.expects(:after_create)
|
70
|
-
DummyClassForMongoid.expects(:after_update)
|
71
|
-
DummyClassForMongoid.expects(:after_destroy)
|
72
|
-
|
73
|
-
Elasticsearch::Model::Adapter::Mongoid::Callbacks.included(DummyClassForMongoid)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context "Importing" do
|
78
|
-
should "implement the __find_in_batches method" do
|
79
|
-
relation = mock()
|
80
|
-
relation.stubs(:no_timeout).returns([])
|
81
|
-
DummyClassForMongoid.expects(:all).returns(relation)
|
82
|
-
|
83
|
-
DummyClassForMongoid.__send__ :extend, Elasticsearch::Model::Adapter::Mongoid::Importing
|
84
|
-
DummyClassForMongoid.__find_in_batches do; end
|
85
|
-
end
|
86
|
-
|
87
|
-
context "when transforming models" do
|
88
|
-
setup do
|
89
|
-
@transform = DummyClassForMongoid.__transform
|
90
|
-
end
|
91
|
-
|
92
|
-
should "provide an object that responds to #call" do
|
93
|
-
assert_respond_to @transform, :call
|
94
|
-
end
|
95
|
-
|
96
|
-
should "provide basic transformation" do
|
97
|
-
model = mock("model", id: 1, as_indexed_json: {})
|
98
|
-
assert_equal @transform.call(model), { index: { _id: "1", data: {} } }
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
104
|
-
end
|
@@ -1,106 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class Elasticsearch::Model::MultipleTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
context "Adapter for multiple models" do
|
6
|
-
|
7
|
-
class ::DummyOne
|
8
|
-
include Elasticsearch::Model
|
9
|
-
|
10
|
-
index_name 'dummy'
|
11
|
-
document_type 'dummy_one'
|
12
|
-
|
13
|
-
def self.find(ids)
|
14
|
-
ids.map { |id| new(id) }
|
15
|
-
end
|
16
|
-
|
17
|
-
attr_reader :id
|
18
|
-
|
19
|
-
def initialize(id)
|
20
|
-
@id = id.to_i
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
module ::Namespace
|
25
|
-
class DummyTwo
|
26
|
-
include Elasticsearch::Model
|
27
|
-
|
28
|
-
index_name 'dummy'
|
29
|
-
document_type 'dummy_two'
|
30
|
-
|
31
|
-
def self.find(ids)
|
32
|
-
ids.map { |id| new(id) }
|
33
|
-
end
|
34
|
-
|
35
|
-
attr_reader :id
|
36
|
-
|
37
|
-
def initialize(id)
|
38
|
-
@id = id.to_i
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class ::DummyTwo
|
44
|
-
include Elasticsearch::Model
|
45
|
-
|
46
|
-
index_name 'other_index'
|
47
|
-
document_type 'dummy_two'
|
48
|
-
|
49
|
-
def self.find(ids)
|
50
|
-
ids.map { |id| new(id) }
|
51
|
-
end
|
52
|
-
|
53
|
-
attr_reader :id
|
54
|
-
|
55
|
-
def initialize(id)
|
56
|
-
@id = id.to_i
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
HITS = [{_index: 'dummy',
|
61
|
-
_type: 'dummy_two',
|
62
|
-
_id: '2',
|
63
|
-
}, {
|
64
|
-
_index: 'dummy',
|
65
|
-
_type: 'dummy_one',
|
66
|
-
_id: '2',
|
67
|
-
}, {
|
68
|
-
_index: 'other_index',
|
69
|
-
_type: 'dummy_two',
|
70
|
-
_id: '1',
|
71
|
-
}, {
|
72
|
-
_index: 'dummy',
|
73
|
-
_type: 'dummy_two',
|
74
|
-
_id: '1',
|
75
|
-
}, {
|
76
|
-
_index: 'dummy',
|
77
|
-
_type: 'dummy_one',
|
78
|
-
_id: '3'}]
|
79
|
-
|
80
|
-
setup do
|
81
|
-
@multimodel = Elasticsearch::Model::Multimodel.new(DummyOne, DummyTwo, Namespace::DummyTwo)
|
82
|
-
end
|
83
|
-
|
84
|
-
context "when returning records" do
|
85
|
-
setup do
|
86
|
-
@multimodel.class.send :include, Elasticsearch::Model::Adapter::Multiple::Records
|
87
|
-
@multimodel.expects(:response).at_least_once.returns(stub(response: { 'hits' => { 'hits' => HITS } }))
|
88
|
-
end
|
89
|
-
|
90
|
-
should "keep the order from response" do
|
91
|
-
assert_instance_of Module, Elasticsearch::Model::Adapter::Multiple::Records
|
92
|
-
records = @multimodel.records
|
93
|
-
|
94
|
-
assert_equal 5, records.count
|
95
|
-
|
96
|
-
assert_kind_of ::Namespace::DummyTwo, records[0]
|
97
|
-
assert_kind_of ::DummyOne, records[1]
|
98
|
-
assert_kind_of ::DummyTwo, records[2]
|
99
|
-
assert_kind_of ::Namespace::DummyTwo, records[3]
|
100
|
-
assert_kind_of ::DummyOne, records[4]
|
101
|
-
|
102
|
-
assert_equal [2, 2, 1, 1, 3], records.map(&:id)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|