elasticsearch-resources 0.1.0

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 (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +201 -0
  7. data/README.md +276 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/elasticsearch-resources.gemspec +32 -0
  12. data/lib/elasticsearch/resources.rb +35 -0
  13. data/lib/elasticsearch/resources/cluster.rb +59 -0
  14. data/lib/elasticsearch/resources/clusterable.rb +34 -0
  15. data/lib/elasticsearch/resources/configurable.rb +52 -0
  16. data/lib/elasticsearch/resources/configuration.rb +11 -0
  17. data/lib/elasticsearch/resources/configuration/cluster.rb +67 -0
  18. data/lib/elasticsearch/resources/configuration/index.rb +45 -0
  19. data/lib/elasticsearch/resources/configuration/settings.rb +25 -0
  20. data/lib/elasticsearch/resources/configuration/type.rb +29 -0
  21. data/lib/elasticsearch/resources/describable.rb +49 -0
  22. data/lib/elasticsearch/resources/document.rb +73 -0
  23. data/lib/elasticsearch/resources/document_factory.rb +49 -0
  24. data/lib/elasticsearch/resources/identifiable.rb +34 -0
  25. data/lib/elasticsearch/resources/index.rb +108 -0
  26. data/lib/elasticsearch/resources/indexable.rb +34 -0
  27. data/lib/elasticsearch/resources/locales/en.yml +29 -0
  28. data/lib/elasticsearch/resources/nameable.rb +28 -0
  29. data/lib/elasticsearch/resources/queryable.rb +36 -0
  30. data/lib/elasticsearch/resources/resource.rb +39 -0
  31. data/lib/elasticsearch/resources/response_factory.rb +49 -0
  32. data/lib/elasticsearch/resources/type.rb +99 -0
  33. data/lib/elasticsearch/resources/typeable.rb +34 -0
  34. data/lib/elasticsearch/resources/version.rb +5 -0
  35. metadata +188 -0
@@ -0,0 +1,73 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ class Document
4
+ include Resource
5
+ include Queryable
6
+ include Typeable
7
+ include Identifiable
8
+ include Describable
9
+
10
+ def initialize(id:, attributes: {}, type:)
11
+ self.type = type
12
+ self.id = id
13
+ self.attributes = attributes
14
+ end
15
+
16
+ def cluster
17
+ index.cluster
18
+ end
19
+
20
+ def index
21
+ type.index
22
+ end
23
+
24
+ def client
25
+ type.client
26
+ end
27
+
28
+ def query(action, options = {})
29
+ params = {
30
+ index: index.name,
31
+ type: type.name,
32
+ id: id
33
+ }.merge(options)
34
+
35
+ super(action, **params)
36
+ end
37
+
38
+ def create(options = {})
39
+ params = {
40
+ body: attributes
41
+ }.merge(options)
42
+
43
+ query(:create, params)
44
+ end
45
+
46
+ def update(options = {})
47
+ params = {
48
+ body: attributes
49
+ }.merge(options)
50
+
51
+ query(:update, params)
52
+ end
53
+
54
+ [:exists?, :delete, :get].each do |action|
55
+ define_method action do |options = {}|
56
+ query(action, options)
57
+ end
58
+ end
59
+
60
+ def find_cluster
61
+ self.cluster
62
+ end
63
+
64
+ def find_index(index: nil)
65
+ self.index
66
+ end
67
+
68
+ def find_type(index: nil, type: nil)
69
+ self.type
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,49 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ class DocumentFactory
4
+ attr_reader :content, :resources
5
+
6
+ def initialize(content:, resources: {})
7
+ @content = content
8
+ @resources = resources
9
+ end
10
+
11
+ def build
12
+ type = get_type
13
+ type.document_class.new(
14
+ type: type,
15
+ id: content['_id'],
16
+ attributes: content['_source']
17
+ )
18
+ end
19
+
20
+ def get_type
21
+ resources[:type] || build_type
22
+ end
23
+
24
+ def build_type
25
+ Elasticsearch::Resources::Type.new(index: get_index) do |type|
26
+ type.name = content['_type']
27
+ end
28
+ end
29
+
30
+ def get_index
31
+ resources[:index] || build_index
32
+ end
33
+
34
+ def build_index
35
+ Elasticsearch::Resources::Index.new(cluster: get_cluster) do |index|
36
+ index.name = content['_index']
37
+ end
38
+ end
39
+
40
+ def get_cluster
41
+ resources[:cluster] || build_cluster
42
+ end
43
+
44
+ def build_cluster
45
+ Elasticsearch::Resources::Cluster.new
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Identifiable
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.include(InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ end
11
+
12
+ module InstanceMethods
13
+ attr_reader :id
14
+
15
+ protected
16
+
17
+ def id=(id)
18
+ raise NullIdError.new if id.nil?
19
+ @id = id.to_s
20
+ end
21
+ end
22
+
23
+ class NullIdError < ArgumentError
24
+ def initialize
25
+ super(message)
26
+ end
27
+
28
+ def message
29
+ I18n.t('elasticsearch.resources.identifiable.null_id_error.message')
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,108 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ class Index
4
+ include Resource
5
+ include Queryable
6
+ include Configurable
7
+ include Clusterable
8
+ include Nameable
9
+
10
+ define_configuration \
11
+ class_name: Configuration::Index,
12
+ default: -> { cluster.settings.index(self.class.configuration.id) }
13
+
14
+ def initialize(cluster:, &block)
15
+ self.cluster = cluster
16
+ configure(id: self.class.configuration.id, cluster: cluster.settings, &block)
17
+ end
18
+
19
+ def setup!
20
+ unless exists?
21
+ create
22
+ super
23
+ end
24
+ end
25
+
26
+ def teardown!
27
+ if exists?
28
+ delete
29
+ super
30
+ end
31
+ end
32
+
33
+ def client
34
+ cluster.client
35
+ end
36
+
37
+ def name
38
+ settings.name || super
39
+ end
40
+
41
+ def types
42
+ []
43
+ end
44
+
45
+ def query_index(action, options = {})
46
+ params = {
47
+ index: name
48
+ }.merge(options)
49
+
50
+ client.indices.send(action, **params)
51
+ end
52
+
53
+ def query(action, options = {})
54
+ params = {
55
+ index: name
56
+ }.merge(options)
57
+
58
+ super(action, **params)
59
+ end
60
+
61
+ def exists?
62
+ query_index(:exists?)
63
+ end
64
+
65
+ def create
66
+ query_index(:create)
67
+ end
68
+
69
+ def put_mapping(options = {})
70
+ query_index(:put_mapping, options)
71
+ end
72
+
73
+ def delete
74
+ query_index(:delete)
75
+ end
76
+
77
+ def search(body, options = {})
78
+ params = {
79
+ body: body
80
+ }.merge(options)
81
+
82
+ query(:search, params)
83
+ end
84
+
85
+ def count(body, options = {})
86
+ params = {
87
+ body: body
88
+ }.merge(options)
89
+
90
+ query(:count, params)
91
+ end
92
+
93
+ def find_cluster
94
+ self.cluster
95
+ end
96
+
97
+ def find_index(index: nil)
98
+ matches_name?(index) ? self : nil
99
+ end
100
+
101
+ def find_type(index: nil, type:)
102
+ types.find do |t|
103
+ t.find_type(type: type)
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,34 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Indexable
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.include(InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ end
11
+
12
+ module InstanceMethods
13
+ attr_reader :index
14
+
15
+ protected
16
+
17
+ def index=(index)
18
+ raise NullIndexError.new if index.nil?
19
+ @index = index
20
+ end
21
+ end
22
+
23
+ class NullIndexError < ArgumentError
24
+ def initialize
25
+ super(message)
26
+ end
27
+
28
+ def message
29
+ I18n.t('elasticsearch.resources.indexable.null_index_error.message')
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,29 @@
1
+ en:
2
+ elasticsearch:
3
+ resources:
4
+ configuration:
5
+ cluster:
6
+ null_name_error:
7
+ message: 'Cluster cannot be assigned a nil name!'
8
+ null_host_error:
9
+ message: 'Cluster cannot be assigned a nil host!'
10
+ index:
11
+ null_name_error:
12
+ message: 'Index cannot be assigned a nil name!'
13
+ type:
14
+ null_name_error:
15
+ message: 'Type cannot be assigned a nil name!'
16
+ identifiable:
17
+ null_id_error:
18
+ message: "ID cannot be assigned a nil value!"
19
+ indexable:
20
+ null_index_error:
21
+ message: "Index cannot be nil!"
22
+ queryable:
23
+ client:
24
+ not_implemented_error: 'This resource does not implement #client.'
25
+ null_client_error:
26
+ message: "No client set. Cannot query!"
27
+ typeable:
28
+ null_type_error:
29
+ message: "Type cannot be nil!"
@@ -0,0 +1,28 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Nameable
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.include(InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ attr_reader :default_name
11
+
12
+ def define_default_name(name)
13
+ @default_name = name&.to_s
14
+ end
15
+ end
16
+
17
+ module InstanceMethods
18
+ def name
19
+ self.class.default_name
20
+ end
21
+
22
+ def matches_name?(name)
23
+ name.to_s == self.name.to_s
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Queryable
4
+ def self.included(base)
5
+ base.include(Resource)
6
+ base.extend(ClassMethods)
7
+ base.include(InstanceMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ end
12
+
13
+ module InstanceMethods
14
+ def client
15
+ raise NotImplementedError.new(I18n.t('elasticsearch.resources.queryable.client.not_implemented_error'))
16
+ end
17
+
18
+ def query(action, params = {})
19
+ raise NullClientError.new if client.nil?
20
+ response = client.send(action, **params)
21
+ ResponseFactory.new(resource: self, action: action, response: response).build
22
+ end
23
+ end
24
+
25
+ class NullClientError < ArgumentError
26
+ def initialize
27
+ super(message)
28
+ end
29
+
30
+ def message
31
+ I18n.t('elasticsearch.resources.queryable.null_client_error.message')
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,39 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Resource
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.include(InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ end
11
+
12
+ module InstanceMethods
13
+ def find_cluster
14
+ nil
15
+ end
16
+
17
+ def find_index(index: nil)
18
+ nil
19
+ end
20
+
21
+ def find_type(index: nil, type: nil)
22
+ nil
23
+ end
24
+
25
+ def setup!
26
+ nil
27
+ end
28
+
29
+ def populate!
30
+ nil
31
+ end
32
+
33
+ def teardown!
34
+ nil
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,49 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ class ResponseFactory
4
+ attr_reader :resource, :action, :response
5
+
6
+ def initialize(resource:, action:, response:)
7
+ @resource = resource
8
+ @action = action
9
+ @response = response
10
+ end
11
+
12
+ def build
13
+ case action
14
+ when :get
15
+ build_get
16
+ when :search
17
+ build_search
18
+ else
19
+ response
20
+ end
21
+ end
22
+
23
+ def build_get
24
+ DocumentFactory.new(
25
+ content: response,
26
+ resources: resources_for(response)
27
+ ).build
28
+ end
29
+
30
+ def build_search
31
+ raw_documents = response['hits']['hits']
32
+ raw_documents.collect do |raw_document|
33
+ DocumentFactory.new(
34
+ content: raw_document,
35
+ resources: resources_for(raw_document)
36
+ ).build
37
+ end
38
+ end
39
+
40
+ def resources_for(content)
41
+ {
42
+ cluster: resource.find_cluster,
43
+ index: resource.find_index(index: content['_index']),
44
+ type: resource.find_type(index: content['_index'], type: content['_type'])
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end