esse 0.0.3 → 0.1.2

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/exec/esse +3 -1
  3. data/lib/esse/backend/index/aliases.rb +8 -4
  4. data/lib/esse/backend/index/close.rb +6 -5
  5. data/lib/esse/backend/index/create.rb +20 -9
  6. data/lib/esse/backend/index/delete.rb +15 -14
  7. data/lib/esse/backend/index/documents.rb +2 -2
  8. data/lib/esse/backend/index/existance.rb +2 -3
  9. data/lib/esse/backend/index/open.rb +6 -5
  10. data/lib/esse/backend/index/refresh.rb +43 -0
  11. data/lib/esse/backend/index/reset.rb +33 -0
  12. data/lib/esse/backend/index/update.rb +37 -15
  13. data/lib/esse/backend/index.rb +18 -4
  14. data/lib/esse/backend/index_type/documents.rb +53 -42
  15. data/lib/esse/backend/index_type.rb +7 -2
  16. data/lib/esse/cli/event_listener.rb +87 -0
  17. data/lib/esse/cli/generate.rb +9 -4
  18. data/lib/esse/cli/index/base_operation.rb +76 -0
  19. data/lib/esse/cli/index/close.rb +26 -0
  20. data/lib/esse/cli/index/create.rb +26 -0
  21. data/lib/esse/cli/index/delete.rb +26 -0
  22. data/lib/esse/cli/index/import.rb +26 -0
  23. data/lib/esse/cli/index/open.rb +26 -0
  24. data/lib/esse/cli/index/reset.rb +26 -0
  25. data/lib/esse/cli/index/update_aliases.rb +32 -0
  26. data/lib/esse/cli/index/update_mapping.rb +33 -0
  27. data/lib/esse/cli/index/update_settings.rb +26 -0
  28. data/lib/esse/cli/index.rb +78 -2
  29. data/lib/esse/cli/templates/config.rb.erb +20 -0
  30. data/lib/esse/cli/templates/index.rb.erb +76 -11
  31. data/lib/esse/cli/templates/type_collection.rb.erb +41 -0
  32. data/lib/esse/cli/templates/{mappings.json → type_mappings.json} +0 -0
  33. data/lib/esse/cli/templates/type_serializer.rb.erb +23 -0
  34. data/lib/esse/cli.rb +75 -3
  35. data/lib/esse/cluster.rb +22 -6
  36. data/lib/esse/config.rb +39 -5
  37. data/lib/esse/core.rb +18 -36
  38. data/lib/esse/errors.rb +47 -0
  39. data/lib/esse/events/bus.rb +103 -0
  40. data/lib/esse/events/event.rb +64 -0
  41. data/lib/esse/events/publisher.rb +119 -0
  42. data/lib/esse/events.rb +49 -0
  43. data/lib/esse/index/backend.rb +2 -1
  44. data/lib/esse/index/base.rb +4 -6
  45. data/lib/esse/index/mappings.rb +2 -3
  46. data/lib/esse/index/settings.rb +7 -8
  47. data/lib/esse/index.rb +2 -1
  48. data/lib/esse/index_mapping.rb +2 -2
  49. data/lib/esse/index_setting.rb +8 -4
  50. data/lib/esse/index_type/actions.rb +2 -1
  51. data/lib/esse/index_type/backend.rb +2 -1
  52. data/lib/esse/index_type/mappings.rb +2 -2
  53. data/lib/esse/index_type.rb +6 -1
  54. data/lib/esse/logging.rb +19 -0
  55. data/lib/esse/object_document_mapper.rb +96 -0
  56. data/lib/esse/primitives/hash_utils.rb +40 -0
  57. data/lib/esse/primitives/hstring.rb +4 -3
  58. data/lib/esse/primitives/output.rb +64 -0
  59. data/lib/esse/primitives.rb +1 -0
  60. data/lib/esse/template_loader.rb +1 -1
  61. data/lib/esse/version.rb +1 -1
  62. data/lib/esse.rb +12 -3
  63. metadata +124 -21
  64. data/.gitignore +0 -12
  65. data/.rubocop.yml +0 -128
  66. data/CHANGELOG.md +0 -0
  67. data/Gemfile +0 -7
  68. data/Gemfile.lock +0 -60
  69. data/LICENSE.txt +0 -21
  70. data/README.md +0 -52
  71. data/Rakefile +0 -4
  72. data/bin/console +0 -22
  73. data/bin/setup +0 -8
  74. data/esse.gemspec +0 -39
  75. data/lib/esse/cli/templates/serializer.rb.erb +0 -14
  76. data/lib/esse/index_type/serializer.rb +0 -87
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Esse
4
+ class Error < StandardError
5
+ end
6
+
7
+ module Events
8
+ class UnregisteredEventError < ::Esse::Error
9
+ def initialize(object_or_event_id)
10
+ case object_or_event_id
11
+ when String, Symbol
12
+ super("You are trying to publish an unregistered event: `#{object_or_event_id}`")
13
+ else
14
+ super('You are trying to publish an unregistered event')
15
+ end
16
+ end
17
+ end
18
+
19
+ class InvalidSubscriberError < ::Esse::Error
20
+ # @api private
21
+ def initialize(object_or_event_id)
22
+ case object_or_event_id
23
+ when String, Symbol
24
+ super("you are trying to subscribe to an event: `#{object_or_event_id}` that has not been registered")
25
+ else
26
+ super('you try use subscriber object that will never be executed')
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ module CLI
33
+ class Error < ::Esse::Error
34
+ def initialize(msg = nil, **message_attributes)
35
+ if message_attributes.any?
36
+ msg = format(msg, **message_attributes)
37
+ end
38
+ super(msg)
39
+ end
40
+ end
41
+
42
+ class InvalidOption < Error
43
+ end
44
+ end
45
+
46
+ # Elasticsearch::Transport::Transport::Errors::NotFound
47
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Esse
4
+ module Events
5
+ # Event bus
6
+ #
7
+ # An event bus stores listeners (callbacks) and events
8
+ #
9
+ # @api private
10
+ class Bus
11
+ # @return [Hash] A hash with events registered within a bus
12
+ attr_reader :events
13
+
14
+ # @return [Hash] A hash with event listeners registered within a bus
15
+ attr_reader :listeners
16
+
17
+ # Initialize a new event bus
18
+ #
19
+ # @param [Hash] events A hash with events
20
+ # @param [Hash] listeners A hash with listeners
21
+ #
22
+ # @api private
23
+ # @idea
24
+ # Hash is thread-safe in practice because CRuby runs
25
+ # threads one at a time and does not do context
26
+ # switching during the execution of C functions
27
+ # However, in case of jRuby or other ruby interpreters,
28
+ # this assumption may not be true. In that case, we should
29
+ # use a different data structure. I think we should use
30
+ # a Concurrent::Hash or Concurrent::Map object from
31
+ # concurrent-ruby
32
+ # @see https://github.com/ruby-concurrency/concurrent-ruby
33
+ def initialize(events: {}, listeners: Hash.new { |h, k| h[k] = [] })
34
+ @listeners = listeners
35
+ @events = events
36
+ end
37
+
38
+ # @api private
39
+ def publish(event_id, payload)
40
+ process(event_id, payload) do |event, listener|
41
+ listener.call(event)
42
+ end
43
+ end
44
+
45
+ # @api private
46
+ def attach(listener)
47
+ events.each do |id, event|
48
+ method_name = event.listener_method
49
+ next unless listener.respond_to?(method_name)
50
+
51
+ listeners[id] << listener.method(method_name)
52
+ end
53
+ end
54
+
55
+ # @api private
56
+ def detach(listener)
57
+ listeners.each do |id, arr|
58
+ arr.each do |func|
59
+ listeners[id].delete(func) if func.receiver == listener
60
+ end
61
+ end
62
+ end
63
+
64
+ # @api private
65
+ def subscribe(event_id, &block)
66
+ listeners[event_id] << block
67
+ self
68
+ end
69
+
70
+ # @api private
71
+ def subscribed?(listener)
72
+ listeners.values.any? { |value| value.any? { |func| func == listener } } || (
73
+ methods = events.values.map(&:listener_method).select(&listener.method(:respond_to?)).map(&listener.method(:method))
74
+ methods && listeners.values.any? { |value| (methods & value).size > 0 }
75
+ )
76
+ end
77
+
78
+ # @api private
79
+ def can_handle?(object_or_event_id)
80
+ case object_or_event_id
81
+ when String, Symbol
82
+ events.key?(object_or_event_id)
83
+ else
84
+ events
85
+ .values
86
+ .map(&:listener_method)
87
+ .any?(&object_or_event_id.method(:respond_to?))
88
+ end
89
+ end
90
+
91
+ protected
92
+
93
+ # @api private
94
+ def process(event_id, payload)
95
+ listeners[event_id].each do |listener|
96
+ event = events[event_id].payload(payload)
97
+
98
+ yield(event, listener)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Esse
4
+ module Events
5
+ class Event
6
+ attr_reader :id
7
+
8
+ # Initialize a new event
9
+ #
10
+ # @param [Symbol, String] id The event identifier
11
+ # @param [Hash] payload
12
+ #
13
+ # @return [Event]
14
+ #
15
+ # @api private
16
+ def initialize(id, payload = {})
17
+ @id = id
18
+ @payload = payload
19
+ end
20
+
21
+ # Get data from the payload
22
+ #
23
+ # @param [String,Symbol] name
24
+ #
25
+ # @api public
26
+ def [](name)
27
+ @payload.fetch(name)
28
+ end
29
+
30
+ # Coerce an event to a hash
31
+ #
32
+ # @return [Hash]
33
+ #
34
+ # @api public
35
+ def to_h
36
+ @payload
37
+ end
38
+ alias_method :to_hash, :to_h
39
+
40
+ # Get or set a payload
41
+ #
42
+ # @overload
43
+ # @return [Hash] payload
44
+ #
45
+ # @overload payload(data)
46
+ # @param [Hash] data A new payload
47
+ # @return [Event] A copy of the event with the provided payload
48
+ #
49
+ # @api public
50
+ def payload(data = nil)
51
+ if data
52
+ self.class.new(id, @payload.merge(data))
53
+ else
54
+ @payload
55
+ end
56
+ end
57
+
58
+ # @api private
59
+ def listener_method
60
+ @listener_method ||= Hstring.new("on_#{id}").underscore.to_sym
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'event'
4
+ require_relative 'bus'
5
+
6
+ module Esse
7
+ module Events
8
+ module Publisher
9
+ def self.included(klass)
10
+ klass.extend(ClassMethods)
11
+ end
12
+
13
+ # Class interface for publishers
14
+ #
15
+ # @api public
16
+ module ClassMethods
17
+ # Register a new event type
18
+ #
19
+ # @param [Symbol,String] event_id The event identifier
20
+ # @param [Hash] payload Optional default payload
21
+ #
22
+ # @return [self]
23
+ #
24
+ # @api public
25
+ def register_event(event_id, payload = {})
26
+ __bus__.events[event_id] = Event.new(event_id, payload)
27
+ self
28
+ end
29
+
30
+ # Publish an event
31
+ #
32
+ # @param [String] event_id The event identifier
33
+ # @param [Hash] payload An optional payload
34
+ # @raise [Esse::Events::UnregisteredEventError] if the event is not registered
35
+ #
36
+ # @api public
37
+ def publish(event_id, payload = {})
38
+ if __bus__.can_handle?(event_id)
39
+ __bus__.publish(event_id, payload)
40
+ self
41
+ else
42
+ raise UnregisteredEventError, event_id
43
+ end
44
+ end
45
+
46
+ # Publish an event with extra runtime information to the payload
47
+ #
48
+ # @param [String] event_id The event identifier
49
+ # @param [Hash] payload An optional payload
50
+ # @raise [Esse::Events::UnregisteredEventError] if the event is not registered
51
+ #
52
+ # @api public
53
+ def instrument(event_id, payload = {}, &block)
54
+ publish_event = false # ensure block is also called on error
55
+ raise(UnregisteredEventError, event_id) unless __bus__.can_handle?(event_id)
56
+
57
+ payload[:__started_at__] = Time.now
58
+ block.call(payload).tap { publish_event = true }
59
+ ensure
60
+ if publish_event
61
+ payload[:runtime] ||= Time.now - payload.delete(:__started_at__) if payload[:__started_at__]
62
+ __bus__.publish(event_id, payload)
63
+ end
64
+ end
65
+
66
+ # Subscribe to events.
67
+ #
68
+ # @param [Symbol,String,Object] object_or_event_id The event identifier or a listener object
69
+ # @param [Hash] filter_hash An optional event filter
70
+ #
71
+ # @raise [Esse::Events::InvalidSubscriberError] if the subscriber is not registered
72
+ # @return [Object] self
73
+ #
74
+ #
75
+ # @api public
76
+ def subscribe(object_or_event_id, &block)
77
+ if __bus__.can_handle?(object_or_event_id)
78
+ if block
79
+ __bus__.subscribe(object_or_event_id, &block)
80
+ else
81
+ __bus__.attach(object_or_event_id)
82
+ end
83
+
84
+ self
85
+ else
86
+ raise InvalidSubscriberError, object_or_event_id
87
+ end
88
+ end
89
+
90
+ # Unsubscribe a listener
91
+ #
92
+ # @param [Object] listener The listener object
93
+ #
94
+ # @return [self]
95
+ #
96
+ # @api public
97
+ def unsubscribe(listener)
98
+ __bus__.detach(listener)
99
+ end
100
+
101
+ # Return true if a given listener has been subscribed to any event
102
+ #
103
+ # @api public
104
+ def subscribed?(listener)
105
+ __bus__.subscribed?(listener)
106
+ end
107
+
108
+ # Internal event bus
109
+ #
110
+ # @return [Bus]
111
+ #
112
+ # @api private
113
+ def __bus__
114
+ @__bus__ ||= Bus.new
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'events/publisher'
4
+
5
+ module Esse
6
+ # Extension used for classes that can pub/sub events
7
+ #
8
+ # Examples:
9
+ #
10
+ # # Publish an event
11
+ # Esse::Events.publish('elasticsearch.create_index', { definition: {index_name: 'my_index'} })
12
+ # # Subscribe to an event
13
+ # Esse::Events.subscribe('elasticsearch.create_index') do |event|
14
+ # puts event.payload
15
+ # end
16
+ #
17
+ # # Publish an event using instrumentation
18
+ # Esse::Events.instrument('elasticsearch.create_index') do |payload|
19
+ # payload[:definition] = {index_name: 'my_index'}
20
+ # # Some slow action
21
+ # end
22
+ # Esse::Events.subscribe('elasticsearch.create_index') do |event|
23
+ # puts event.payload[:runtime] # Extra information about the amount of time the action took
24
+ # end
25
+ #
26
+ # # Attach a listener to the event bus
27
+ # class MyEventListener
28
+ # def on_elasticsearch_create_index(event)
29
+ # puts event.payload
30
+ # end
31
+ # end
32
+ # listener = MyEventListener.new
33
+ # Esse::Events.attach(listener)
34
+ # # Dettash the listener
35
+ # Esse::Events.detach(listener)
36
+ #
37
+ #
38
+ module Events
39
+ include Publisher
40
+
41
+ register_event 'elasticsearch.close'
42
+ register_event 'elasticsearch.open'
43
+ register_event 'elasticsearch.create_index'
44
+ register_event 'elasticsearch.delete_index'
45
+ register_event 'elasticsearch.update_mapping'
46
+ register_event 'elasticsearch.update_settings'
47
+ register_event 'elasticsearch.update_aliases'
48
+ end
49
+ end
@@ -3,9 +3,10 @@
3
3
  module Esse
