elasticsearch-model 6.0.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/README.md +14 -7
  4. data/Rakefile +27 -36
  5. data/elasticsearch-model.gemspec +1 -1
  6. data/examples/activerecord_mapping_completion.rb +2 -15
  7. data/gemfiles/3.0.gemfile +6 -1
  8. data/gemfiles/4.0.gemfile +7 -1
  9. data/gemfiles/5.0.gemfile +6 -0
  10. data/lib/elasticsearch/model.rb +15 -8
  11. data/lib/elasticsearch/model/adapters/active_record.rb +7 -26
  12. data/lib/elasticsearch/model/indexing.rb +5 -3
  13. data/lib/elasticsearch/model/naming.rb +6 -1
  14. data/lib/elasticsearch/model/response.rb +2 -2
  15. data/lib/elasticsearch/model/response/pagination.rb +2 -192
  16. data/lib/elasticsearch/model/response/pagination/kaminari.rb +109 -0
  17. data/lib/elasticsearch/model/response/pagination/will_paginate.rb +95 -0
  18. data/lib/elasticsearch/model/response/result.rb +1 -1
  19. data/lib/elasticsearch/model/version.rb +1 -1
  20. data/spec/elasticsearch/model/adapter_spec.rb +119 -0
  21. data/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +334 -0
  22. data/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +340 -0
  23. data/spec/elasticsearch/model/adapters/active_record/dynamic_index_name_spec.rb +18 -0
  24. data/spec/elasticsearch/model/adapters/active_record/import_spec.rb +187 -0
  25. data/spec/elasticsearch/model/adapters/active_record/multi_model_spec.rb +110 -0
  26. data/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +38 -0
  27. data/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +315 -0
  28. data/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +75 -0
  29. data/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +61 -0
  30. data/spec/elasticsearch/model/adapters/active_record_spec.rb +207 -0
  31. data/spec/elasticsearch/model/adapters/default_spec.rb +41 -0
  32. data/spec/elasticsearch/model/adapters/mongoid/basic_spec.rb +267 -0
  33. data/spec/elasticsearch/model/adapters/mongoid/multi_model_spec.rb +66 -0
  34. data/spec/elasticsearch/model/adapters/mongoid_spec.rb +235 -0
  35. data/spec/elasticsearch/model/adapters/multiple_spec.rb +125 -0
  36. data/spec/elasticsearch/model/callbacks_spec.rb +33 -0
  37. data/spec/elasticsearch/model/client_spec.rb +66 -0
  38. data/spec/elasticsearch/model/hash_wrapper_spec.rb +12 -0
  39. data/spec/elasticsearch/model/importing_spec.rb +214 -0
  40. data/spec/elasticsearch/model/indexing_spec.rb +918 -0
  41. data/spec/elasticsearch/model/module_spec.rb +101 -0
  42. data/spec/elasticsearch/model/multimodel_spec.rb +55 -0
  43. data/spec/elasticsearch/model/naming_inheritance_spec.rb +184 -0
  44. data/spec/elasticsearch/model/naming_spec.rb +186 -0
  45. data/spec/elasticsearch/model/proxy_spec.rb +107 -0
  46. data/spec/elasticsearch/model/response/aggregations_spec.rb +66 -0
  47. data/spec/elasticsearch/model/response/base_spec.rb +90 -0
  48. data/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +410 -0
  49. data/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +262 -0
  50. data/spec/elasticsearch/model/response/records_spec.rb +118 -0
  51. data/spec/elasticsearch/model/response/response_spec.rb +131 -0
  52. data/spec/elasticsearch/model/response/result_spec.rb +122 -0
  53. data/spec/elasticsearch/model/response/results_spec.rb +56 -0
  54. data/spec/elasticsearch/model/searching_search_request_spec.rb +112 -0
  55. data/spec/elasticsearch/model/searching_spec.rb +49 -0
  56. data/spec/elasticsearch/model/serializing_spec.rb +22 -0
  57. data/spec/spec_helper.rb +161 -0
  58. data/spec/support/app.rb +21 -0
  59. data/spec/support/app/answer.rb +33 -0
  60. data/spec/support/app/article.rb +22 -0
  61. data/spec/support/app/article_for_pagination.rb +12 -0
  62. data/spec/support/app/article_with_custom_serialization.rb +13 -0
  63. data/spec/support/app/article_with_dynamic_index_name.rb +15 -0
  64. data/spec/support/app/author.rb +9 -0
  65. data/spec/support/app/authorship.rb +4 -0
  66. data/spec/support/app/category.rb +3 -0
  67. data/spec/support/app/comment.rb +3 -0
  68. data/spec/support/app/episode.rb +11 -0
  69. data/spec/support/app/image.rb +19 -0
  70. data/spec/support/app/import_article.rb +12 -0
  71. data/spec/support/app/mongoid_article.rb +21 -0
  72. data/spec/support/app/namespaced_book.rb +10 -0
  73. data/spec/support/app/parent_and_child_searchable.rb +24 -0
  74. data/spec/support/app/post.rb +14 -0
  75. data/spec/support/app/question.rb +27 -0
  76. data/spec/support/app/searchable.rb +48 -0
  77. data/spec/support/app/series.rb +11 -0
  78. data/spec/support/model.json +1 -0
  79. data/{test → spec}/support/model.yml +0 -0
  80. metadata +129 -86
  81. data/test/integration/active_record_associations_parent_child_test.rb +0 -188
  82. data/test/integration/active_record_associations_test.rb +0 -339
  83. data/test/integration/active_record_basic_test.rb +0 -255
  84. data/test/integration/active_record_custom_serialization_test.rb +0 -67
  85. data/test/integration/active_record_import_test.rb +0 -168
  86. data/test/integration/active_record_namespaced_model_test.rb +0 -56
  87. data/test/integration/active_record_pagination_test.rb +0 -149
  88. data/test/integration/dynamic_index_name_test.rb +0 -52
  89. data/test/integration/mongoid_basic_test.rb +0 -240
  90. data/test/integration/multiple_models_test.rb +0 -176
  91. data/test/support/model.json +0 -1
  92. data/test/test_helper.rb +0 -92
  93. data/test/unit/adapter_active_record_test.rb +0 -157
  94. data/test/unit/adapter_default_test.rb +0 -41
  95. data/test/unit/adapter_mongoid_test.rb +0 -161
  96. data/test/unit/adapter_multiple_test.rb +0 -106
  97. data/test/unit/adapter_test.rb +0 -69
  98. data/test/unit/callbacks_test.rb +0 -31
  99. data/test/unit/client_test.rb +0 -27
  100. data/test/unit/hash_wrapper_test.rb +0 -13
  101. data/test/unit/importing_test.rb +0 -224
  102. data/test/unit/indexing_test.rb +0 -720
  103. data/test/unit/module_test.rb +0 -68
  104. data/test/unit/multimodel_test.rb +0 -38
  105. data/test/unit/naming_inheritance_test.rb +0 -94
  106. data/test/unit/naming_test.rb +0 -103
  107. data/test/unit/proxy_test.rb +0 -98
  108. data/test/unit/response_aggregations_test.rb +0 -46
  109. data/test/unit/response_base_test.rb +0 -40
  110. data/test/unit/response_pagination_kaminari_test.rb +0 -433
  111. data/test/unit/response_pagination_will_paginate_test.rb +0 -398
  112. data/test/unit/response_records_test.rb +0 -91
  113. data/test/unit/response_result_test.rb +0 -90
  114. data/test/unit/response_results_test.rb +0 -34
  115. data/test/unit/response_test.rb +0 -104
  116. data/test/unit/searching_search_request_test.rb +0 -78
  117. data/test/unit/searching_test.rb +0 -41
  118. data/test/unit/serializing_test.rb +0 -17
