elos 0.1.0 → 1.0.4

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/bin/push +40 -0
  4. data/bin/rspec +16 -0
  5. data/db/migrate/001_create_a_entry_repos.rb +7 -0
  6. data/elos-0.1.0.gem +0 -0
  7. data/elos-1.0.3.gem +0 -0
  8. data/elos.gemspec +20 -9
  9. data/lib/elos/configuration.rb +16 -0
  10. data/lib/elos/criteria.rb +78 -0
  11. data/lib/elos/data_object.rb +30 -0
  12. data/lib/elos/errors/not_found.rb +5 -0
  13. data/lib/elos/errors/validation_failed.rb +5 -0
  14. data/lib/elos/index/core.rb +35 -0
  15. data/lib/elos/index/indexable.rb +32 -0
  16. data/lib/elos/index/locatable.rb +17 -0
  17. data/lib/elos/index/mappings.rb +25 -0
  18. data/lib/elos/index/model/assignable.rb +19 -0
  19. data/lib/elos/index/model/identifiable.rb +9 -0
  20. data/lib/elos/index/model/initializable.rb +13 -0
  21. data/lib/elos/index/model.rb +12 -0
  22. data/lib/elos/index/raw_helpers.rb +9 -0
  23. data/lib/elos/index/refreshable.rb +9 -0
  24. data/lib/elos/index/reindexable.rb +132 -0
  25. data/lib/elos/index/searchable.rb +17 -0
  26. data/lib/elos/index/subscribable.rb +14 -0
  27. data/lib/elos/index/unindexable.rb +9 -0
  28. data/lib/elos/index.rb +15 -0
  29. data/lib/elos/lock.rb +48 -0
  30. data/lib/elos/query_builder/base.rb +23 -0
  31. data/lib/elos/query_builder/builtin/match_all_query_builder.rb +5 -0
  32. data/lib/elos/query_builder/builtin/where_query_builder.rb +5 -0
  33. data/lib/elos/query_builder/filters.rb +41 -0
  34. data/lib/elos/query_builder/queries.rb +15 -0
  35. data/lib/elos/repository/adapter/active_record/scanable.rb +11 -0
  36. data/lib/elos/repository/adapter/active_record.rb +6 -0
  37. data/lib/elos/repository/adapter/elos/migratable.rb +13 -0
  38. data/lib/elos/repository/adapter/elos/model/destroyable.rb +44 -0
  39. data/lib/elos/repository/adapter/elos/model/persistable.rb +79 -0
  40. data/lib/elos/repository/adapter/elos/model/reindexable.rb +15 -0
  41. data/lib/elos/repository/adapter/elos/model/unindexable.rb +7 -0
  42. data/lib/elos/repository/adapter/elos/model/validatable.rb +8 -0
  43. data/lib/elos/repository/adapter/elos/scanable.rb +24 -0
  44. data/lib/elos/repository/adapter/elos.rb +31 -0
  45. data/lib/elos/repository/publishable.rb +26 -0
  46. data/lib/elos/result.rb +23 -0
  47. data/lib/elos/version.rb +2 -2
  48. data/lib/elos.rb +3 -3
  49. data/lib/initialize.rb +6 -0
  50. metadata +129 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fbdcf9020cc5fd26078aa94d7baaa1c61f4d5c6a
4
- data.tar.gz: c874a6670ddce992a34e7f1d0788eabf3b5672f4
3
+ metadata.gz: 4c5f6f066aac89f49b12b923b11c03178df3003c
4
+ data.tar.gz: 27028953724446f96f69b59191e6ddf93bb63bd6
5
5
  SHA512:
6
- metadata.gz: e8ab7b916b4aa3c3df901359c80b97a7fd831bb5b60570f62b61850efcce76fcdeab41897dca06ddd2f0d403e6e37610a7a286b1d09ad38891dc21b8aa7fa794
7
- data.tar.gz: 4d7628c6ba01494b0845e394486c62418c6d18f4030e44bcfe72b9d51b23c1772df793101c1324d9abe1fd8c2353b511ae404bbf83e723e793325f5e76cc9ff4
6
+ metadata.gz: 84a7cb6d89f163762c8871a7569c324dcd2d82290fe293fc2102cae665e9e4cef01793cbd1e84d5baae2e8f6fb95270f221f5d12de33e2f2413fff444fd31e8e
7
+ data.tar.gz: ac0abb746a1fc9bb1c56854f6fad3126f030f3e5dc712f503187c172d5c85e87e2ee8f75143b7d020db7d775cce6b9cb3b88b129c6666bbfc809c54261a7f502
data/.rspec CHANGED
@@ -1,2 +1,4 @@
1
1
  --format documentation
