lycra 0.0.7 → 5.0.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.
data/lib/lycra/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Lycra
2
2
  module Version
3
- MAJOR = '0'
3
+ MAJOR = '5'
4
4
  MINOR = '0'
5
- PATCH = '7'
5
+ PATCH = '0'
6
6
  VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
7
 
8
8
  class << self
data/spec/spec_helper.rb CHANGED
@@ -1,20 +1,25 @@
1
+ require 'byebug'
1
2
  require 'faker'
2
- require 'factory_girl'
3
+ require 'factory_bot'
4
+ require 'active_record'
5
+ require 'yaml'
3
6
  require 'lycra'
4
7
  require 'rspec'
5
8
  require 'coveralls'
6
9
  Coveralls.wear!
7
10
 
8
- #Dir[File.join(File.dirname(__FILE__), '..', "spec/support/**/*.rb")].each { |f| require f }
9
- Dir[File.join(File.dirname(__FILE__), '..', "spec/factories/**/*.rb")].each { |f| require f }
11
+ ActiveRecord::Base.establish_connection(
12
+ YAML::load(File.open('config/database.yml'))['test']
13
+ )
10
14
 
11
- #LYCRA_ES1_CLIENT = Elasticsearch::Client.new host: 'localhost', port: 9201
12
- LYCRA_ES2_CLIENT = Elasticsearch::Client.new host: 'localhost', port: 4500
13
- Elasticsearch::Model.client = LYCRA_ES2_CLIENT
15
+ Dir[File.join(File.dirname(__FILE__), '..', "app/models/**/*.rb")].each { |f| require f }
16
+ Dir[File.join(File.dirname(__FILE__), '..', "app/documents/**/*.rb")].each { |f| require f }
17
+ Dir[File.join(File.dirname(__FILE__), '..', "spec/support/**/*.rb")].each { |f| require f }
18
+ Dir[File.join(File.dirname(__FILE__), '..', "spec/factories/**/*.rb")].each { |f| require f }
14
19
 
15
20
  RSpec.configure do |config|
16
- # configure factory_girl syntax methods
17
- config.include FactoryGirl::Syntax::Methods
21
+ # configure factory_bot syntax methods
22
+ config.include FactoryBot::Syntax::Methods
18
23
 
19
24
  # rspec-expectations config goes here. You can use an alternate
20
25
  # assertion/expectation library such as wrong or the stdlib/minitest
@@ -0,0 +1,120 @@
1
+ #
2
+ # a document defining mappings, using the Lycra::Document mixin
3
+ #
4
+
5
+ class FooSubject
6
+ def foo
7
+ 'foo'
8
+ end
9
+
10
+ def bar
11
+ "BAR"
12
+ end
13
+ end
14
+
15
+ class Foo
16
+ include Lycra::Document
17
+
18
+ def initialize(*args, **opts, &block)
19
+ @subject = args.first
20
+ end
21
+
22
+ document_type 'Thingamajig'
23
+
24
+ attribute :foo, String
25
+
26
+ attribute :bar, Integer do
27
+ resolve ->(obj, arg, ctx) do
28
+ return 35
29
+ end
30
+ end
31
+
32
+ attribute :baz do
33
+ type String
34
+ resolve do |obj, arg, ctx|
35
+ "baz"
36
+ end
37
+ end
38
+
39
+ attribute :blah, Integer, ->(obj, arg, ctx) { 35 }
40
+ attribute :yadda, String, :bar
41
+
42
+ attribute :bad do
43
+ type String
44
+ resolve ->(obj, arg, ctx) do
45
+ return '35'
46
+ end
47
+ end
48
+ end
49
+
50
+ #
51
+ # a document defining mappings, inheriting from Lycra::Document::Base
52
+ #
53
+
54
+ class BarSubject
55
+ def foo
56
+ 'bar'
57
+ end
58
+
59
+ def bar
60
+ "FOO"
61
+ end
62
+ end
63
+
64
+ class Bar < Lycra::Document::Base
65
+ attribute :foo, String
66
+
67
+ attribute :bar, Integer do
68
+ resolve ->(obj, arg, ctx) do
69
+ return 35
70
+ end
71
+ end
72
+
73
+ attribute :baz do
74
+ type String
75
+ resolve do |obj, arg, ctx|
76
+ "baz"
77
+ end
78
+ end
79
+
80
+ attribute :blah, Integer, ->(obj, arg, ctx) { 35 }
81
+ attribute :yadda, String do
82
+ resolve :bar
83
+ end
84
+
85
+ attribute :bad do
86
+ type String
87
+ resolve ->(obj, arg, ctx) do
88
+ return '35'
89
+ end
90
+ end
91
+ end
92
+
93
+ =begin
94
+
95
+ #
96
+ # an active record model, with mappings inline (could be moved to concern)
97
+ #
98
+
99
+ class Foo < ApplicationRecord
100
+ include Elasticsearch::Model
101
+ include Lycra::Model
102
+ end
103
+
104
+
105
+ #
106
+ # a document defining mappings, with records backed by a corresponding model
107
+ # and/or
108
+ # an active record model, with mappings defined in a corresponding document
109
+ #
110
+ # this can be a one- or two-way relationship depending on how you want to use it
111
+
112
+ class FooDocument
113
+ include Lycra::Document # or... Lycra::Model::Document to specify a document w/ a backing model?
114
+ end
115
+
116
+ class Foo < ApplicationRecord
117
+ include Lycra::Document::Model # specify a model backed by a document
118
+ end
119
+
120
+ =end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lycra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Rebec
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-27 00:00:00.000000000 Z
11
+ date: 2018-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: canfig
@@ -25,27 +25,27 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: elasticsearch
28
+ name: elasticsearch-model
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.18
33
+ version: '5.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.0.18
40
+ version: '5.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: elasticsearch-persistence
42
+ name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
- type: :runtime
48
+ type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
@@ -53,13 +53,13 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: elasticsearch-model
56
+ name: sqlite3
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- type: :runtime
62
+ type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
@@ -67,21 +67,21 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: elasticsearch-rails
70
+ name: activerecord
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
75
+ version: '5.0'
76
+ type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '5.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: sqlite3
98
+ name: factory_bot
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rspec
112
+ name: faker
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
@@ -123,7 +123,7 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: factory_girl
126
+ name: byebug
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -137,33 +137,50 @@ dependencies:
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: faker
140
+ name: awesome_print
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="
144
144
  - !ruby/object:Gem::Version