4
4
  class Index
5
5
  module ClassMethods
6
- def backend
6
+ def elasticsearch
7
7
  Esse::Backend::Index.new(self)
8
8
  end
9
+ alias_method :backend, :elasticsearch
9
10
  end
10
11
 
11
12
  extend ClassMethods
@@ -3,12 +3,10 @@
3
3
  module Esse
4
4
  class Index
5
5
  module ClassMethods
6
- attr_reader :cluster_id
7
-
8
6
  # Define a Index method on the given module that calls the Index
9
7
  # method on the receiver. This is how the Esse::Index() method is
10
8
  # defined, and allows you to define Index() methods on other modules,
11
- # making it easier to have custom index settings for all indexes under
9
+ # making it easier to have custom index settings for all indices under
12
10
  # a namespace. Example:
13
11
  #
14
12
  # module V1
@@ -35,7 +33,7 @@ module Esse
35
33
  #
36
34
  # Example:
37
35
  # # Using a custom cluster
38
- # Esse.config.clusters(:v1).client = Elasticsearch::Client.new
36
+ # Esse.config.cluster(:v1).client = Elasticsearch::Client.new
39
37
  # class UsersIndex < Esse::Index(:v1)
40
38
  # end
41
39
  #
@@ -92,12 +90,12 @@ module Esse
92
90
  def cluster
