materialist 2.0.0 → 2.1.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.
- checksums.yaml +4 -4
- data/README.md +11 -1
- data/lib/materialist/materializer.rb +19 -2
- data/lib/materialist.rb +1 -1
- data/spec/materialist/materializer_spec.rb +89 -9
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2acc5e6e25f3d5fb77c44a7c6dc465442b307b4
|
4
|
+
data.tar.gz: 155b6c787990989d49e59eb83190ad9adeb592f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c65249eadde28bed09a39c7114569a5d420f6f356b139b135913db8b84e732751d65aa3e27e12e8706f44d25c8af67fef0c3afc344e03a0f941911873f46ae2f
|
7
|
+
data.tar.gz: '0296ac0b29e449b14259be7f175898172f5fb8e65785f8e6cb082a95365d24dd969d26a2e4747df77a9e253db0c3a7149e9fd95a7c747a0b3cf60ee50d137cd8'
|
data/README.md
CHANGED
@@ -118,6 +118,10 @@ class ZoneMaterializer
|
|
118
118
|
|
119
119
|
persist_to :zone
|
120
120
|
|
121
|
+
source_key :source_id do |url|
|
122
|
+
/(\d+)\/?$/.match(url)[1]
|
123
|
+
end
|
124
|
+
|
121
125
|
capture :id, as: :orderweb_id
|
122
126
|
capture :code
|
123
127
|
capture :name
|
@@ -142,6 +146,12 @@ describes the name of the active record model to be used.
|
|
142
146
|
If missing, materialist skips materialising the resource itself, but will continue
|
143
147
|
with any other functionality -- such as `materialize_link`.
|
144
148
|
|
149
|
+
|
150
|
+
#### `source_key <column> <url_parser_block> (default: url)`
|
151
|
+
describes the column used to persist the unique identifier parsed from the url_parser_block.
|
152
|
+
By default the column used is `:source_url` and the original `url` is used as the identifier.
|
153
|
+
Passing an optional block allows you to extract an identifier from the URL.
|
154
|
+
|
145
155
|
#### `capture <key>, as: <column> (default: key)`
|
146
156
|
describes mapping a resource key to a database column.
|
147
157
|
|
@@ -169,7 +179,7 @@ class ZoneMaterializer
|
|
169
179
|
|
170
180
|
def my_method(record)
|
171
181
|
end
|
172
|
-
|
182
|
+
|
173
183
|
def my_second_method(record)
|
174
184
|
end
|
175
185
|
end
|
@@ -80,6 +80,11 @@ module Materialist
|
|
80
80
|
__materialist_options[:model_class] = klass
|
81
81
|
end
|
82
82
|
|
83
|
+
def source_key(key, &url_parser_block)
|
84
|
+
__materialist_options[:source_key] = key
|
85
|
+
__materialist_options[:url_parser] = url_parser_block
|
86
|
+
end
|
87
|
+
|
83
88
|
def after_upsert(*method_array)
|
84
89
|
__materialist_options[:after_upsert] = method_array
|
85
90
|
end
|
@@ -120,7 +125,7 @@ module Materialist
|
|
120
125
|
|
121
126
|
def destroy
|
122
127
|
return unless materialize_self?
|
123
|
-
model_class.find_by(
|
128
|
+
model_class.find_by(source_lookup(url)).tap do |entity|
|
124
129
|
entity.destroy!.tap do |entity|
|
125
130
|
send_messages(after_destroy, entity) unless after_destroy.nil?
|
126
131
|
end if entity
|
@@ -136,7 +141,7 @@ module Materialist
|
|
136
141
|
end
|
137
142
|
|
138
143
|
def upsert_record
|
139
|
-
model_class.find_or_initialize_by(
|
144
|
+
model_class.find_or_initialize_by(source_lookup(url)).tap do |entity|
|
140
145
|
entity.update_attributes attributes
|
141
146
|
entity.save!
|
142
147
|
end
|
@@ -176,6 +181,18 @@ module Materialist
|
|
176
181
|
options.fetch(:model_class).to_s.camelize.constantize
|
177
182
|
end
|
178
183
|
|
184
|
+
def source_key
|
185
|
+
options.fetch(:source_key, :source_url)
|
186
|
+
end
|
187
|
+
|
188
|
+
def url_parser
|
189
|
+
options[:url_parser] || ->url { url }
|
190
|
+
end
|
191
|
+
|
192
|
+
def source_lookup(url)
|
193
|
+
@_source_lookup ||= { source_key => url_parser.call(url) }
|
194
|
+
end
|
195
|
+
|
179
196
|
def attributes
|
180
197
|
build_attributes root_resource, mapping
|
181
198
|
end
|
data/lib/materialist.rb
CHANGED
@@ -11,6 +11,7 @@ RSpec.describe Materialist::Materializer do
|
|
11
11
|
include Materialist::Materializer
|
12
12
|
|
13
13
|
persist_to :foobar
|
14
|
+
|
14
15
|
capture :name
|
15
16
|
capture :age, as: :how_old
|
16
17
|
capture_link_href :city, as: :city_url
|
@@ -31,6 +32,19 @@ RSpec.describe Materialist::Materializer do
|
|
31
32
|
include Materialist::Materializer
|
32
33
|
|
33
34
|
persist_to :city
|
35
|
+
source_key :source_url
|
36
|
+
capture :name
|
37
|
+
end
|
38
|
+
|
39
|
+
class DefinedSourceMaterializer
|
40
|
+
include Materialist::Materializer
|
41
|
+
|
42
|
+
persist_to :defined_source
|
43
|
+
|
44
|
+
source_key :source_id do |url|
|
45
|
+
url.split('/').last.to_i
|
46
|
+
end
|
47
|
+
|
34
48
|
capture :name
|
35
49
|
end
|
36
50
|
end
|
@@ -42,37 +56,49 @@ RSpec.describe Materialist::Materializer do
|
|
42
56
|
end
|
43
57
|
|
44
58
|
def save!
|
45
|
-
self.class.all[
|
59
|
+
self.class.all[source_key_value] = self
|
46
60
|
end
|
47
61
|
|
48
62
|
def destroy!
|
49
|
-
self.class.all.delete
|
63
|
+
self.class.all.delete source_key_value
|
50
64
|
end
|
51
65
|
|
52
66
|
def reload
|
53
|
-
self.class.all[
|
67
|
+
self.class.all[source_key_value]
|
54
68
|
end
|
55
69
|
|
56
70
|
def actions_called
|
57
71
|
@_actions_called ||= {}
|
58
72
|
end
|
59
73
|
|
74
|
+
private def source_key_value
|
75
|
+
send(self.class.source_key_column)
|
76
|
+
end
|
77
|
+
|
60
78
|
class << self
|
61
|
-
attr_accessor :error_to_throw_once_in_find_or_initialize_by
|
79
|
+
attr_accessor :error_to_throw_once_in_find_or_initialize_by,
|
80
|
+
:source_key_column
|
62
81
|
|
63
|
-
def find_or_initialize_by(
|
82
|
+
def find_or_initialize_by(kv_hash)
|
64
83
|
if(err = error_to_throw_once_in_find_or_initialize_by)
|
65
84
|
self.error_to_throw_once_in_find_or_initialize_by = nil
|
66
85
|
raise err
|
67
86
|
end
|
68
87
|
|
69
|
-
|
70
|
-
|
88
|
+
key_value = kv_hash[source_key_column]
|
89
|
+
|
90
|
+
(all[key_value] || self.new).tap do |record|
|
91
|
+
record.send("#{source_key_column}=", key_value)
|
71
92
|
end
|
72
93
|
end
|
73
94
|
|
74
|
-
def
|
75
|
-
|
95
|
+
def source_key_column
|
96
|
+
@source_key_column || :source_url
|
97
|
+
end
|
98
|
+
|
99
|
+
def find_by(kv_hash)
|
100
|
+
key_value = kv_hash[source_key_column]
|
101
|
+
all[key_value]
|
76
102
|
end
|
77
103
|
|
78
104
|
def create!(attrs)
|
@@ -109,6 +135,11 @@ RSpec.describe Materialist::Materializer do
|
|
109
135
|
attr_accessor :source_url, :name
|
110
136
|
end
|
111
137
|
|
138
|
+
class DefinedSource < BaseModel
|
139
|
+
attr_accessor :source_id, :name
|
140
|
+
self.source_key_column = :source_id
|
141
|
+
end
|
142
|
+
|
112
143
|
module ActiveRecord
|
113
144
|
class RecordNotUnique < StandardError; end
|
114
145
|
class RecordInvalid < StandardError; end
|
@@ -120,6 +151,9 @@ RSpec.describe Materialist::Materializer do
|
|
120
151
|
let(:city_body) {{ _links: { country: { href: country_url }}, name: 'paris', timezone: 'Europe/Paris' }}
|
121
152
|
let(:source_url) { 'https://service.dev/foobars/1' }
|
122
153
|
let(:source_body) {{ _links: { city: { href: city_url }}, name: 'jack', age: 30 }}
|
154
|
+
let(:defined_source_id) { 65 }
|
155
|
+
let(:defined_source_url) { "https://service.dev/defined_sources/#{defined_source_id}" }
|
156
|
+
let(:defined_source_body) {{ name: 'ben' }}
|
123
157
|
|
124
158
|
def stub_resource(url, body)
|
125
159
|
stub_request(:get, url).to_return(
|
@@ -132,10 +166,12 @@ RSpec.describe Materialist::Materializer do
|
|
132
166
|
before do
|
133
167
|
Foobar.destroy_all
|
134
168
|
City.destroy_all
|
169
|
+
DefinedSource.destroy_all
|
135
170
|
|
136
171
|
stub_resource source_url, source_body
|
137
172
|
stub_resource country_url, country_body
|
138
173
|
stub_resource city_url, city_body
|
174
|
+
stub_resource defined_source_url, defined_source_body
|
139
175
|
end
|
140
176
|
|
141
177
|
let(:action) { :create }
|
@@ -362,5 +398,49 @@ RSpec.describe Materialist::Materializer do
|
|
362
398
|
end
|
363
399
|
end
|
364
400
|
end
|
401
|
+
|
402
|
+
context "when creating a new entity based on the source_key column" do
|
403
|
+
let(:perform) { DefinedSourceMaterializer.perform(defined_source_url, action) }
|
404
|
+
|
405
|
+
it "creates based on source_key" do
|
406
|
+
expect{perform}.to change{DefinedSource.count}.by 1
|
407
|
+
end
|
408
|
+
|
409
|
+
it "sets the correct source key" do
|
410
|
+
perform
|
411
|
+
inserted = DefinedSource.find_by(source_id: defined_source_id)
|
412
|
+
expect(inserted.source_id).to eq defined_source_id
|
413
|
+
expect(inserted.name).to eq defined_source_body[:name]
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
context "when updating a new entity based on the source_key column" do
|
418
|
+
let(:action) { :update }
|
419
|
+
let!(:record) { DefinedSource.create!(source_id: defined_source_id, name: 'mo') }
|
420
|
+
let(:perform) { DefinedSourceMaterializer.perform(defined_source_url, action) }
|
421
|
+
|
422
|
+
it "updates based on source_key" do
|
423
|
+
perform
|
424
|
+
expect(DefinedSource.count).to eq 1
|
425
|
+
end
|
426
|
+
|
427
|
+
it "updates the existing record" do
|
428
|
+
perform
|
429
|
+
inserted = DefinedSource.find_by(source_id: defined_source_id)
|
430
|
+
expect(inserted.source_id).to eq defined_source_id
|
431
|
+
expect(inserted.name).to eq defined_source_body[:name]
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
context "when deleting an entity based on the source_key column" do
|
436
|
+
let(:action) { :delete }
|
437
|
+
let!(:record) { DefinedSource.create!(source_id: defined_source_id, name: 'mo') }
|
438
|
+
let(:perform) { DefinedSourceMaterializer.perform(defined_source_url, action) }
|
439
|
+
|
440
|
+
it "deletes based on source_key" do
|
441
|
+
perform
|
442
|
+
expect(DefinedSource.count).to eq 0
|
443
|
+
end
|
444
|
+
end
|
365
445
|
end
|
366
446
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: materialist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mo Valipour
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-11-
|
11
|
+
date: 2017-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|