2
2
  --color
3
+ --order rand
4
+ --require spec_helper
data/bin/push ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "elos"
5
+
6
+ def versions(version_string)
7
+ vers = version_string.split('.').map(&:to_i)
8
+ fail 'Invalid version format!' unless vers.length == 3
9
+ vers
10
+ end
11
+
12
+ def later_version!(vers1, vers2)
13
+ [vers1, vers2].transpose.each do |ver1, ver2|
14
+ return if ver1 > ver2
15
+ fail 'Not later version!' if ver1 < ver2
16
+ end
17
+ fail 'Not later version!'
18
+ end
19
+
20
+ specified_vers = versions(ARGV[0]) if ARGV.length > 0
21
+ vers = versions(Elos::VERSION)
22
+ specified_vers ||=
23
+ begin
24
+ r = vers.dup
25
+ r[2] = r[2] + 1
26
+ r
27
+ end
28
+
29
+ later_version!(specified_vers, vers)
30
+
31
+ path = File.expand_path('../..', __FILE__)
32
+ new_ver = specified_vers.join('.')
33
+ `sed -i -e 's/#{Elos::VERSION}/#{new_ver}/g' #{path}/lib/elos/version.rb`
34
+ `git add --all`
35
+ `git commit -m 'version #{new_ver}'`
36
+ `git push origin master`
37
+ `git tag #{new_ver}`
38
+ `git push origin #{new_ver}`
39
+ `gem build elos.gemspec`
40
+ `gem push elos-#{new_ver}.gem`
data/bin/rspec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
@@ -0,0 +1,7 @@
1
+ class CreateAEntryRepos < ActiveRecord::Migration
2
+ def change
3
+ create_table :a_entry_repos do |t|
4
+ t.string :title
5
+ end
6
+ end
7
+ end
data/elos-0.1.0.gem ADDED
Binary file
data/elos-1.0.3.gem ADDED
Binary file
data/elos.gemspec CHANGED
@@ -4,21 +4,32 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'elos/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "elos"
7
+ spec.name = 'elos'
8
8
  spec.version = Elos::VERSION
9
- spec.authors = ["Tetsuri Moriya"]
10
- spec.email = ["tetsuri.moriya@gmail.com"]
9
+ spec.authors = ['Tetsuri Moriya']
10
+ spec.email = ['tetsuri.moriya@gmail.com']
11
11
 
12
12
  spec.summary = %q{Elasticsearch integration for Databases}
13
13
  spec.description = %q{Elasticsearch integration for Databases, such as ActiveRecord}
14
- spec.homepage = "https://github.com/pandora2000/elos"
15
- spec.license = "MIT"
14
+ spec.homepage = 'https://github.com/pandora2000/elos'
15
+ spec.license = 'MIT'
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
- spec.bindir = "exe"
18
+ spec.bindir = 'exe'
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
- spec.require_paths = ["lib"]
20
+ spec.require_paths = ['lib']
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.9"
23
- spec.add_development_dependency "rake", "~> 10.0"
22
+ [['activesupport', '>= 3.0.0'],
23
+ ['elasticsearch']].each do |args|
24
+ spec.add_dependency *args
25
+ end
26
+
27
+ [['bundler', '~> 1.9'],
28
+ ['rake', '~> 10.0'],
29
+ ['rspec', '>= 0'],
30
+ ['database_cleaner', '~> 1.2.0'],
31
+ ['activerecord'],
32
+ ['mysql2']].each do |args|
33
+ spec.add_development_dependency *args
34
+ end
24
35
  end