93
91
  unless Esse.config.cluster_ids.include?(cluster_id)
94
92
  raise NotImplementedError, <<~MSG
95
- There is no cluster configured for this index. Use `Esse.config.clusters(cluster_id) { ... }' define the elasticsearch
93
+ There is no cluster configured for this index. Use `Esse.config.cluster(cluster_id) { ... }' define the elasticsearch
96
94
  client connection.
97
95
  MSG
98
96
  end
99
97
 
100
- Esse.synchronize { Esse.config.clusters(cluster_id) }
98
+ Esse.synchronize { Esse.config.cluster(cluster_id) }
101
99
  end
102
100
 
103
101
  def inspect
@@ -7,7 +7,6 @@
7
7
  module Esse
8
8
  class Index
9
9
  module ClassMethods
10
-
11
10
  # This is the actually content that will be passed through the ES api
12
11
  def mappings_hash
13
12
  { Esse::MAPPING_ROOT_KEY => (index_mapping || type_mapping) }
@@ -16,9 +15,9 @@ module Esse
16
15
  # This method is only used to define mapping
17
16
  def mappings(hash = {}, &block)
18
17
  @mapping = Esse::IndexMapping.new(body: hash, paths: template_dirs)
19
- return unless block_given?
18
+ return unless block
20
19
 
