lycra 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/documents/lycra/document.rb +191 -0
- data/lib/lycra/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91043f8065e7fcf15adf93772387b25ad5e84259
|
4
|
+
data.tar.gz: 8319be6afc7ee3594784357ffb744dc4b9e71d4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06811b5b68df2ad87ddf8e35ba19873add41e5a4325dfa3615b822235bcaa615849bf75d846583e043b4d4472e0819c3bf553357f7e8afd489ca8cf29df7ca64
|
7
|
+
data.tar.gz: e30ee923b27916255f75c8be97dca2f806cbec8bdd2e770fa4a766baa0a555fb635b720f4364cb12faefbbd78c146c7369bc9969c77031d0bec4196525fcd4ac
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'elasticsearch/persistence/model'
|
2
|
+
|
3
|
+
module Lycra
|
4
|
+
# TODO explain how this is used, what it is, why, etc.
|
5
|
+
|
6
|
+
# TODO add validations for the results of as_indexed_json against the mapped attributes
|
7
|
+
|
8
|
+
class Document
|
9
|
+
attr_reader :subject
|
10
|
+
|
11
|
+
INDEX_REGEX = /\A#{::Lycra.configuration.index_prefix}-?/
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def inherited(base)
|
15
|
+
# Make sure we inherit the parent's class-level instance variables whenever we inherit from the class.
|
16
|
+
# TODO add more comments/examples explaining why we clone these vars
|
17
|
+
base.send :instance_variable_set, :@lycra_index_name, index_name.try(:dup)
|
18
|
+
base.send :instance_variable_set, :@lycra_document_type, document_type.try(:dup)
|
19
|
+
base.send :instance_variable_set, :@lycra_attributes, attributes.try(:dup)
|
20
|
+
base.send :instance_variable_set, :@lycra_mapping, mapping.try(:dup)
|
21
|
+
base.send :instance_variable_set, :@lycra_settings, settings.try(:dup)
|
22
|
+
end
|
23
|
+
|
24
|
+
def document_type(doctype=nil)
|
25
|
+
@lycra_document_type = doctype if doctype.present?
|
26
|
+
@lycra_document_type
|
27
|
+
end
|
28
|
+
|
29
|
+
def index_name(zindex_name=nil)
|
30
|
+
@lycra_index_name = prefixed_index_name(zindex_name) if zindex_name.present?
|
31
|
+
@lycra_index_name
|
32
|
+
end
|
33
|
+
|
34
|
+
def attribute(name, type, mappings={})
|
35
|
+
attributes[name] = {type: Elasticsearch::Persistence::Model::Utils.lookup_type(type)}.merge(mappings[:mapping] || {})
|
36
|
+
end
|
37
|
+
|
38
|
+
def attributes(attrs=nil)
|
39
|
+
@lycra_attributes = attrs if attrs.present?
|
40
|
+
@lycra_attributes ||= {}
|
41
|
+
end
|
42
|
+
|
43
|
+
def mapping(map=nil)
|
44
|
+
@lycra_mapping = map if map.present?
|
45
|
+
@lycra_mapping ||= {}
|
46
|
+
end
|
47
|
+
alias_method :mappings, :mapping
|
48
|
+
|
49
|
+
def settings(settings=nil)
|
50
|
+
@lycra_settings = settings if settings.present?
|
51
|
+
@lycra_settings ||= {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def prefixed_index_name(idx)
|
55
|
+
[::Lycra.configuration.index_prefix, idx.to_s.gsub(INDEX_REGEX, '')].compact.join('-')
|
56
|
+
end
|
57
|
+
|
58
|
+
def index_basename
|
59
|
+
index_name.to_s.gsub(INDEX_REGEX, '')
|
60
|
+
end
|
61
|
+
|
62
|
+
def import(*models, **opts, &block)
|
63
|
+
models = [models].flatten
|
64
|
+
document = models.first.lycra_document
|
65
|
+
raise ArgumentError, 'All models must use the same index in order to be imported together' unless models.all? { |model| model.index_name == document.index_name }
|
66
|
+
|
67
|
+
index_name = opts.delete(:index_name) || document.index_name
|
68
|
+
|
69
|
+
if opts.delete(:force) == true && document.__elasticsearch__.client.indices.exists?(index: index_name)
|
70
|
+
# delete the index if it exists and the force-create option was passed
|
71
|
+
document.__elasticsearch__.client.indices.delete index: index_name
|
72
|
+
end
|
73
|
+
|
74
|
+
unless document.__elasticsearch__.client.indices.exists?(index: index_name)
|
75
|
+
document.__elasticsearch__.client.indices.create index: index_name, update_all_types: true, body: {
|
76
|
+
settings: document.settings,
|
77
|
+
mappings: models.inject({}) { |mappings, model| mappings.merge!(model.mappings) } # hacky, need to map all the document mappings
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
models.each do |model|
|
82
|
+
model.index_name index_name
|
83
|
+
model.import **opts, &block
|
84
|
+
model.index_name document.index_name
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def rotate(*models, **opts, &block)
|
89
|
+
models = [models].flatten
|
90
|
+
document = models.first.lycra_document
|
91
|
+
raise ArgumentError, 'All models must use the same index in order to be imported together' unless models.all? { |model| model.index_name == document.index_name }
|
92
|
+
|
93
|
+
unstamped_alias = document.index_name
|
94
|
+
timestamped_index = [unstamped_alias, Time.now.to_i].compact.join('-')
|
95
|
+
existing_index = nil
|
96
|
+
|
97
|
+
import(*models, **opts.merge({index_name: timestamped_index}), &block)
|
98
|
+
|
99
|
+
if document.__elasticsearch__.client.indices.exists_alias? name: unstamped_alias
|
100
|
+
existing_index = document.__elasticsearch__.client.indices.get_alias(name: unstamped_alias).keys.first
|
101
|
+
document.__elasticsearch__.client.indices.delete_alias name: unstamped_alias, index: existing_index
|
102
|
+
elsif document.__elasticsearch__.client.indices.exists? index: unstamped_alias
|
103
|
+
document.__elasticsearch__.client.indices.delete index: unstamped_alias
|
104
|
+
end
|
105
|
+
document.__elasticsearch__.client.indices.put_alias name: unstamped_alias, index: timestamped_index
|
106
|
+
document.__elasticsearch__.client.indices.delete index: existing_index unless existing_index.nil?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# NOTE: HEADS UP! Yes, this is an INSTANCE METHOD!
|
111
|
+
# It is a shortcut, since this class represents both your model **class** (i.e. MyModel) and your model **records** (i.e. MyModel.find(1)).
|
112
|
+
#
|
113
|
+
# normal class usage allows for things like:
|
114
|
+
#
|
115
|
+
# MyDocument.new(MyModel) # interact with elasticsearch at the model level (index names, mappings, etc.)
|
116
|
+
# MyDocument.new(MyModel.find(1)) # interact with elasticsearch at the record level (as_indexed_json, also has access to index name, etc.)
|
117
|
+
#
|
118
|
+
# but with this, we also get:
|
119
|
+
#
|
120
|
+
# document = MyDocument.new(MyModel) # instantiate a class-level model document
|
121
|
+
# # ... do some stuff at the class-level ...
|
122
|
+
# document.new(my_model_record) # easily re-use the same document class to decorate your record without needing to know what it was
|
123
|
+
# # ... do some stuff with your record ...
|
124
|
+
def new(object)
|
125
|
+
self.class.new(object)
|
126
|
+
end
|
127
|
+
|
128
|
+
def initialize(subject)
|
129
|
+
@subject = subject
|
130
|
+
|
131
|
+
if subject.is_a?(Class)
|
132
|
+
# TODO explain why and/or maybe add some ! methods that are more explicit about what we're doing
|
133
|
+
unless self.class.index_name.present?
|
134
|
+
raise Lycra::UndefinedIndexError, self
|
135
|
+
end
|
136
|
+
|
137
|
+
index_name(self.class.index_name)
|
138
|
+
document_type(self.class.document_type)
|
139
|
+
mapping(self.class.mapping)
|
140
|
+
settings(self.class.settings)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def document_type(doctype=nil)
|
145
|
+
subject.__elasticsearch__.document_type doctype
|
146
|
+
end
|
147
|
+
|
148
|
+
def index_name(idx=nil)
|
149
|
+
if idx.present?
|
150
|
+
subject.__elasticsearch__.index_name self.class.prefixed_index_name(idx)
|
151
|
+
else
|
152
|
+
subject.__elasticsearch__.index_name
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def mapping(options={}, &block)
|
157
|
+
self.class.attributes.each do |field, opts|
|
158
|
+
subject.__elasticsearch__.mapping.indexes field, opts
|
159
|
+
end
|
160
|
+
|
161
|
+
if options.present? || block_given?
|
162
|
+
subject.__elasticsearch__.mapping options, &block
|
163
|
+
end
|
164
|
+
|
165
|
+
subject.__elasticsearch__.mapping
|
166
|
+
end
|
167
|
+
alias_method :mappings, :mapping
|
168
|
+
|
169
|
+
def settings(settings=nil, &block)
|
170
|
+
subject.__elasticsearch__.settings settings, &block if settings.present? || block_given?
|
171
|
+
subject.__elasticsearch__.settings
|
172
|
+
end
|
173
|
+
|
174
|
+
def method_missing(meth, *args, &block)
|
175
|
+
return subject.send(meth, *args, &block) if respond_to_missing?(meth, true)
|
176
|
+
super
|
177
|
+
end
|
178
|
+
|
179
|
+
def respond_to_missing?(meth, include_private=false)
|
180
|
+
subject.respond_to?(meth, include_private)
|
181
|
+
end
|
182
|
+
|
183
|
+
def as_json(opts={})
|
184
|
+
subject.as_json(opts)
|
185
|
+
end
|
186
|
+
|
187
|
+
def as_indexed_json(opts={})
|
188
|
+
as_json(opts)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
data/lib/lycra/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lycra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Rebec
|
@@ -158,6 +158,7 @@ executables: []
|
|
158
158
|
extensions: []
|
159
159
|
extra_rdoc_files: []
|
160
160
|
files:
|
161
|
+
- app/documents/lycra/document.rb
|
161
162
|
- lib/lycra.rb
|
162
163
|
- lib/lycra/engine.rb
|
163
164
|
- lib/lycra/errors.rb
|