elasticsearch-persistence 5.0.2 → 6.1.1

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