21
- @mapping.define_singleton_method(:as_json, &block)
20
+ @mapping.define_singleton_method(:to_h, &block)
22
21
  end
23
22
 
24
23
  private
@@ -4,16 +4,15 @@ module Esse
4
4
  # https://github.com/elastic/elasticsearch-ruby/blob/master/elasticsearch-api/lib/elasticsearch/api/actions/indices/put_settings.rb
5
5
  class Index
6
6
  module ClassMethods
7
-
8
- def settings_hash(cluster_settings: true)
9
- hash = cluster_settings ? cluster.index_settings.merge(setting.body) : setting.body
7
+ def settings_hash
8
+ hash = setting.body
10
9
  { Esse::SETTING_ROOT_KEY => (hash.key?(Esse::SETTING_ROOT_KEY) ? hash[Esse::SETTING_ROOT_KEY] : hash) }
11
10
  end
12
11
 
13
12
  # Define /_settings definition by each index.
14
13
  #
15
14
  # +hash+: The body of the request includes the updated settings.
16
- # +block+: Overwrite default :as_json from IndexSetting instance
15
+ # +block+: Overwrite default :to_h from IndexSetting instance
17
16
  #
18
17
  # Example:
19
18
  #
@@ -29,16 +28,16 @@ module Esse
29
28
  # end