@@ -0,0 +1,16 @@
1
+ module Elos::Configuration
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_accessor :client, :env, :settings
6
+ end
7
+
8
+ class_methods do
9
+ def config(host: nil, env: nil, settings: {})
10
+ host ||= 'localhost:9200'
11
+ self.client = ::Elasticsearch::Client.new(host: host)
12
+ self.env = env
13
+ self.settings = settings
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,78 @@
1
+ class Elos::Criteria < Elos::Result
2
+ def initialize(params:, query_builder_class:, klass:)
3
+ @client = Elos.client
4
+ @params = params
5
+ @query_builder_class = query_builder_class
6
+ @klass = klass
7
+ end
8
+
9
+ def page(page)
10
+ @params[:page] = page
11
+ self
12
+ end
13
+
14
+ def per(per = nil)
15
+ if per
16
+ @params[:per] = per
17
+ self
18
+ else
19
+ @params[:per]
20
+ end
21
+ end
22
+
23
+ alias_method :limit, :per
24
+
25
+ def includes(*names)
26
+ @includes = names
27
+ self
28
+ end
29
+
30
+ def total_count
31
+ result
32
+ @total_count
33
+ end
34
+
35
+ def current_page
36
+ @params[:page]
37
+ end
38
+
39
+ def total_pages
40
+ [0, total_count - 1].max / @params[:per] + 1
41
+ end
42
+
43
+ def first_page?
44
+ current_page == 1
45
+ end
46
+
47
+ def last_page?
48
+ current_page == total_pages
49
+ end
50
+
51
+ def to_a!
52
+ r = to_a
53
+ raise Elos::Errors::NotFound if r.empty?
54
+ r
55
+ end
56
+
57
+ def first!
58
+ r = first
59
+ raise Elos::Errors::NotFound unless r
60
+ r
61
+ end
62
+
63
+ def query
64
+ @query_builder_class.new(@params)._build
65
+ end
66
+
67
+ protected
68
+
69
+ def result
70
+ return @result if @result
71
+ search_result = @client.search(index: @klass.read_alias_name, type: @klass.type_name, body: query)
72
+ # puts JSON.pretty_generate(results)
73
+ @total_count = search_result['hits']['total']
74
+ @results = search_result['hits']['hits'].map do |h|
75
+ @klass.new(h['_source'].reverse_merge(score: h['_score'], highlight: h['highlight']).merge(id: h['_id'], _persisted: true))
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,30 @@
1
+ class Elos::DataObject
2
+ attr_reader :object
3
+
4
+ def initialize(params = {})
5
+ @params = params
6
+ @object = objectify(params)
7
+ end
8
+
9
+ def method_missing(method, *args, **hargs, &block)
10
+ if object.respond_to?(method)
11
+ object.send(method, *args)
12
+ elsif method.to_s.end_with?('=')
13
+ object.send(method, *args)
14
+ else
15
+ super
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def objectify(value)
22
+ if value.is_a?(Hash)
23
+ OpenStruct.new(Hash[value.map { |k, v| [k, objectify(v)] }])
24
+ elsif value.is_a?(Array)
25
+ value.map { |v| objectify(v) }
26
+ else
27
+ value
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ class Elos::Errors::NotFound < StandardError
2
+ def initialize
3
+ super('Not found.')
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class Elos::Errors::ValidationFailed < StandardError
2
+ def initialize
3
+ super('Validation failed.')
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ module Elos::Index::Core
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_accessor :client, :type_name, :index_name
6
+
7
+ self.client = Elos.client
8
+ self.type_name = name.underscore.gsub('/', '-')
9
+ self.index_name = "#{name.underscore.pluralize.gsub('/', '-')}=#{Elos.env}="
10
+ end
11
+
12
+ class_methods do
13
+ protected
14
+
15
+ def create_index(name)
16
+ unless client.indices.exists(index: name)
17
+ client.indices.create(index: name, body: index_parameters)
18
+ end
19
+ end
20
+
21
+ def delete_index(name)
22
+ if client.indices.exists(index: name)
23
+ client.indices.delete(index: name)
24
+ end
25
+ end
26
+
27
+ def refresh_index(name)
28
+ client.indices.refresh(index: name)
29
+ end
30
+
31
+ def index_parameters
32
+ { settings: Elos.settings, mappings: mappings }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ module Elos::Index::Indexable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_writer :index_data
6
+ end
7
+
8
+ class_methods do
9
+ def index_data(index_data = nil)
10
+ if index_data
11
+ self.index_data = index_data
12
+ else
13
+ self.class_variable_get(:@@index_data)
14
+ end
15
+ end
16
+
17
+ def index(obj, destroy: false, unindex: false)
18
+ if !unindex && data = index_data.(obj)
19
+ data.merge!(_destroyed: destroy)
20
+ params = { index: write_alias_name, type: type_name, body: data }
21
+ params.merge!(id: obj.id) if obj.id
22
+ client.index(params)['_id']
23
+ else
24
+ begin
25
+ client.delete(index: write_alias_name, type: type_name, id: obj.id)
26
+ nil
27
+ rescue Elasticsearch::Transport::Transport::Errors::NotFound
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module Elos::Index::Locatable
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def where(params = {})
6
+ search(query_builder_class: Elos::QueryBuilder::Builtin::WhereQueryBuilder, **params)
7
+ end
8
+
9
+ def find(arg)
10
+ if arg.is_a?(Array)
11
+ where(id: arg).to_a!
12
+ else
13
+ where(id: [arg]).first!
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ module Elos::Index::Mappings
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_writer :mappings
6
+ end
7
+
8
+ class_methods do
9
+ def mappings(mappings = nil)
10
+ if mappings
11
+ set_mappings(mappings)
12
+ else
13
+ self.class_variable_get(:@@mappings)
14
+ end
15
+ end
16
+
17
+ protected
18
+
19
+ def set_mappings(mappings)
20
+ mps = mappings.deep_dup
21
+ mps[type_name][:properties].merge!(_destroyed: { type: 'boolean' })
22
+ self.mappings = mps
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ module Elos::Index::Model::Assignable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ after_new -> { assign_attributes(@_attrs) }
6
+ end
7
+
8
+ def assign_attributes(attrs)
9
+ attrs.each do |key, value|
10
+ @_data.send("#{key}=", value)
11
+ end
12
+ end
13
+
14
+ def method_missing(method, *args)
15
+ @_data.send(method, *args)
16
+ rescue NoMethodError
17
+ super
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ module Elos::Index::Model::Identifiable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ attr_accessor :id
6
+
7
+ before_new -> { self.id = @_attrs.delete(:id) }
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Elos::Index::Model::Initializable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ define_model_callbacks :new
6
+ end
7
+
8
+ def initialize(attrs = {})
9
+ @_data = Elos::DataObject.new
10
+ @_attrs = attrs
11
+ run_callbacks :new
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Elos::Index::Model
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include ActiveModel::Model
6
+ include ActiveModel::Callbacks
7
+
8
+ include Elos::Index::Model::Initializable
9
+ include Elos::Index::Model::Assignable
10
+ include Elos::Index::Model::Identifiable
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module Elos::Index::RawHelpers
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def raw_get(id)
6
+ client.get(index: read_alias_name, type: type_name, id: id)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Elos::Index::Refreshable
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def refresh
6
+ refresh_index(read_alias_name)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,132 @@
1
+ module Elos::Index::Reindexable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_accessor :read_alias_name, :write_alias_name, :reindex_block
6
+
7
+ self.read_alias_name = "#{index_name}read"
8
+ self.write_alias_name = "#{index_name}write"
9
+ end
10
+
11
+ class_methods do
12
+ def initialize_for_reindex(force = false)
13
+ return false if !force && client.indices.exists_alias(name: read_alias_name) && client.indices.exists_alias(name: write_alias_name)
14
+ Elos::Lock.unlock(lock_key) if force
15
+ delete_index("#{index_name}*")
16
+ index_name = random_index_name
17
+ unless client.indices.exists(index: index_name)
18
+ client.indices.create(index: index_name, body: index_parameters)
19
+ alias_index(read_alias_name, index_name)
20
+ alias_index(write_alias_name, index_name)
21
+ return true
22
+ end
23
+ false
24
+ end
25
+
26
+ def reindex(set_block = nil, &block)
27
+ return set_reindex(set_block) if set_block
28
+ proc = block || self.reindex_block
29
+ long_args = proc.parameters.length == 2
30
+ Elos::Lock.lock(lock_key) do
31
+ initialize_for_reindex
32
+ old_index_name = read_index_name
33
+ unless write_index_names == [old_index_name]
34
+ repair_for_reindex
35
+ end
36
+ return unless new_index_name = create_index_with_random_name
37
+ begin
38
+ alias_index(write_alias_name, new_index_name)
39
+ if long_args
40
+ proc.(old_index_name, new_index_name)
41
+ else
42
+ proc.()
43
+ end
44
+ switch_pointed_index(read_alias_name, old_index_name, new_index_name)
45
+ unalias_index(write_alias_name, old_index_name)
46
+ rescue Exception => e
47
+ if read_index_name == old_index_name
48
+ if write_index_names.include?(new_index_name)
49
+ unalias_index(write_alias_name, new_index_name)
50
+ end
51
+ delete_index(new_index_name)
52
+ end
53
+ raise e
54
+ end
55
+ delete_index(old_index_name)
56
+ end
57
+ end
58
+
59
+ protected
60
+
61
+ def read_index_name
62
+ aliased_index_name(read_alias_name)
63
+ end
64
+
65
+ def write_index_name
66
+ write_index_names.first
67
+ end
68
+
69
+ def write_index_names
70
+ aliased_index_names(write_alias_name)
71
+ end
72
+
73
+ def lock_key
74
+ "elos:reindex_or_migrate:#{name.underscore}"
75
+ end
76
+
77
+ def set_reindex(block)
78
+ self.reindex_block = block
79
+ end
80
+
81
+ def repair_for_reindex
82
+ (write_index_names - [read_index_name]).each do |name|
83
+ unalias_index(write_alias_name, name)
84
+ delete_index(name)
85
+ end
86
+ return if write_index_name == read_index_name
87
+ alias_index(write_alias_name, read_index_name)
88
+ end
89
+
90
+ def aliased_index_name(alias_name)
91
+ aliased_index_names(alias_name).first
92
+ end
93
+
94
+ def aliased_index_names(alias_name)
95
+ client.indices.get_alias(index: "#{index_name}*", name: alias_name).keys
96
+ end
97
+
98
+ def alias_index(alias_name, index_name)
99
+ client.indices.update_aliases body: {
100
+ actions: [
101
+ { add: { index: index_name, alias: alias_name } }
102
+ ]
103
+ }
104
+ end
105
+
106
+ def unalias_index(alias_name, index_name)
107
+ client.indices.update_aliases body: {
108
+ actions: [
109
+ { remove: { index: index_name, alias: alias_name } }
110
+ ]
111
+ }
112
+ end
113
+
114
+ def switch_pointed_index(alias_name, from_index_name, to_index_name)
115
+ client.indices.update_aliases body: {
116
+ actions: [
117
+ { remove: { index: from_index_name, alias: alias_name } },
118
+ { add: { index: to_index_name, alias: alias_name } }
119
+ ]
120
+ }
121
+ end
122
+
123
+ def create_index_with_random_name
124
+ create_index(name = random_index_name)
125
+ name
126
+ end
127
+
128
+ def random_index_name
129
+ "#{index_name}#{SecureRandom.uuid}"
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,17 @@
1
+ module Elos::Index::Searchable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_accessor :query_builder_class
6
+ end
7
+
8
+ class_methods do
9
+ def query_builder(klass)
10
+ self.query_builder_class = klass
11
+ end
12
+
13
+ def search(query_builder_class: self.query_builder_class, **params)
14
+ Elos::Criteria.new(params: params, query_builder_class: query_builder_class, klass: self)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Elos::Index::Subscribable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_accessor :repository_class
6
+ end
7
+
8
+ class_methods do
9
+ def subscribe(repository_class)
10
+ self.repository_class = repository_class
11
+ repository_class.subscribers << self
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module Elos::Index::Unindexable
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def unindex
6
+ initialize_for_reindex(true)
7
+ end
8
+ end
9
+ end
data/lib/elos/index.rb ADDED
@@ -0,0 +1,15 @@
1
+ module Elos::Index
2
+ extend ActiveSupport::Concern
3
+
4
+ include Elos::Index::Core
5
+ include Elos::Index::Mappings
6
+ include Elos::Index::RawHelpers
7
+ include Elos::Index::Refreshable
8
+ include Elos::Index::Indexable
9
+ include Elos::Index::Reindexable
10
+ include Elos::Index::Unindexable
11
+ include Elos::Index::Searchable
12
+ include Elos::Index::Locatable
13
+ include Elos::Index::Subscribable
14
+ include Elos::Index::Model
15
+ end