@@ -0,0 +1,122 @@
1
+ require 'spec_helper'
2
+ require 'active_support/json/encoding'
3
+
4
+ describe Elasticsearch::Model::Response::Result do
5
+
6
+ let(:result) do
7
+ described_class.new(foo: 'bar', bar: { bam: 'baz' })
8
+ end
9
+
10
+ it 'provides access to the properties' do
11
+ expect(result.foo).to eq('bar')
12
+ expect(result.bar.bam).to eq('baz')
13
+ expect { result.xoxo }.to raise_exception(NoMethodError)
14
+ end
15
+
16
+ describe '#id' do
17
+
18
+ let(:result) do
19
+ described_class.new(foo: 'bar', _id: 42, _source: { id: 12 })
20
+ end
21
+
22
+ it 'returns the _id field' do
23
+ expect(result.id).to eq(42)
24
+ end
25
+
26
+ it 'provides access to the source id field' do
27
+ expect(result._source.id).to eq(12)
28
+ end
29
+ end
30
+
31
+ describe '#type' do
32
+
33
+ let(:result) do
34
+ described_class.new(foo: 'bar', _type: 'baz', _source: { type: 'BAM' })
35
+ end
36
+
37
+ it 'returns the _type field' do
38
+ expect(result.type).to eq('baz')
39
+ end
40
+
41
+ it 'provides access to the source type field' do
42
+ expect(result._source.type).to eq('BAM')
43
+ end
44
+ end
45
+
46
+ describe 'method delegation' do
47
+
48
+ let(:result) do
49
+ described_class.new(foo: 'bar', _source: { bar: { bam: 'baz' } })
50
+ end
51
+
52
+ it 'provides access to the _source field via a method' do
53
+ expect(result._source).to eq('bar' => { 'bam' => 'baz' })
54
+ end
55
+
56
+ it 'is recognized by #method' do
57
+ expect(result.method :bar).to be_a Method
58
+ end
59
+
60
+ it 'respond_to? still works' do
61
+ expect(result.respond_to? :bar).to be true
62
+ end
63
+
64
+ context 'when methods map to keys in subdocuments of the response from Elasticsearch' do
65
+
66
+ it 'provides access to top level fields via a method' do
67
+ expect(result.foo).to eq('bar')
68
+ expect(result.fetch(:foo)).to eq('bar')
69
+ expect(result.fetch(:does_not_exist, 'moo')).to eq('moo')
70
+ end
71
+
72
+ it 'responds to hash methods' do
73
+ expect(result.keys).to eq(['foo', '_source'])
74
+ expect(result.to_hash).to eq('foo' => 'bar', '_source' => { 'bar' => { 'bam' => 'baz' } })
75
+ end
76
+
77
+ it 'provides access to fields in the _source subdocument via a method' do
78
+ expect(result.bar).to eq('bam' => 'baz')
79
+ expect(result.bar.bam).to eq('baz')
80
+ expect(result._source.bar).to eq('bam' => 'baz')
81
+ expect(result._source.bar.bam).to eq('baz')
82
+ end
83
+
84
+ context 'when boolean methods are called' do
85
+
86
+ it 'provides access to top level fields via a method' do
87
+ expect(result.foo?).to eq(true)
88
+ expect(result.boo?).to eq(false)
89
+ end
90
+
91
+ it 'delegates to fields in the _source subdocument via a method' do
92
+ expect(result.bar?).to eq(true)
93
+ expect(result.bar.bam?).to eq(true)
94
+ expect(result.boo?).to eq(false)
95
+ expect(result.bar.boo?).to eq(false)
96
+ expect(result._source.bar?).to eq(true)
97
+ expect(result._source.bar.bam?).to eq(true)
98
+ expect(result._source.boo?).to eq(false)
99
+ expect(result._source.bar.boo?).to eq(false)
100
+ end
101
+ end
102
+ end
103
+
104
+ context 'when methods do not map to keys in subdocuments of the response from Elasticsearch' do
105
+
106
+ it 'raises a NoMethodError' do
107
+ expect { result.does_not_exist }.to raise_exception(NoMethodError)
108
+ end
109
+ end
110
+ end
111
+
112
+ describe '#as_json' do
113
+
114
+ let(:result) do
115
+ described_class.new(foo: 'bar', _source: { bar: { bam: 'baz' } })
116
+ end
117
+
118
+ it 'returns a json string' do
119
+ expect(result.as_json(except: 'foo')).to eq({'_source'=>{'bar'=>{'bam'=>'baz'}}})
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model::Response::Results do
4
+
5
+ before(:all) do
6
+ class OriginClass
7
+ def self.index_name; 'foo'; end
8
+ def self.document_type; 'bar'; end
9
+ end
10
+ end
11
+
12
+ after(:all) do
13
+ remove_classes(OriginClass)
14
+ end
15
+
16
+ let(:response_document) do
17
+ { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [{'foo' => 'bar'}] } }
18
+ end
19
+
20
+ let(:search) do
21
+ Elasticsearch::Model::Searching::SearchRequest.new(OriginClass, '*').tap do |request|
22
+ allow(request).to receive(:execute!).and_return(response_document)
23
+ end
24
+ end
25
+
26
+ let(:response) do
27
+ Elasticsearch::Model::Response::Response.new(OriginClass, search)
28
+ end
29
+
30
+ let(:results) do
31
+ response.results
32
+ end
33
+
34
+ describe '#results' do
35
+
36
+ it 'provides access to the results' do
37
+ expect(results.results.size).to be(1)
38
+ expect(results.results.first.foo).to eq('bar')
39
+ end
40
+ end
41
+
42
+ describe 'Enumerable' do
43
+
44
+ it 'deletebates enumerable methods to the results' do
45
+ expect(results.empty?).to be(false)
46
+ expect(results.first.foo).to eq('bar')
47
+ end
48
+ end
49
+
50
+ describe '#raw_response' do
51
+
52
+ it 'returns the raw response document' do
53
+ expect(response.raw_response).to eq(response_document)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model::Serializing do
4
+
5
+ before(:all) do
6
+ class ::DummySearchingModel
7
+ extend Elasticsearch::Model::Searching::ClassMethods
8
+ def self.index_name; 'foo'; end
9
+ def self.document_type; 'bar'; end
10
+ end
11
+ end
12
+
13
+ after(:all) do
14
+ remove_classes(DummySearchingModel)
15
+ end
16
+
17
+ before do
18
+ allow(DummySearchingModel).to receive(:client).and_return(client)
19
+ end
20
+
21
+ let(:client) do
22
+ double('client')
23
+ end
24
+
25
+ describe '#initialize' do
26
+
27
+ context 'when the search definition is a simple query' do
28
+
29
+ before do
30
+ expect(client).to receive(:search).with(index: 'foo', type: 'bar', q: 'foo').and_return({})
31
+ end
32
+
33
+ let(:search) do
34
+ Elasticsearch::Model::Searching::SearchRequest.new(DummySearchingModel, 'foo')
35
+ end
36
+
37
+ it 'passes the query to the client' do
38
+ expect(search.execute!).to eq({})
39
+ end
40
+ end
41
+
42
+ context 'when the search definition is a hash' do
43
+
44
+ before do
45
+ expect(client).to receive(:search).with(index: 'foo', type: 'bar', body: { foo: 'bar' }).and_return({})
46
+ end
47
+
48
+ let(:search) do
49
+ Elasticsearch::Model::Searching::SearchRequest.new(DummySearchingModel, foo: 'bar')
50
+ end
51
+
52
+ it 'passes the hash to the client' do
53
+ expect(search.execute!).to eq({})
54
+ end
55
+ end
56
+
57
+ context 'when the search definition is a json string' do
58
+
59
+ before do
60
+ expect(client).to receive(:search).with(index: 'foo', type: 'bar', body: '{"foo":"bar"}').and_return({})
61
+ end
62
+
63
+ let(:search) do
64
+ Elasticsearch::Model::Searching::SearchRequest.new(DummySearchingModel, '{"foo":"bar"}')
65
+ end
66
+
67
+ it 'passes the json string to the client' do
68
+ expect(search.execute!).to eq({})
69
+ end
70
+ end
71
+
72
+ context 'when the search definition is a custom object' do
73
+
74
+ before(:all) do
75
+ class MySpecialQueryBuilder
76
+ def to_hash; {foo: 'bar'}; end
77
+ end
78
+ end
79
+
80
+ after(:all) do
81
+ Object.send(:remove_const, :MySpecialQueryBuilder) if defined?(MySpecialQueryBuilder)
82
+ end
83
+
84
+ before do
85
+ expect(client).to receive(:search).with(index: 'foo', type: 'bar', body: {foo: 'bar'}).and_return({})
86
+ end
87
+
88
+ let(:search) do
89
+ Elasticsearch::Model::Searching::SearchRequest.new(DummySearchingModel, MySpecialQueryBuilder.new)
90
+ end
91
+
92
+ it 'passes the query builder to the client and calls #to_hash on it' do
93
+ expect(search.execute!).to eq({})
94
+ end
95
+ end
96
+
97
+ context 'when extra options are specified' do
98
+
99
+ before do
100
+ expect(client).to receive(:search).with(index: 'foo', type: 'bar', q: 'foo', size: 15).and_return({})
101
+ end
102
+
103
+ let(:search) do
104
+ Elasticsearch::Model::Searching::SearchRequest.new(DummySearchingModel, 'foo', size: 15)
105
+ end
106
+
107
+ it 'passes the extra options to the client as part of the request' do
108
+ expect(search.execute!).to eq({})
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model::Searching::ClassMethods do
4
+
5
+ before(:all) do
6
+ class ::DummySearchingModel
7
+ extend Elasticsearch::Model::Searching::ClassMethods
8
+
9
+ def self.index_name; 'foo'; end
10
+ def self.document_type; 'bar'; end
11
+ end
12
+ end
13
+
14
+ after(:all) do
15
+ remove_classes(DummySearchingModel)
16
+ end
17
+
18
+ it 'has the search method' do
19
+ expect(DummySearchingModel).to respond_to(:search)
20
+ end
21
+
22
+ describe '#search' do
23
+
24
+ let(:response) do
25
+ double('search', execute!: { 'hits' => {'hits' => [ {'_id' => 2 }, {'_id' => 1 } ]} })
26
+ end
27
+
28
+ before do
29
+ expect(Elasticsearch::Model::Searching::SearchRequest).to receive(:new).with(DummySearchingModel, 'foo', { default_operator: 'AND' }).and_return(response)
30
+ end
31
+
32
+ it 'creates a search object' do
33
+ expect(DummySearchingModel.search('foo', default_operator: 'AND')).to be_a(Elasticsearch::Model::Response::Response)
34
+ end
35
+ end
36
+
37
+ describe 'lazy execution' do
38
+
39
+ let(:response) do
40
+ double('search').tap do |r|
41
+ expect(r).to receive(:execute!).never
42
+ end
43
+ end
44
+
45
+ it 'does not execute the search until the results are accessed' do
46
+ DummySearchingModel.search('foo')
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model::Serializing do
4
+
5
+ before(:all) do
6
+ class DummyClass
7
+ include Elasticsearch::Model::Serializing::InstanceMethods
8
+
9
+ def as_json(options={})
10
+ 'HASH'
11
+ end
12
+ end
13
+ end
14
+
15
+ after(:all) do
16
+ remove_classes(DummyClass)
17
+ end
18
+
19
+ it 'delegates to #as_json by default' do
20
+ expect(DummyClass.new.as_indexed_json).to eq('HASH')
21
+ end
22
+ end
@@ -0,0 +1,161 @@
1
+ require 'pry-nav'
2
+ require 'kaminari'
3
+ require 'kaminari/version'
4
+ require 'will_paginate'
5
+ require 'will_paginate/collection'
6
+ require 'elasticsearch/model'
7
+ require 'hashie/version'
8
+ require 'active_model'
9
+ require 'mongoid'
10
+ require 'yaml'
11
+ require 'active_record'
12
+
13
+ unless defined?(ELASTICSEARCH_URL)
14
+ ELASTICSEARCH_URL = ENV['ELASTICSEARCH_URL'] || "localhost:#{(ENV['TEST_CLUSTER_PORT'] || 9200)}"
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+ config.formatter = 'documentation'
19
+ config.color = true
20
+
21
+ config.before(:suite) do
22
+ require 'ansi'
23
+ tracer = ::Logger.new(STDERR)
24
+ tracer.formatter = lambda { |s, d, p, m| "#{m.gsub(/^.*$/) { |n| ' ' + n }.ansi(:faint)}\n" }
25
+ Elasticsearch::Model.client = Elasticsearch::Client.new host: ELASTICSEARCH_URL,
26
+ tracer: (ENV['QUIET'] ? nil : tracer)
27
+
28
+ unless ActiveRecord::Base.connected?
29
+ ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ":memory:" )
30
+ end
31
+ require 'support/app'
32
+
33
+ if ::ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks) && ::ActiveRecord::VERSION::MAJOR.to_s < '5'
34
+ ::ActiveRecord::Base.raise_in_transactional_callbacks = true
35
+ end
36
+ end
37
+
38
+ config.after(:all) do
39
+ drop_all_tables!
40
+ delete_all_indices!
41
+ end
42
+ end
43
+
44
+ # Is the ActiveRecord version at least 4.0?
45
+ #
46
+ # @return [ true, false ] Whether the ActiveRecord version is at least 4.0.
47
+ #
48
+ # @since 6.0.1
49
+ def active_record_at_least_4?
50
+ defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 4
51
+ end
52
+
53
+ # Delete all documents from the indices of the provided list of models.
54
+ #
55
+ # @param [ Array<ActiveRecord::Base> ] models The list of models.
56
+ #
57
+ # @return [ true ]
58
+ #
59
+ # @since 6.0.1
60
+ def clear_indices(*models)
61
+ models.each do |model|
62
+ begin; Elasticsearch::Model.client.delete_by_query(index: model.index_name, q: '*'); rescue; end
63
+ end and true
64
+ end
65
+
66
+ # Delete all documents from the tables of the provided list of models.
67
+ #
68
+ # @param [ Array<ActiveRecord::Base> ] models The list of models.
69
+ #
70
+ # @return [ true ]
71
+ #
72
+ # @since 6.0.1
73
+ def clear_tables(*models)
74
+ begin; models.map(&:delete_all); rescue; end and true
75
+ end
76
+
77
+ # Drop all tables of models registered as subclasses of ActiveRecord::Base.
78
+ #
79
+ # @return [ true ]
80
+ #
81
+ # @since 6.0.1
82
+ def drop_all_tables!
83
+ ActiveRecord::Base.descendants.each do |model|
84
+ begin
85
+ ActiveRecord::Schema.define do
86
+ drop_table model
87
+ end if model.table_exists?
88
+ rescue
89
+ end
90
+ end and true
91
+ end
92
+
93
+ # Drop all indices of models registered as subclasses of ActiveRecord::Base.
94
+ #
95
+ # @return [ true ]
96
+ #
97
+ # @since 6.0.1
98
+ def delete_all_indices!
99
+ client = Elasticsearch::Model.client
100
+ ActiveRecord::Base.descendants.each do |model|
101
+ begin
102
+ client.indices.delete(index: model.index_name) if model.__elasticsearch__.index_exists?
103
+ rescue
104
+ end
105
+ end and true
106
+ end
107
+
108
+ # Remove all classes.
109
+ #
110
+ # @param [ Array<Class> ] classes The list of classes to remove.
111
+ #
112
+ # @return [ true ]
113
+ #
114
+ # @since 6.0.1
115
+ def remove_classes(*classes)
116
+ classes.each do |_class|
117
+ Object.send(:remove_const, _class.name.to_sym) if defined?(_class)
118
+ end and true
119
+ end
120
+
121
+ # Determine whether the tests with Mongoid should be run.
122
+ # Depends on whether MongoDB is running on the default host and port, `localhost:27017`.
123
+ #
124
+ # @return [ true, false ]
125
+ #
126
+ # @since 6.0.1
127
+ def test_mongoid?
128
+ $mongoid_available ||= begin
129
+ require 'mongoid'
130
+ if defined?(Mongo) # older versions of Mongoid use the driver, Moped
131
+ client = Mongo::Client.new(['localhost:27017'])
132
+ Timeout.timeout(1) do
133
+ client.database.command(ping: 1) && true
134
+ end
135
+ end and true
136
+ rescue Timeout::Error, LoadError, Mongo::Error => e
137
+ client.close
138
+ $stderr.puts("MongoDB not installed or running: #{e}")
139
+ end
140
+ end
141
+
142
+ # Connect Mongoid and set up its Logger if Mongoid tests should be run.
143
+ #
144
+ # @since 6.0.1
145
+ def connect_mongoid(source)
146
+ if test_mongoid?
147
+ $stderr.puts "Mongoid #{Mongoid::VERSION}", '-'*80
148
+
149
+ if !ENV['QUIET'] == 'true'
150
+ logger = ::Logger.new($stderr)
151
+ logger.formatter = lambda { |s, d, p, m| " #{m.ansi(:faint, :cyan)}\n" }
152
+ logger.level = ::Logger::DEBUG
153
+ Mongoid.logger = logger
154
+ Mongo::Logger.logger = logger
155
+ else
156
+ Mongo::Logger.logger.level = ::Logger::WARN
157
+ end
158
+
159
+ Mongoid.connect_to(source)
160
+ end
161
+ end