lycra 0.0.3 → 0.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.
- 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
|