elasticsearch-persistence-queryable 0.1.8

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 (99) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +13 -0
  6. data/README.md +678 -0
  7. data/Rakefile +57 -0
  8. data/elasticsearch-persistence.gemspec +57 -0
  9. data/examples/music/album.rb +34 -0
  10. data/examples/music/artist.rb +50 -0
  11. data/examples/music/artists/_form.html.erb +8 -0
  12. data/examples/music/artists/artists_controller.rb +67 -0
  13. data/examples/music/artists/artists_controller_test.rb +53 -0
  14. data/examples/music/artists/index.html.erb +57 -0
  15. data/examples/music/artists/show.html.erb +51 -0
  16. data/examples/music/assets/application.css +226 -0
  17. data/examples/music/assets/autocomplete.css +48 -0
  18. data/examples/music/assets/blank_cover.png +0 -0
  19. data/examples/music/assets/form.css +113 -0
  20. data/examples/music/index_manager.rb +60 -0
  21. data/examples/music/search/index.html.erb +93 -0
  22. data/examples/music/search/search_controller.rb +41 -0
  23. data/examples/music/search/search_controller_test.rb +9 -0
  24. data/examples/music/search/search_helper.rb +15 -0
  25. data/examples/music/suggester.rb +45 -0
  26. data/examples/music/template.rb +392 -0
  27. data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.css +7 -0
  28. data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.js +6 -0
  29. data/examples/notes/.gitignore +7 -0
  30. data/examples/notes/Gemfile +28 -0
  31. data/examples/notes/README.markdown +36 -0
  32. data/examples/notes/application.rb +238 -0
  33. data/examples/notes/config.ru +7 -0
  34. data/examples/notes/test.rb +118 -0
  35. data/lib/elasticsearch/per_thread_registry.rb +53 -0
  36. data/lib/elasticsearch/persistence/client.rb +51 -0
  37. data/lib/elasticsearch/persistence/inheritence.rb +9 -0
  38. data/lib/elasticsearch/persistence/model/base.rb +95 -0
  39. data/lib/elasticsearch/persistence/model/callbacks.rb +37 -0
  40. data/lib/elasticsearch/persistence/model/errors.rb +9 -0
  41. data/lib/elasticsearch/persistence/model/find.rb +155 -0
  42. data/lib/elasticsearch/persistence/model/gateway_delegation.rb +23 -0
  43. data/lib/elasticsearch/persistence/model/hash_wrapper.rb +17 -0
  44. data/lib/elasticsearch/persistence/model/rails.rb +39 -0
  45. data/lib/elasticsearch/persistence/model/store.rb +271 -0
  46. data/lib/elasticsearch/persistence/model.rb +148 -0
  47. data/lib/elasticsearch/persistence/null_relation.rb +56 -0
  48. data/lib/elasticsearch/persistence/query_cache.rb +68 -0
  49. data/lib/elasticsearch/persistence/querying.rb +21 -0
  50. data/lib/elasticsearch/persistence/relation/delegation.rb +130 -0
  51. data/lib/elasticsearch/persistence/relation/finder_methods.rb +39 -0
  52. data/lib/elasticsearch/persistence/relation/merger.rb +179 -0
  53. data/lib/elasticsearch/persistence/relation/query_builder.rb +279 -0
  54. data/lib/elasticsearch/persistence/relation/query_methods.rb +362 -0
  55. data/lib/elasticsearch/persistence/relation/search_option_methods.rb +44 -0
  56. data/lib/elasticsearch/persistence/relation/spawn_methods.rb +61 -0
  57. data/lib/elasticsearch/persistence/relation.rb +110 -0
  58. data/lib/elasticsearch/persistence/repository/class.rb +71 -0
  59. data/lib/elasticsearch/persistence/repository/find.rb +73 -0
  60. data/lib/elasticsearch/persistence/repository/naming.rb +115 -0
  61. data/lib/elasticsearch/persistence/repository/response/results.rb +105 -0
  62. data/lib/elasticsearch/persistence/repository/search.rb +156 -0
  63. data/lib/elasticsearch/persistence/repository/serialize.rb +31 -0
  64. data/lib/elasticsearch/persistence/repository/store.rb +94 -0
  65. data/lib/elasticsearch/persistence/repository.rb +77 -0
  66. data/lib/elasticsearch/persistence/scoping/default.rb +137 -0
  67. data/lib/elasticsearch/persistence/scoping/named.rb +70 -0
  68. data/lib/elasticsearch/persistence/scoping.rb +52 -0
  69. data/lib/elasticsearch/persistence/version.rb +5 -0
  70. data/lib/elasticsearch/persistence.rb +157 -0
  71. data/lib/elasticsearch/rails_compatibility.rb +17 -0
  72. data/lib/rails/generators/elasticsearch/model/model_generator.rb +21 -0
  73. data/lib/rails/generators/elasticsearch/model/templates/model.rb.tt +9 -0
  74. data/lib/rails/generators/elasticsearch_generator.rb +2 -0
  75. data/lib/rails/instrumentation/railtie.rb +31 -0
  76. data/lib/rails/instrumentation.rb +10 -0
  77. data/test/integration/model/model_basic_test.rb +157 -0
  78. data/test/integration/repository/custom_class_test.rb +85 -0
  79. data/test/integration/repository/customized_class_test.rb +82 -0
  80. data/test/integration/repository/default_class_test.rb +114 -0
  81. data/test/integration/repository/virtus_model_test.rb +114 -0
  82. data/test/test_helper.rb +53 -0
  83. data/test/unit/model_base_test.rb +48 -0
  84. data/test/unit/model_find_test.rb +148 -0
  85. data/test/unit/model_gateway_test.rb +99 -0
  86. data/test/unit/model_rails_test.rb +88 -0
  87. data/test/unit/model_store_test.rb +514 -0
  88. data/test/unit/persistence_test.rb +32 -0
  89. data/test/unit/repository_class_test.rb +51 -0
  90. data/test/unit/repository_client_test.rb +32 -0
  91. data/test/unit/repository_find_test.rb +388 -0
  92. data/test/unit/repository_indexing_test.rb +37 -0
  93. data/test/unit/repository_module_test.rb +146 -0
  94. data/test/unit/repository_naming_test.rb +146 -0
  95. data/test/unit/repository_response_results_test.rb +98 -0
  96. data/test/unit/repository_search_test.rb +117 -0
  97. data/test/unit/repository_serialize_test.rb +57 -0
  98. data/test/unit/repository_store_test.rb +303 -0
  99. metadata +487 -0