30
29
  # end
31
30
  def settings(hash = {}, &block)
32
- @setting = Esse::IndexSetting.new(body: hash, paths: template_dirs, globals: cluster.index_settings)
33
- return unless block_given?
31
+ @setting = Esse::IndexSetting.new(body: hash, paths: template_dirs, globals: -> { cluster.index_settings })
32
+ return unless block
34
33
 
35
- @setting.define_singleton_method(:as_json, &block)
34
+ @setting.define_singleton_method(:to_h, &block)
36
35
  end
37
36
 
38
37
  private
39
38
 
40
39
  def setting
41
- @setting ||= Esse::IndexSetting.new(paths: template_dirs, globals: cluster.index_settings)
40
+ @setting ||= Esse::IndexSetting.new(paths: template_dirs, globals: -> { cluster.index_settings })
42
41
  end
43
42
  end
44
43
 
data/lib/esse/index.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'core'
3
+ require_relative 'object_document_mapper'
4
4
 
5
5
  module Esse
6
6
  class Index
@@ -13,6 +13,7 @@ module Esse
13
13
  require_relative 'index/mappings'
14
14
  require_relative 'index/descendants'
15
15
  require_relative 'index/backend'
16
+ extend ObjectDocumentMapper
16
17
 
17
18
  @cluster_id = nil
