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
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "elasticsearch/resources"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'elasticsearch/resources/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "elasticsearch-resources"
8
+ spec.version = Elasticsearch::Resources::VERSION
9
+ spec.authors = ["David Elner"]
10
+ spec.email = ["david@davidelner.com"]
11
+
12
+ spec.summary = %q{Access well-known Elasticsearch indexes like resources.}
13
+ spec.description = %q{Allows you to strongly-type Elasticsearch types and query them more easily.}
14
+ spec.homepage = "https://github.com/delner/elasticsearch-resources"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_dependency "i18n", "~> 0.7"
24
+ spec.add_dependency "elasticsearch", "~> 5.0"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.13"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "pry", "~> 0.10"
29
+ spec.add_development_dependency "rspec", "~> 3.0"
30
+ spec.add_development_dependency "rspec-collection_matchers", "~> 1.1"
31
+ spec.add_development_dependency "simplecov", "~> 0.12"
32
+ end
@@ -0,0 +1,35 @@
1
+ # Load library dependencies
2
+ require 'i18n'
3
+ require 'elasticsearch'
4
+
5
+ # Load classes and modules
6
+ require "elasticsearch/resources/version"
7
+ require 'elasticsearch/resources/configuration'
8
+
9
+ require 'elasticsearch/resources/configurable'
10
+ require 'elasticsearch/resources/identifiable'
11
+ require 'elasticsearch/resources/describable'
12
+ require 'elasticsearch/resources/nameable'
13
+ require 'elasticsearch/resources/clusterable'
14
+ require 'elasticsearch/resources/indexable'
15
+ require 'elasticsearch/resources/typeable'
16
+ require 'elasticsearch/resources/queryable'
17
+ require 'elasticsearch/resources/document_factory'
18
+ require 'elasticsearch/resources/response_factory'
19
+
20
+ require 'elasticsearch/resources/resource'
21
+ require 'elasticsearch/resources/document'
22
+ require 'elasticsearch/resources/type'
23
+ require 'elasticsearch/resources/index'
24
+ require 'elasticsearch/resources/cluster'
25
+
26
+ module Elasticsearch
27
+ module Resources
28
+ def self.locales_paths
29
+ Dir[File.join(File.expand_path('../resources', __FILE__), '**/locales/*.yml')]
30
+ end
31
+ end
32
+ end
33
+
34
+ # Load i18n locales
35
+ I18n.load_path += Elasticsearch::Resources.locales_paths
@@ -0,0 +1,59 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ class Cluster
4
+ include Resource
5
+ include Queryable
6
+ include Configurable
7
+ include Nameable
8
+
9
+ define_configuration class_name: Configuration::Cluster
10
+
11
+ def initialize(&block)
12
+ configure(id: self.class.configuration.id, &block)
13
+ end
14
+
15
+ def setup!
16
+ client
17
+ super
18
+ end
19
+
20
+ def client
21
+ settings.client
22
+ end
23
+
24
+ def indexes
25
+ []
26
+ end
27
+
28
+ def search(body, options = {})
29
+ params = {
30
+ body: body
31
+ }.merge(options)
32
+
33
+ query(:search, params)
34
+ end
35
+
36
+ def count(body, options = {})
37
+ params = {
38
+ body: body
39
+ }.merge(options)
40
+
41
+ query(:count, params)
42
+ end
43
+
44
+ def find_cluster
45
+ self
46
+ end
47
+
48
+ def find_index(index:)
49
+ indexes.find do |i|
50
+ i.find_index(index: index)
51
+ end
52
+ end
53
+
54
+ def find_type(index:, type:)
55
+ find_index(index: index)&.find_type(index: index, type: type)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,34 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Clusterable
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 :cluster
14
+
15
+ protected
16
+
17
+ def cluster=(cluster)
18
+ raise NullClusterError.new if cluster.nil?
19
+ @cluster = cluster
20
+ end
21
+ end
22
+
23
+ class NullClusterError < ArgumentError
24
+ def initialize
25
+ super(message)
26
+ end
27
+
28
+ def message
29
+ I18n.t('elasticsearch.resources.clusterable.null_cluster_error.message')
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,52 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Configurable
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.include(InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def configuration
11
+ @configuration ||= superclass.respond_to?(:configuration) ? superclass.configuration.dup : Configuration.new
12
+ end
13
+
14
+ protected
15
+
16
+ def define_configuration(options = {})
17
+ @configuration = configuration.tap do |c|
18
+ options.each do |name, value|
19
+ c.send("#{name.to_s}=", value) if c.respond_to?("#{name.to_s}=") && !value.nil?
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ module InstanceMethods
26
+ attr_reader :settings
27
+
28
+ def default_settings
29
+ default_expression = self.class.configuration.default
30
+ default_expression ? self.instance_exec(&default_expression) : nil
31
+ end
32
+
33
+ def configure(options = {}, &block)
34
+ @settings = default_settings&.dup || self.class.configuration.class_name&.new(**options)
35
+ settings.tap do |s|
36
+ yield(s) if block_given?
37
+ end
38
+ end
39
+ end
40
+
41
+ class Configuration
42
+ ATTRIBUTES = [:id, :class_name, :default].freeze
43
+
44
+ attr_accessor *ATTRIBUTES
45
+
46
+ def ==(obj)
47
+ ATTRIBUTES.all? { |a| obj.send(a) == self.send(a) }
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ require 'elasticsearch/resources/configuration/type'
2
+ require 'elasticsearch/resources/configuration/index'
3
+ require 'elasticsearch/resources/configuration/cluster'
4
+ require 'elasticsearch/resources/configuration/settings'
5
+
6
+ module Elasticsearch
7
+ module Resources
8
+ module Configuration
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,67 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Configuration
4
+ class Cluster
5
+ attr_reader :id, :name
6
+
7
+ def initialize(id:)
8
+ @id = id
9
+ end
10
+
11
+ def client
12
+ @client ||= Elasticsearch::Client.new(host: host)
13
+ end
14
+
15
+ def indexes
16
+ @indexes ||= default_indexes
17
+ end
18
+
19
+ def index(id)
20
+ indexes.find { |t| t.id == id.to_sym }.tap do |t|
21
+ yield(t) if block_given?
22
+ end
23
+ end
24
+
25
+ def name=(name)
26
+ raise NullNameError.new if name.nil?
27
+ @name = name.to_s
28
+ end
29
+
30
+ def host
31
+ @host ||= '127.0.0.1:9200'
32
+ end
33
+
34
+ def host=(host)
35
+ raise NullHostError.new if host.nil?
36
+ @host = host
37
+ end
38
+
39
+ class NullNameError < ArgumentError
40
+ def initialize
41
+ super(message)
42
+ end
43
+
44
+ def message
45
+ I18n.t('elasticsearch.resources.configuration.cluster.null_name_error.message')
46
+ end
47
+ end
48
+
49
+ class NullHostError < ArgumentError
50
+ def initialize
51
+ super(message)
52
+ end
53
+
54
+ def message
55
+ I18n.t('elasticsearch.resources.configuration.cluster.null_host_error.message')
56
+ end
57
+ end
58
+
59
+ protected
60
+
61
+ def default_indexes
62
+ []
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,45 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Configuration
4
+ class Index
5
+ attr_reader :id, :name, :cluster
6
+
7
+ def initialize(id:, cluster:)
8
+ @id = id
9
+ @cluster = cluster
10
+ end
11
+
12
+ def types
13
+ @types ||= default_types
14
+ end
15
+
16
+ def type(id)
17
+ types.find { |t| t.id == id.to_sym }.tap do |t|
18
+ yield(t) if block_given? && !t.nil?
19
+ end
20
+ end
21
+
22
+ def name=(name)
23
+ raise NullNameError.new if name.nil?
24
+ @name = name.to_s
25
+ end
26
+
27
+ class NullNameError < ArgumentError
28
+ def initialize
29
+ super(message)
30
+ end
31
+
32
+ def message
33
+ I18n.t('elasticsearch.resources.configuration.index.null_name_error.message')
34
+ end
35
+ end
36
+
37
+ protected
38
+
39
+ def default_types
40
+ []
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Configuration
4
+ class Settings
5
+ def clusters
6
+ @clusters ||= default_clusters
7
+ end
8
+
9
+ def cluster(id)
10
+ clusters.find { |t| t.id == id.to_sym }.tap do |t|
11
+ yield(t) if block_given?
12
+ end
13
+ end
14
+
15
+ protected
16
+
17
+ def default_clusters
18
+ [
19
+ Elasticsearch::Resources::Configuration::Cluster.new(id: :default)
20
+ ]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Configuration
4
+ class Type
5
+ attr_reader :id, :name, :index
6
+
7
+ def initialize(id:, index:)
8
+ @id = id
9
+ @index = index
10
+ end
11
+
12
+ def name=(name)
13
+ raise NullNameError.new if name.nil?
14
+ @name = name.to_s
15
+ end
16
+
17
+ class NullNameError < ArgumentError
18
+ def initialize
19
+ super(message)
20
+ end
21
+
22
+ def message
23
+ I18n.t('elasticsearch.resources.configuration.type.null_name_error.message')
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ module Elasticsearch
2
+ module Resources
3
+ module Describable
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.include(InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def attributes
11
+ @attributes ||= []
12
+ end
13
+
14
+ protected
15
+
16
+ def define_attributes(*attributes)
17
+ new_attributes = attributes.collect(&:to_sym) - self.attributes.collect(&:to_sym)
18
+ self.attributes.concat(new_attributes).tap { |a| define_attribute_helpers(new_attributes) }
19
+ end
20
+
21
+ private
22
+
23
+ def define_attribute_helpers(attributes)
24
+ attributes.each do |attribute|
25
+ self.send(:define_method, "#{attribute}") do
26
+ self.attributes[attribute.to_s]
27
+ end
28
+
29
+ self.send(:define_method, "#{attribute}=") do |value|
30
+ self.attributes[attribute.to_s] = value
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ module InstanceMethods
37
+ def attributes
38
+ @attributes ||= {}
39
+ end
40
+
41
+ protected
42
+
43
+ def attributes=(attributes = {})
44
+ @attributes = attributes.collect { |k, v| [k.to_s, v] }.to_h
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end