materialist 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52edad7b633726d80df5bf86cb2190a0f68b6094
4
- data.tar.gz: 2db6abb9165052f9a564751c49ea3c9c6f7c7a34
3
+ metadata.gz: d2acc5e6e25f3d5fb77c44a7c6dc465442b307b4
4
+ data.tar.gz: 155b6c787990989d49e59eb83190ad9adeb592f0
5
5
  SHA512:
6
- metadata.gz: 8ae7bb5132903ff79355624196fdb2e0e087534b29ab7c76734ce014b65959701b414539ce937f0cbe787c4335119778a622a76cf5f0f15599279675e97aefb1
7
- data.tar.gz: 404ed0434c32eaf7c7353771f05cdf3c907214d7fec93503227eb359beb37ca4bd6ad1e29d140c427e797d186df04f6e798c58a665f50c9743e57ae06877b722
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(source_url: url).tap do |entity|
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(source_url: url).tap do |entity|
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
@@ -1,3 +1,3 @@
1
1
  module Materialist
2
- VERSION = '2.0.0'
2
+ VERSION = '2.1.0'
3
3
  end
@@ -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[source_url] = self
59
+ self.class.all[source_key_value] = self
46
60
  end
47
61
 
48
62
  def destroy!
49
- self.class.all.delete source_url
63
+ self.class.all.delete source_key_value
50
64
  end
51
65
 
52
66
  def reload
53
- self.class.all[source_url]
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(source_url:)
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
- (all[source_url] || self.new).tap do |record|
70
- record.source_url = source_url
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 find_by(source_url:)
75
- all[source_url]
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.0.0
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-06 00:00:00.000000000 Z
11
+ date: 2017-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq