elasticsearch-persistence 5.0.2 → 6.1.1

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.
Files changed (81) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +2 -0
  3. data/Gemfile +9 -0
  4. data/README.md +206 -338
  5. data/Rakefile +15 -12
  6. data/elasticsearch-persistence.gemspec +6 -7
  7. data/examples/notes/application.rb +3 -4
  8. data/lib/elasticsearch/persistence.rb +2 -110
  9. data/lib/elasticsearch/persistence/repository.rb +212 -53
  10. data/lib/elasticsearch/persistence/repository/dsl.rb +94 -0
  11. data/lib/elasticsearch/persistence/repository/find.rb +27 -10
  12. data/lib/elasticsearch/persistence/repository/response/results.rb +21 -8
  13. data/lib/elasticsearch/persistence/repository/search.rb +30 -18
  14. data/lib/elasticsearch/persistence/repository/serialize.rb +65 -7
  15. data/lib/elasticsearch/persistence/repository/store.rb +38 -44
  16. data/lib/elasticsearch/persistence/version.rb +1 -1
  17. data/spec/repository/find_spec.rb +179 -0
  18. data/spec/repository/response/results_spec.rb +128 -0
  19. data/spec/repository/search_spec.rb +181 -0
  20. data/spec/repository/serialize_spec.rb +53 -0
  21. data/spec/repository/store_spec.rb +327 -0
  22. data/spec/repository_spec.rb +723 -0
  23. data/spec/spec_helper.rb +32 -0
  24. metadata +26 -104
  25. data/examples/music/album.rb +0 -54
  26. data/examples/music/artist.rb +0 -70
  27. data/examples/music/artists/_form.html.erb +0 -8
  28. data/examples/music/artists/artists_controller.rb +0 -67
  29. data/examples/music/artists/artists_controller_test.rb +0 -53
  30. data/examples/music/artists/index.html.erb +0 -60
  31. data/examples/music/artists/show.html.erb +0 -54
  32. data/examples/music/assets/application.css +0 -257
  33. data/examples/music/assets/autocomplete.css +0 -48
  34. data/examples/music/assets/blank_artist.png +0 -0
  35. data/examples/music/assets/blank_cover.png +0 -0
  36. data/examples/music/assets/form.css +0 -113
  37. data/examples/music/index_manager.rb +0 -73
  38. data/examples/music/search/index.html.erb +0 -95
  39. data/examples/music/search/search_controller.rb +0 -41
  40. data/examples/music/search/search_controller_test.rb +0 -12
  41. data/examples/music/search/search_helper.rb +0 -15
  42. data/examples/music/suggester.rb +0 -69
  43. data/examples/music/template.rb +0 -430
  44. data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.css +0 -7
  45. data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.js +0 -6
  46. data/examples/music/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  47. data/lib/elasticsearch/persistence/client.rb +0 -51
  48. data/lib/elasticsearch/persistence/model.rb +0 -135
  49. data/lib/elasticsearch/persistence/model/base.rb +0 -87
  50. data/lib/elasticsearch/persistence/model/errors.rb +0 -8
  51. data/lib/elasticsearch/persistence/model/find.rb +0 -180
  52. data/lib/elasticsearch/persistence/model/rails.rb +0 -47
  53. data/lib/elasticsearch/persistence/model/store.rb +0 -254
  54. data/lib/elasticsearch/persistence/model/utils.rb +0 -0
  55. data/lib/elasticsearch/persistence/repository/class.rb +0 -71
  56. data/lib/elasticsearch/persistence/repository/naming.rb +0 -115
  57. data/lib/rails/generators/elasticsearch/model/model_generator.rb +0 -21
  58. data/lib/rails/generators/elasticsearch/model/templates/model.rb.tt +0 -9
  59. data/lib/rails/generators/elasticsearch_generator.rb +0 -2
  60. data/test/integration/model/model_basic_test.rb +0 -233
  61. data/test/integration/repository/custom_class_test.rb +0 -85
  62. data/test/integration/repository/customized_class_test.rb +0 -82
  63. data/test/integration/repository/default_class_test.rb +0 -116
  64. data/test/integration/repository/virtus_model_test.rb +0 -118
  65. data/test/test_helper.rb +0 -55
  66. data/test/unit/model_base_test.rb +0 -72
  67. data/test/unit/model_find_test.rb +0 -153
  68. data/test/unit/model_gateway_test.rb +0 -101
  69. data/test/unit/model_rails_test.rb +0 -112
  70. data/test/unit/model_store_test.rb +0 -576
  71. data/test/unit/persistence_test.rb +0 -32
  72. data/test/unit/repository_class_test.rb +0 -51
  73. data/test/unit/repository_client_test.rb +0 -32
  74. data/test/unit/repository_find_test.rb +0 -388
  75. data/test/unit/repository_indexing_test.rb +0 -37
  76. data/test/unit/repository_module_test.rb +0 -146
  77. data/test/unit/repository_naming_test.rb +0 -146
  78. data/test/unit/repository_response_results_test.rb +0 -98
  79. data/test/unit/repository_search_test.rb +0 -117
  80. data/test/unit/repository_serialize_test.rb +0 -57
  81. data/test/unit/repository_store_test.rb +0 -303