18
19
 
@@ -12,14 +12,14 @@ module Esse
12
12
 
13
13
  # This method will be overwrited when passing a block during the
14
14
  # mapping defination
15
- def as_json
15
+ def to_h
16
16
  return @mappings unless @mappings.empty?
17
17
 
18
18
  from_template || @mappings
19
19
  end
20
20
 
21
21
  def body
22
- as_json
22
+ to_h
23
23
  end
24
24
 
25
25
  def empty?
@@ -3,8 +3,12 @@
3
3
  module Esse
4
4
  # https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices.html
5
5
  class IndexSetting
6
- def initialize(body: {}, paths: [], globals: {})
7
- @globals = globals || {}
6
+ # @param [Hash] options
7
+ # @option options [Proc] :globals A proc that will be called to load global settings
8
+ # @option options [Array] :paths A list of paths to load settings from
9
+ # @option options [Hash] :body A hash of settings to override
10
+ def initialize(body: {}, paths: [], globals: nil)
11
+ @globals = globals || -> { {} }
8
12
  @paths = Array(paths)
9
13
  @settings = body
10
14
  end
@@ -19,14 +23,14 @@ module Esse
19
23
  # end
20
24
  # end
21
25
  #
22
- def as_json
26
+ def to_h
23
27
  return @settings unless @settings.empty?
24
28
 
25
29
  from_template || @settings
26
30
  end
27
31
 
28
32
  def body
29
- @globals.merge(as_json)
33
+ HashUtils.deep_merge(@globals.call, to_h)
30
34
  end
31
35
 
32
36
  protected
@@ -3,7 +3,8 @@
3
3
  module Esse
4
4
  class IndexType
5
5
  module ClassMethods
6
- def action(name, options = {}, &block); end
6
+ def action(name, options = {}, &block)
7
+ end
7
8
  end
8
9
 
9
10
  extend ClassMethods
@@ -3,9 +3,10 @@
3
3
  module Esse
4
4
  class IndexType
5
5
  module ClassMethods
6
- def backend
6
+ def elasticsearch
7
7
  Esse::Backend::IndexType.new(self)
8
8
  end
9
+ alias_method :backend, :elasticsearch
9
10
  end
10
11
 
11
12
  extend ClassMethods
@@ -7,9 +7,9 @@ module Esse
7
7
  # This method is only used to define mapping
8
8
  def mappings(hash = {}, &block)
9
9
  @mapping = Esse::IndexMapping.new(body: hash, paths: template_dirs, filenames: mapping_filenames)
10
- return unless block_given?
10
+ return unless block
11
11
 
12
- @mapping.define_singleton_method(:as_json, &block)
12
+ @mapping.define_singleton_method(:to_h, &block)
13
13
  end
14
14
 
15
15
  # This is the actually content that will be passed through the ES api
@@ -1,10 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'object_document_mapper'
4
+
3
5
  module Esse
6
+ # Type is actually deprecated. Elasticsearch today uses _doc instead of type
7
+ # And in upcoming release it will be totally removed.
8
+ # But I want to keep compatibility with old versions of es.
4
9
  class IndexType
5
10
  require_relative 'index_type/actions'
6
11
  require_relative 'index_type/mappings'
7
- require_relative 'index_type/serializer'
8
12
  require_relative 'index_type/backend'
13
+ extend ObjectDocumentMapper
9
14
  end
10
15
  end
@@ -0,0 +1,19 @@
1
+ require 'logger'
2
+
3
+ module Esse
4
+ module Logging
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def logger
11
+ @logger ||= ::Logger.new($stdout)
12
+ end
13
+
14
+ def logger=(log)
15
+ @logger = log || ::Logger.new(File::NULL)
16
+ end
17
+ end
18
+ end
19
+ end