@@ -0,0 +1,31 @@
1
+ module Elasticsearch
2
+ module Persistence
3
+ module Instrumentation
4
+
5
+ class Railtie < ::Rails::Railtie
6
+ include ActionView::Helpers::NumberHelper
7
+ def time_diff(start, finish)
8
+ begin
9
+ ((finish.to_time - start.to_time) * 1000).to_s(:rounded, precision: 5, strip_insignificant_zeros: true)
10
+ rescue
11
+ number_with_precision((finish.to_time - start.to_time) * 1000, precision: 5, strip_insignificant_zeros: true)
12
+ end
13
+ end
14
+
15
+ ActiveSupport::Notifications.subscribe 'query.elasticsearch' do |name, start, finish, id, payload|
16
+ ::Rails.logger.debug([" #{payload[:name]}".bright, "(#{time_diff(start,finish)}ms)",payload[:query]].join(" ").color(:yellow))
17
+ end
18
+
19
+ ActiveSupport::Notifications.subscribe 'cache.query.elasticsearch' do |name, start, finish, id, payload|
20
+ ::Rails.logger.debug([" #{payload[:name]}".bright, "CACHE".color(:mediumpurple).bright ,"(#{time_diff(start,finish)}ms)", payload[:query]].join(" ").color(:yellow))
21
+ end
22
+
23
+ initializer 'elasticsearch_persistence.set_defaults' do
24
+ config.elasticsearch_cache_store = :redis_store
25
+ config.elasticsearch_expire_cache_in = 15.minutes
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ require 'elasticsearch/rails/instrumentation/railtie'
2
+
3
+ module Elasticsearch
4
+ module Persistence
5
+
6
+ module Instrumentation
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,157 @@
1
+ require 'test_helper'
2
+
3
+ require 'elasticsearch/persistence/model'
4
+
5
+ module Elasticsearch
6
+ module Persistence
7
+ class PersistenceModelBasicIntegrationTest < Elasticsearch::Test::IntegrationTestCase
8
+
9
+ class ::Person
10
+ include Elasticsearch::Persistence::Model
11
+
12
+ settings index: { number_of_shards: 1 }
13
+
14
+ attribute :name, String,
15
+ mapping: { fields: {
16
+ name: { type: 'string', analyzer: 'snowball' },
17
+ raw: { type: 'string', analyzer: 'keyword' }
18
+ } }
19
+
20
+ attribute :birthday, Date
21
+ attribute :department, String
22
+ attribute :salary, Integer
23
+ attribute :admin, Boolean, default: false
24
+
25
+ validates :name, presence: true
26
+ end
27
+
28
+ context "A basic persistence model" do
29
+ setup do
30
+ Person.create_index! force: true
31
+ end
32
+
33
+ should "save the object with custom ID" do
34
+ person = Person.new id: 1, name: 'Number One'
35
+ person.save
36
+
37
+ document = Person.find(1)
38
+ assert_not_nil document
39
+ assert_equal 'Number One', document.name
40
+ end
41
+
42
+ should "create the object with custom ID" do
43
+ person = Person.create id: 1, name: 'Number One'
44
+
45
+ document = Person.find(1)
46
+ assert_not_nil document
47
+ assert_equal 'Number One', document.name
48
+ end
49
+
50
+ should "save and find the object" do
51
+ person = Person.new name: 'John Smith', birthday: Date.parse('1970-01-01')
52
+ person.save
53
+
54
+ assert_not_nil person.id
55
+ document = Person.find(person.id)
56
+
57
+ assert_instance_of Person, document
58
+ assert_equal 'John Smith', document.name
59
+ assert_equal 'John Smith', Person.find(person.id).name
60
+
61
+ assert_not_nil Elasticsearch::Persistence.client.get index: 'people', type: 'person', id: person.id
62
+ end
63
+
64
+ should "delete the object" do
65
+ person = Person.create name: 'John Smith', birthday: Date.parse('1970-01-01')
66
+
67
+ person.destroy
68
+ assert person.frozen?
69
+
70
+ assert_raise Elasticsearch::Transport::Transport::Errors::NotFound do
71
+ Elasticsearch::Persistence.client.get index: 'people', type: 'person', id: person.id
72
+ end
73
+ end
74
+
75
+ should "update an object attribute" do
76
+ person = Person.create name: 'John Smith'
77
+
78
+ person.update name: 'UPDATED'
79
+
80
+ assert_equal 'UPDATED', person.name
81
+ assert_equal 'UPDATED', Person.find(person.id).name
82
+ end
83
+
84
+ should "increment an object attribute" do
85
+ person = Person.create name: 'John Smith', salary: 1_000
86
+
87
+ person.increment :salary
88
+
89
+ assert_equal 1_001, person.salary
90
+ assert_equal 1_001, Person.find(person.id).salary
91
+ end
92
+
93
+ should "update the object timestamp" do
94
+ person = Person.create name: 'John Smith'
95
+ updated_at = person.updated_at
96
+
97
+ sleep 1
98
+ person.touch
99
+
100
+ assert person.updated_at > updated_at, [person.updated_at, updated_at].inspect
101
+
102
+ found = Person.find(person.id)
103
+ assert found.updated_at > updated_at, [found.updated_at, updated_at].inspect
104
+ end
105
+
106
+ should "find instances by search" do
107
+ Person.create name: 'John Smith'
108
+ Person.create name: 'Mary Smith'
109
+ Person.gateway.refresh_index!
110
+
111
+ people = Person.search query: { match: { name: 'smith' } },
112
+ highlight: { fields: { name: {} } }
113
+
114
+ assert_equal 2, people.total
115
+ assert_equal 2, people.size
116
+
117
+ assert people.map_with_hit { |o,h| h._score }.all? { |s| s > 0 }
118
+
119
+ assert_not_nil people.first.hit
120
+ assert_match /smith/i, people.first.hit.highlight['name'].first
121
+ end
122
+
123
+ should "find instances in batches" do
124
+ 50.times { |i| Person.create name: "John #{i+1}" }
125
+ Person.gateway.refresh_index!
126
+
127
+ @batches = 0
128
+ @results = []
129
+
130
+ Person.find_in_batches(_source_include: 'name') do |batch|
131
+ @batches += 1
132
+ @results += batch.map(&:name)
133
+ end
134
+
135
+ assert_equal 3, @batches
136
+ assert_equal 50, @results.size
137
+ assert_contains @results, 'John 1'
138
+ end
139
+
140
+ should "find each instance" do
141
+ 50.times { |i| Person.create name: "John #{i+1}" }
142
+ Person.gateway.refresh_index!
143
+
144
+ @results = []
145
+
146
+ Person.find_each(_source_include: 'name') do |person|
147
+ @results << person.name
148
+ end
149
+
150
+ assert_equal 50, @results.size
151
+ assert_contains @results, 'John 1'
152
+ end
153
+ end
154
+
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,85 @@
1
+ require 'test_helper'
2
+
3
+ module Elasticsearch
4
+ module Persistence
5
+ class RepositoryCustomClassIntegrationTest < Elasticsearch::Test::IntegrationTestCase
6
+
7
+ class ::MyNote
8
+ attr_reader :attributes
9
+
10
+ def initialize(attributes={})
11
+ @attributes = Hashie::Mash.new(attributes)
12
+ end
13
+
14
+ def method_missing(method_name, *arguments, &block)
15
+ attributes.respond_to?(method_name) ? attributes.__send__(method_name, *arguments, &block) : super
16
+ end
17
+
18
+ def respond_to?(method_name, include_private=false)
19
+ attributes.respond_to?(method_name) || super
20
+ end
21
+
22
+ def to_hash
23
+ @attributes
24
+ end
25
+ end
26
+
27
+ context "A custom repository class" do
28
+ setup do
29
+ class ::MyNotesRepository
30
+ include Elasticsearch::Persistence::Repository
31
+
32
+ klass MyNote
33
+
34
+ settings number_of_shards: 1 do
35
+ mapping do
36
+ indexes :title, analyzer: 'snowball'
37
+ end
38
+ end
39
+
40
+ create_index!
41
+
42
+ def deserialize(document)
43
+ klass.new document.merge(document['_source'])
44
+ end
45
+ end
46
+
47
+ @repository = MyNotesRepository.new
48
+
49
+ @repository.client.cluster.health wait_for_status: 'yellow'
50
+ end
51
+
52
+ should "save the object under a correct index and type" do
53
+ @repository.save MyNote.new(id: '1', title: 'Test')
54
+ result = @repository.find(1)
55
+
56
+ assert_instance_of MyNote, result
57
+ assert_equal 'Test', result.title
58
+
59
+ assert_not_nil Elasticsearch::Persistence.client.get index: 'my_notes_repository',
60
+ type: 'my_note',
61
+ id: '1'
62
+ end
63
+
64
+ should "delete the object" do
65
+ note = MyNote.new id: 1, title: 'Test'
66
+ @repository.save note
67
+
68
+ assert_not_nil @repository.find(1)
69
+
70
+ @repository.delete(note)
71
+ assert_raise(Elasticsearch::Persistence::Repository::DocumentNotFound) { @repository.find(1) }
72
+ end
73
+
74
+ should "retrieve the object via a search query" do
75
+ note = MyNote.new title: 'Testing'
76
+ @repository.save note, refresh: true
77
+
78
+ results = @repository.search query: { match: { title: 'Test' } }
79
+ assert_equal 'Testing', results.first.title
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,82 @@
1
+ require 'test_helper'
2
+
3
+ module Elasticsearch
4
+ module Persistence
5
+ class RepositoryCustomizedClassIntegrationTest < Elasticsearch::Test::IntegrationTestCase
6
+
7
+ module ::My
8
+ class Note
9
+ attr_reader :attributes
10
+
11
+ def initialize(attributes={})
12
+ @attributes = attributes
13
+ end
14
+
15
+ def to_hash
16
+ @attributes
17
+ end
18
+ end
19
+ end
20
+
21
+ context "A custom repository class" do
22
+ setup do
23
+ @repository = Elasticsearch::Persistence::Repository.new do
24
+ index 'my_notes'
25
+ type 'my_note'
26
+ klass My::Note
27
+
28
+ settings number_of_shards: 1 do
29
+ mapping do
30
+ indexes :title, analyzer: 'snowball'
31
+ end
32
+ end
33
+
34
+ create_index!
35
+ end
36
+
37
+ @repository.client.cluster.health wait_for_status: 'yellow'
38
+ end
39
+
40
+ should "save the object under a correct index and type" do
41
+ @repository.save My::Note.new(id: '1', title: 'Test')
42
+
43
+ assert_instance_of My::Note, @repository.find(1)
44
+ assert_not_nil Elasticsearch::Persistence.client.get index: 'my_notes', type: 'my_note', id: '1'
45
+ end
46
+
47
+ should "update the document" do
48
+ @repository.save Note.new(id: 1, title: 'Test')
49
+
50
+ @repository.update 1, doc: { title: 'UPDATED' }
51
+ assert_equal 'UPDATED', @repository.find(1).attributes['title']
52
+ end
53
+
54
+ should "update the document with a script" do
55
+ @repository.save Note.new(id: 1, title: 'Test')
56
+
57
+ @repository.update 1, script: 'ctx._source.title = "UPDATED"'
58
+ assert_equal 'UPDATED', @repository.find(1).attributes['title']
59
+ end
60
+
61
+ should "delete the object" do
62
+ note = My::Note.new id: 1, title: 'Test'
63
+ @repository.save note
64
+
65
+ assert_not_nil @repository.find(1)
66
+
67
+ @repository.delete(note)
68
+ assert_raise(Elasticsearch::Persistence::Repository::DocumentNotFound) { @repository.find(1) }
69
+ end
70
+
71
+ should "create the index with correct mapping" do
72
+ note = My::Note.new title: 'Testing'
73
+ @repository.save note, refresh: true
74
+
75
+ results = @repository.search query: { match: { title: 'Test' } }
76
+ assert_equal 'Testing', results.first.attributes['title']
77
+ end
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,114 @@
1
+ require 'test_helper'
2
+
3
+ module Elasticsearch
4
+ module Persistence
5
+ class RepositoryDefaultClassIntegrationTest < Elasticsearch::Test::IntegrationTestCase
6
+
7
+ class ::Note
8
+ attr_reader :attributes
9
+
10
+ def initialize(attributes={})
11
+ @attributes = attributes
12
+ end
13
+
14
+ def to_hash
15
+ @attributes
16
+ end
17
+ end
18
+
19
+ context "The default repository class" do
20
+ setup do
21
+ @repository = Elasticsearch::Persistence::Repository.new
22
+ @repository.client.cluster.health wait_for_status: 'yellow'
23
+ end
24
+
25
+ should "save the object with a custom ID and find it" do
26
+ @repository.save Note.new(id: '1', title: 'Test')
27
+
28
+ assert_equal 'Test', @repository.find(1).attributes['title']
29
+ end
30
+
31
+ should "save the object with an auto-generated ID and find it" do
32
+ response = @repository.save Note.new(title: 'Test')
33
+
34
+ assert_equal 'Test', @repository.find(response['_id']).attributes['title']
35
+ end
36
+
37
+ should "update the document" do
38
+ @repository.save Note.new(id: 1, title: 'Test')
39
+
40
+ @repository.update 1, type: 'note', doc: { title: 'UPDATED' }
41
+ assert_equal 'UPDATED', @repository.find(1).attributes['title']
42
+ end
43
+
44
+ should "update the document with a script" do
45
+ @repository.save Note.new(id: 1, title: 'Test')
46
+
47
+ @repository.update 1, type: 'note', script: 'ctx._source.title = "UPDATED"'
48
+ assert_equal 'UPDATED', @repository.find(1).attributes['title']
49
+ end
50
+
51
+ should "save the document with an upsert" do
52
+ @repository.update 1, type: 'note', script: 'ctx._source.clicks += 1', upsert: { clicks: 1 }
53
+ assert_equal 1, @repository.find(1).attributes['clicks']
54
+ end
55
+
56
+ should "delete an object" do
57
+ note = Note.new(id: '1', title: 'Test')
58
+
59
+ @repository.save(note)
60
+ assert_not_nil @repository.find(1)
61
+ @repository.delete(note)
62
+ assert_raise(Elasticsearch::Persistence::Repository::DocumentNotFound) { @repository.find(1) }
63
+ end
64
+
65
+ should "find multiple objects" do
66
+ (1..5).each { |i| @repository.save Note.new(id: i, title: "Test #{i}") }
67
+
68
+ assert_equal 5, @repository.find(1, 2, 3, 4, 5).size
69
+ assert_equal 5, @repository.find([1, 2, 3, 4, 5]).size
70
+ end
71
+
72
+ should "pass options to save and find" do
73
+ note = Note.new(id: '1', title: 'Test')
74
+ @repository.save note, routing: 'ABC'
75
+
76
+ assert_raise Elasticsearch::Persistence::Repository::DocumentNotFound do
77
+ @repository.find(1, routing: 'DEF')
78
+ end
79
+
80
+ assert_nothing_raised do
81
+ note = @repository.find(1, routing: 'ABC')
82
+ assert_instance_of Note, note
83
+ end
84
+ end
85
+
86
+ should "find notes with full text search" do
87
+ @repository.save Note.new(title: 'Test')
88
+ @repository.save Note.new(title: 'Test Test')
89
+ @repository.save Note.new(title: 'Crust')
90
+ @repository.client.indices.refresh index: @repository.index_name
91
+
92
+ results = @repository.search 'test'
93
+ assert_equal 2, results.size
94
+
95
+ results = @repository.search query: { match: { title: 'Test' } }
96
+ assert_equal 2, results.size
97
+ end
98
+
99
+ should "count notes" do
100
+ @repository.save Note.new(title: 'Test')
101
+ @repository.client.indices.refresh index: @repository.index_name
102
+ assert_equal 1, @repository.count
103
+ end
104
+
105
+ should "save and find a plain hash" do
106
+ @repository.save id: 1, title: 'Hash'
107
+ result = @repository.find(1)
108
+ assert_equal 'Hash', result['_source']['title']
109
+ end
110
+ end
111
+
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,114 @@
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'], script: 'ctx._source.views += count', params: { count: 3 }
106
+
107
+ page = @repository.find(response['_id'])
108
+ assert_equal 3, page.views
109
+ end
110
+ end
111
+
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,53 @@
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 } if ENV['SERVER']
10
+
11
+ if defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
12
+ require 'test-unit'
13
+ require 'mocha/test_unit'
14
+ else
15
+ require 'minitest/autorun'
16
+ require 'mocha/mini_test'
17
+ end
18
+
19
+ require 'shoulda-context'
20
+
21
+ require 'turn' unless ENV["TM_FILEPATH"] || ENV["NOTURN"] || defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
22
+
23
+ require 'ansi'
24
+ require 'oj'
25
+
26
+ require 'elasticsearch/extensions/test/cluster'
27
+ require 'elasticsearch/extensions/test/startup_shutdown'
28
+
29
+ require 'elasticsearch/persistence'
30
+
31
+ module Elasticsearch
32
+ module Test
33
+ class IntegrationTestCase < ::Test::Unit::TestCase
34
+ extend Elasticsearch::Extensions::Test::StartupShutdown
35
+
36
+ startup { Elasticsearch::Extensions::Test::Cluster.start(nodes: 1) if ENV['SERVER'] and not Elasticsearch::Extensions::Test::Cluster.running? }
37
+ shutdown { Elasticsearch::Extensions::Test::Cluster.stop if ENV['SERVER'] && started? }
38
+ context "IntegrationTest" do; should "noop on Ruby 1.8" do; end; end if RUBY_1_8
39
+
40
+ def setup
41
+ tracer = ::Logger.new(STDERR)
42
+ tracer.formatter = lambda { |s, d, p, m| "#{m.gsub(/^.*$/) { |n| ' ' + n }.ansi(:faint)}\n" }
43
+ Elasticsearch::Persistence.client = Elasticsearch::Client.new \
44
+ host: "localhost:#{(ENV['TEST_CLUSTER_PORT'] || 9250)}",
45
+ tracer: (ENV['QUIET'] ? nil : tracer)
46
+ end
47
+
48
+ def teardown
49
+ Elasticsearch::Persistence.client.indices.delete index: '_all'
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,48 @@
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
+ m = DummyBaseModel.new id: 1
24
+ assert_equal 1, m.id
25
+
26
+ m = DummyBaseModel.new 'id' => 2
27
+ assert_equal 2, m.id
28
+ end
29
+
30
+ should "set the ID using setter method" do
31
+ m = DummyBaseModel.new id: 1
32
+ assert_equal 1, m.id
33
+
34
+ m.id = 2
35
+ assert_equal 2, m.id
36
+ end
37
+
38
+ should "have ID in attributes" do
39
+ m = DummyBaseModel.new id: 1, name: 'Test'
40
+ assert_equal 1, m.attributes[:id]
41
+ end
42
+
43
+ should "have the customized inspect method" do
44
+ m = DummyBaseModel.new name: 'Test'
45
+ assert_match /name\: "Test"/, m.inspect
46
+ end
47
+ end
48
+ end