@@ -1,118 +0,0 @@
1
- require 'test_helper'
2
-
3
- require 'virtus'
4
-
5
- module Elasticsearch
6
- module Persistence
7
- class RepositoryWithVirtusIntegrationTest < Elasticsearch::Test::IntegrationTestCase
8
-
9
- class ::Page
10
- include Virtus.model
11
-
12
- attribute :id, String, writer: :private
13
- attribute :title, String
14
- attribute :views, Integer, default: 0
15
- attribute :published, Boolean, default: false
16
- attribute :slug, String, default: lambda { |page, attr| page.title.downcase.gsub(' ', '-') }
17
-
18
- def set_id(id)
19
- self.id = id
20
- end
21
- end
22
-
23
- context "The repository with a Virtus model" do
24
- setup do
25
- @repository = Elasticsearch::Persistence::Repository.new do
26
- index :pages
27
- klass Page
28
-
29
- def deserialize(document)
30
- page = klass.new document['_source']
31
- page.set_id document['_id']
32
- page
33
- end
34
- end
35
- end
36
-
37
- should "save and find the object" do
38
- page = Page.new title: 'Test Page'
39
-
40
- response = @repository.save page
41
- id = response['_id']
42
-
43
- result = @repository.find(id)
44
-
45
- assert_instance_of Page, result
46
- assert_equal 'Test Page', result.title
47
- assert_equal 0, result.views
48
-
49
- assert_not_nil Elasticsearch::Persistence.client.get index: 'pages',
50
- type: 'page',
51
- id: id
52
- end
53
-
54
- should "update the object with a partial document" do
55
- response = @repository.save Page.new(title: 'Test')
56
- id = response['_id']
57
-
58
- page = @repository.find(id)
59
-
60
- assert_equal 'Test', page.title
61
-
62
- @repository.update page.id, doc: { title: 'UPDATE' }
63
-
64
- page = @repository.find(id)
65
- assert_equal 'UPDATE', page.title
66
- end
67
-
68
- should "update the object with a Hash" do
69
- response = @repository.save Page.new(title: 'Test')
70
- id = response['_id']
71
-
72
- page = @repository.find(id)
73
-
74
- assert_equal 'Test', page.title
75
-
76
- @repository.update id: page.id, title: 'UPDATE'
77
-
78
- page = @repository.find(id)
79
- assert_equal 'UPDATE', page.title
80
- end
81
-
82
- should "update the object with a script" do
83
- response = @repository.save Page.new(title: 'Test Page')
84
- id = response['_id']
85
-
86
- page = @repository.find(id)
87
-
88
- assert_not_nil page.id
89
- assert_equal 0, page.views
90
-
91
- @repository.update page.id, script: 'ctx._source.views += 1'
92
-
93
- page = @repository.find(id)
94
- assert_equal 1, page.views
95
-
96
- @repository.update id: page.id, script: 'ctx._source.views += 1'
97
-
98
- page = @repository.find(id)
99
- assert_equal 2, page.views
100
- end
101
-
102
- should "update the object with a script and params" do
103
- response = @repository.save Page.new(title: 'Test Page')
104
-
105
- @repository.update id: response['_id'],
106
- script: {
107
- inline: 'ctx._source.views += params.count',
108
- params: { count: 3 }
109
- }
110
-
111
- page = @repository.find(response['_id'])
112
- assert_equal 3, page.views
113
- end
114
- end
115
-
116
- end
117
- end
118
- end
@@ -1,55 +0,0 @@
1
- RUBY_1_8 = defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
2
-
3
- exit(0) if RUBY_1_8
4
-
5
- $LOAD_PATH.unshift File.expand_path('../../../elasticsearch-model/lib', __FILE__) if File.exists? File.expand_path('../../../elasticsearch-model/lib', __FILE__)
6
-
7
- require 'simplecov' and SimpleCov.start { add_filter "/test|test_/" } if ENV["COVERAGE"]
8
-
9
- # Register `at_exit` handler for integration tests shutdown.
10
- # MUST be called before requiring `test/unit`.
11
- at_exit { Elasticsearch::Test::IntegrationTestCase.__run_at_exit_hooks } if ENV['SERVER']
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 'elasticsearch/extensions/test/cluster'
29
- require 'elasticsearch/extensions/test/startup_shutdown'
30
-
31
- require 'elasticsearch/persistence'
32
-
33
- module Elasticsearch
34
- module Test
35
- class IntegrationTestCase < ::Test::Unit::TestCase
36
- extend Elasticsearch::Extensions::Test::StartupShutdown
37
-
38
- startup { Elasticsearch::Extensions::Test::Cluster.start(nodes: 1) if ENV['SERVER'] and not Elasticsearch::Extensions::Test::Cluster.running? }
39
- shutdown { Elasticsearch::Extensions::Test::Cluster.stop if ENV['SERVER'] && started? }
40
- context "IntegrationTest" do; should "noop on Ruby 1.8" do; end; end if RUBY_1_8
41
-
42
- def setup
43
- tracer = ::Logger.new(STDERR)
44
- tracer.formatter = lambda { |s, d, p, m| "#{m.gsub(/^.*$/) { |n| ' ' + n }.ansi(:faint)}\n" }
45
- Elasticsearch::Persistence.client = Elasticsearch::Client.new \
46
- host: "localhost:#{(ENV['TEST_CLUSTER_PORT'] || 9250)}",
47
- tracer: (ENV['QUIET'] ? nil : tracer)
48
- end
49
-
50
- def teardown
51
- Elasticsearch::Persistence.client.indices.delete index: '_all'
52
- end
53
- end
54
- end
55
- end
@@ -1,72 +0,0 @@
1
- require 'test_helper'
2
-
3
- require 'elasticsearch/persistence/model'
4
- require 'elasticsearch/persistence/model/rails'
5
-
6
- class Elasticsearch::Persistence::ModelBaseTest < Test::Unit::TestCase
7
- context "The model" do
8
- setup do
9
- class DummyBaseModel
10
- include Elasticsearch::Persistence::Model
11
-
12
- attribute :name, String
13
- end
14
- end
15
-
16
- should "respond to id, _id, _index, _type and _version" do
17
- model = DummyBaseModel.new
18
-
19
- [:id, :_id, :_index, :_type, :_version].each { |method| assert_respond_to model, method }
20
- end
21
-
22
- should "set the ID from attributes during initialization" do
23
- model = DummyBaseModel.new id: 1
24
- assert_equal 1, model.id
25
-
26
- model = DummyBaseModel.new 'id' => 2
27
- assert_equal 2, model.id
28
- end
29
-
30
- should "set the ID using setter method" do
31
- model = DummyBaseModel.new id: 1
32
- assert_equal 1, model.id
33
-
34
- model.id = 2
35
- assert_equal 2, model.id
36
- end
37
-
38
- should "have ID in attributes" do
39
- model = DummyBaseModel.new id: 1, name: 'Test'
40
- assert_equal 1, model.attributes[:id]
41
- end
42
-
43
- should "have the customized inspect method" do
44
- model = DummyBaseModel.new name: 'Test'
45
- assert_match /name\: "Test"/, model.inspect
46
- end
47
-
48
- context "with custom document_type" do
49
- setup do
50
- @model = DummyBaseModel
51
- @gateway = mock()
52
- @mapping = mock()
53
- @model.stubs(:gateway).returns(@gateway)
54
- @gateway.stubs(:mapping).returns(@mapping)
55
- @document_type = 'dummybase'
56
- end
57
-
58
- should "forward the argument to mapping" do
59
- @gateway.expects(:document_type).with(@document_type).once
60
- @mapping.expects(:type=).with(@document_type).once
61
- @model.document_type @document_type
62
- end
63
-
64
- should "return the value from the gateway" do
65
- @gateway.expects(:document_type).once.returns(@document_type)
66
- @mapping.expects(:type=).never
67
- returned_type = @model.document_type
68
- assert_equal @document_type, returned_type
69
- end
70
- end
71
- end
72
- end
@@ -1,153 +0,0 @@
1
- require 'test_helper'
2
-
3
- require 'active_model'
4
- require 'virtus'
5
-
6
- require 'elasticsearch/persistence/model/errors'
7
- require 'elasticsearch/persistence/model/find'
8
-
9
- class Elasticsearch::Persistence::ModelFindTest < Test::Unit::TestCase
10
- context "The model find module," do
11
-
12
- class DummyFindModel
13
- include ActiveModel::Naming
14
- include ActiveModel::Conversion
15
- include ActiveModel::Serialization
16
- include ActiveModel::Serializers::JSON
17
- include ActiveModel::Validations
18
-
19
- include Virtus.model
20
-
21
- extend Elasticsearch::Persistence::Model::Find::ClassMethods
22
-
23
- extend ActiveModel::Callbacks
24
- define_model_callbacks :create, :save, :update, :destroy
25
- define_model_callbacks :find, :touch, only: :after
26
-
27
- attribute :title, String
28
- attribute :count, Integer, default: 0
29
- attribute :created_at, DateTime, default: lambda { |o,a| Time.now.utc }
30
- attribute :updated_at, DateTime, default: lambda { |o,a| Time.now.utc }
31
- end
32
-
33
- setup do
34
- @gateway = stub(client: stub(), index_name: 'foo', document_type: 'bar')
35
- DummyFindModel.stubs(:gateway).returns(@gateway)
36
-
37
- DummyFindModel.stubs(:index_name).returns('foo')
38
- DummyFindModel.stubs(:document_type).returns('bar')
39
-
40
- @response = MultiJson.load <<-JSON
41
- {
42
- "took": 14,
43
- "timed_out": false,
44
- "_shards": {
45
- "total": 5,
46
- "successful": 5,
47
- "failed": 0
48
- },
49
- "hits": {
50
- "total": 1,
51
- "max_score": 1.0,
52
- "hits": [
53
- {
54
- "_index": "dummy",
55
- "_type": "dummy",
56
- "_id": "abc123",
57
- "_score": 1.0,
58
- "_source": {
59
- "name": "TEST"
60
- }
61
- }
62
- ]
63
- }
64
- }
65
- JSON
66
- end
67
-
68
- should "find all records" do
69
- DummyFindModel
70
- .stubs(:search)
71
- .with({ query: { match_all: {} }, size: 10_000 }, {})
72
- .returns(@response)
73
-
74
- DummyFindModel.all
75
- end
76
-
77
- should "pass options when finding all records" do
78
- DummyFindModel
79
- .expects(:search)
80
- .with({ query: { match: { title: 'test' } }, size: 10_000 }, { routing: 'abc123' })
81
- .returns(@response)
82
-
83
- DummyFindModel.all( { query: { match: { title: 'test' } } }, { routing: 'abc123' } )
84
- end
85
-
86
- context "finding via scroll" do
87
- setup do
88
- @gateway
89
- .expects(:deserialize)
90
- .returns('_source' => {'foo' => 'bar'})
91
- .at_least_once
92
-
93
- # 1. Initial batch of documents and the scroll_id
94
- @gateway.client
95
- .expects(:search)
96
- .with do |arguments|
97
- assert_equal 'foo', arguments[:index]
98
- assert_equal 'bar', arguments[:type]
99
- true
100
- end
101
- .returns(MultiJson.load('{"_scroll_id":"abc123==", "hits":{"hits":[{"_source":{"foo":"bar_1"}}]}}'))
102
-
103
- # 2. Second batch of documents and the scroll_id
104
- # 3. Last, empty batch of documents
105
- @gateway.client
106
- .expects(:scroll)
107
- .twice
108
- .returns(MultiJson.load('{"_scroll_id":"abc456==", "hits":{"hits":[{"_source":{"foo":"bar_2"}}]}}'))
109
- .then
110
- .returns(MultiJson.load('{"_scroll_id":"abc789==", "hits":{"hits":[]}}'))
111
- end
112
-
113
- should "find all records in batches" do
114
- @doc = nil
115
- result = DummyFindModel.find_in_batches { |batch| @doc = batch.first['_source']['foo'] }
116
-
117
- assert_equal 'abc789==', result
118
- assert_equal 'bar', @doc
119
- end
120
-
121
- should "return an Enumerator for find in batches" do
122
- @doc = nil
123
- assert_nothing_raised do
124
- e = DummyFindModel.find_in_batches
125
- assert_instance_of Enumerator, e
126
-
127
- e.each { |batch| @doc = batch.first['_source']['foo'] }
128
- assert_equal 'bar', @doc
129
- end
130
- end
131
-
132
- should "find each" do
133
- @doc = nil
134
- result = DummyFindModel.find_each { |doc| @doc = doc['_source']['foo'] }
135
-
136
- assert_equal 'abc789==', result
137
- assert_equal 'bar', @doc
138
- end
139
-
140
- should "return an Enumerator for find each" do
141
- @doc = nil
142
- assert_nothing_raised do
143
- e = DummyFindModel.find_each
144
- assert_instance_of Enumerator, e
145
-
146
- e.each { |doc| @doc = doc['_source']['foo'] }
147
- assert_equal 'bar', @doc
148
- end
149
- end
150
- end
151
-
152
- end
153
- end
@@ -1,101 +0,0 @@
1
- require 'test_helper'
2
-
3
- require 'elasticsearch/persistence/model'
4
- require 'elasticsearch/persistence/model/rails'
5
-
6
- class Elasticsearch::Persistence::ModelGatewayTest < Test::Unit::TestCase
7
- context "The model gateway" do
8
- setup do
9
- class DummyGatewayModel
10
- include Elasticsearch::Persistence::Model
11
- end
12
- end
13
-
14
- teardown do
15
- Elasticsearch::Persistence::ModelGatewayTest.__send__ :remove_const, :DummyGatewayModel \
16
- rescue NameError; nil
17
- end
18
-
19
- should "be accessible" do
20
- assert_instance_of Elasticsearch::Persistence::Repository::Class, DummyGatewayModel.gateway
21
-
22
- $a = 0
23
- DummyGatewayModel.gateway { $a += 1 }
24
- assert_equal 1, $a
25
-
26
- @b = 0
27
- def run!; DummyGatewayModel.gateway { |g| @b += 1 }; end
28
- run!
29
- assert_equal 1, @b
30
-
31
- assert_equal DummyGatewayModel, DummyGatewayModel.gateway.klass
32
- end
33
-
34
- should "define common attributes" do
35
- d = DummyGatewayModel.new
36
-
37
- assert_respond_to d, :updated_at
38
- assert_respond_to d, :created_at
39
- end
40
-
41
- should "allow to configure settings" do
42
- DummyGatewayModel.settings(number_of_shards: 1)
43
-
44
- assert_equal 1, DummyGatewayModel.settings.to_hash[:number_of_shards]
45
- end
46
-
47
- should "allow to configure mappings" do
48
- DummyGatewayModel.mapping { indexes :name, analyzer: 'snowball' }
49
-
50
- assert_equal 'snowball',
51
- DummyGatewayModel.mapping.to_hash[:dummy_gateway_model][:properties][:name][:analyzer]
52
- end
53
-
54
- should "configure the mapping via attribute" do
55
- DummyGatewayModel.attribute :name, String, mapping: { analyzer: 'snowball' }
56
-
57
- assert_respond_to DummyGatewayModel, :name
58
- assert_equal 'snowball',
59
- DummyGatewayModel.mapping.to_hash[:dummy_gateway_model][:properties][:name][:analyzer]
60
- end
61
-
62
- should "configure the mapping via an attribute block" do
63
- DummyGatewayModel.attribute :name, String do
64
- indexes :name, analyzer: 'custom'
65
- end
66
-
67
- assert_respond_to DummyGatewayModel, :name
68
- assert_equal 'custom',
69
- DummyGatewayModel.mapping.to_hash[:dummy_gateway_model][:properties][:name][:analyzer]
70
- end
71
-
72
- should "properly look up types for classes" do
73
- assert_equal 'text', Elasticsearch::Persistence::Model::Utils::lookup_type(String)
74
- assert_equal 'integer', Elasticsearch::Persistence::Model::Utils::lookup_type(Integer)
75
- assert_equal 'float', Elasticsearch::Persistence::Model::Utils::lookup_type(Float)
76
- assert_equal 'date', Elasticsearch::Persistence::Model::Utils::lookup_type(Date)
77
- assert_equal 'boolean', Elasticsearch::Persistence::Model::Utils::lookup_type(Virtus::Attribute::Boolean)
78
- end
79
-
80
- should "remove IDs from hash when serializing" do
81
- assert_equal( {foo: 'bar'}, DummyGatewayModel.gateway.serialize(id: '123', foo: 'bar') )
82
- end
83
-
84
- should "set IDs from hash when deserializing" do
85
- assert_equal 'abc123', DummyGatewayModel.gateway.deserialize('_id' => 'abc123', '_source' => {}).id
86
- end
87
-
88
- should "set @persisted variable from hash when deserializing" do
89
- assert DummyGatewayModel.gateway.deserialize('_id' => 'abc123', '_source' => {}).instance_variable_get(:@persisted)
90
- end
91
-
92
- should "allow accessing the raw _source" do
93
- assert_equal 'bar', DummyGatewayModel.gateway.deserialize('_source' => { 'foo' => 'bar' })._source['foo']
94
- end
95
-
96
- should "allow to access the raw hit from results as Hashie::Mash" do
97
- assert_equal 0.42, DummyGatewayModel.gateway.deserialize('_score' => 0.42, '_source' => {}).hit._score
98
- end
99
-
100
- end
101
- end