lycra 0.0.7 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
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