145
- version: 1.6.6
145
+ version: '0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
- version: 1.6.6
153
- description: Open source business intelligence based on elasticsearch queries, inspired
154
- by https://github.com/ankane/blazer
152
+ version: '0'
153
+ description: Better elasticsearch documents for ruby
155
154
  email:
156
155
  - mark@markrebec.com
157
156
  executables: []
158
157
  extensions: []
159
158
  extra_rdoc_files: []
160
159
  files:
161
- - app/documents/lycra/document.rb
160
+ - lib/awesome_print/ext/lycra_attribute.rb
161
+ - lib/awesome_print/ext/lycra_attributes.rb
162
+ - lib/awesome_print/formatters/lycra_attribute_formatter.rb
163
+ - lib/awesome_print/formatters/lycra_attributes_formatter.rb
164
+ - lib/elasticsearch/model/adapters/lycra.rb
165
+ - lib/elasticsearch/model/adapters/lycra/document.rb
166
+ - lib/elasticsearch/model/adapters/lycra/multiple.rb
162
167
  - lib/lycra.rb
168
+ - lib/lycra/attributes.rb
169
+ - lib/lycra/attributes/attribute.rb
170
+ - lib/lycra/attributes/collection.rb
171
+ - lib/lycra/awesome_print.rb
172
+ - lib/lycra/decorator.rb
173
+ - lib/lycra/decorator/model.rb
174
+ - lib/lycra/document.rb
175
+ - lib/lycra/document/model.rb
176
+ - lib/lycra/document/proxy.rb
177
+ - lib/lycra/document/registry.rb
163
178
  - lib/lycra/engine.rb
164
179
  - lib/lycra/errors.rb
165
- - lib/lycra/model.rb
180
+ - lib/lycra/import.rb
181
+ - lib/lycra/inheritance.rb
166
182
  - lib/lycra/monkeypatches.rb
183
+ - lib/lycra/multidoc.rb
167
184
  - lib/lycra/search.rb
168
185
  - lib/lycra/search/aggregations.rb
169
186
  - lib/lycra/search/enumerable.rb
@@ -172,9 +189,13 @@ files:
172
189
  - lib/lycra/search/query.rb
173
190
  - lib/lycra/search/scoping.rb
174
191
  - lib/lycra/search/sort.rb
192
+ - lib/lycra/serializer.rb
193
+ - lib/lycra/serializer/model.rb
194
+ - lib/lycra/types.rb
175
195
  - lib/lycra/version.rb
176
196
  - spec/lycra_spec.rb
177
197
  - spec/spec_helper.rb
198
+ - spec/support/foo.rb
178
199
  homepage: http://github.com/markrebec/lycra
179
200
  licenses: []
180
201
  metadata: {}
@@ -194,10 +215,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
215
  version: '0'
195
216
  requirements: []
196
217
  rubyforge_project:
197
- rubygems_version: 2.6.11
218
+ rubygems_version: 2.7.7
198
219
  signing_key:
199
220
  specification_version: 4
200
- summary: Business intelligence based on elasticsearch queries
221
+ summary: Better elasticsearch documents for ruby
201
222
  test_files:
202
- - spec/lycra_spec.rb
203
223
  - spec/spec_helper.rb
224
+ - spec/lycra_spec.rb
225
+ - spec/support/foo.rb
@@ -1,191 +0,0 @@
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