materialist 0.1.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ddfdebe864838d6fdb912aee5d3002417aca969b
4
- data.tar.gz: 13ebd4c0bad48a307820aaa28c81d674335da88c
3
+ metadata.gz: 2369c3f2842a7dc8cc9ff3efe2339328b7cf14aa
4
+ data.tar.gz: d043d9df4eda5667d6a09b040a485c39e7c16449
5
5
  SHA512:
6
- metadata.gz: c082a2dfffdae443aaafb41d20f4a12da3203a90bbae0e4bd8075f77364fdc67d2386de3373572d1a0b6b46bbb93d0e7a1adca2df59777f15de7c9eb9fbf0d02
7
- data.tar.gz: 80d88005986ec167b4d599085e9fcd424c37b4cab98baacc44a38deed1731e035c8acc8da118e0be286b17f5c2de1adf95ddd4a45253b43ba9648169b4f79113
6
+ metadata.gz: 78c9b1b5683feadc832ac2184b0b79b1a52f421697b4d921af7e776da7607218093e6a7f9aa12cb5fc2ddf8147c4752c0b4649fc3ea748e408ccc01aec98d9ff
7
+ data.tar.gz: 7f9b3b1a197b8c793a040b3d1cb894282bc58446055910c3727d08fea83678de23c7823bcdb613b57b5ec8161c360a00518e96dfc1dd8444641fe6a683399bd9
data/README.md CHANGED
@@ -143,7 +143,10 @@ If missing, materialist skips materialising the resource itself, but will contin
143
143
  with any other functionality -- such as `materialize_link`.
144
144
 
145
145
  #### `capture <key>, as: <column> (default: key)`
146
- describes mapping a resource key to database column.
146
+ describes mapping a resource key to a database column.
147
+
148
+ #### `capture_link_href <key>, as: <column>`
149
+ describes mapping a link href (as it appears on the hateous response) to a database column.
147
150
 
148
151
  #### `link <key>`
149
152
  describes materializing from a relation of the resource. This can be nested to any depth as shown above.
@@ -155,17 +158,20 @@ describes materializing the linked entity.
155
158
  This simulates a `:noop` event on the given topic and the `url` of the
156
159
  liked resource `<key>` as it appears on the response (`_links`) -- meaning the materializer for the given topic will be invoked.
157
160
 
158
- #### `after_upsert <method>` -- also `after_destroy`
159
- describes the name of the instance method to be invoked after a record was materialized.
161
+ #### `after_upsert <method> (, <method>(, ...))` -- also `after_destroy`
162
+ describes the name of the instance method(s) to be invoked after a record was materialized.
160
163
 
161
164
  ```ruby
162
165
  class ZoneMaterializer
163
166
  include Materialist::Materializer
164
167
 
165
- after_upsert :my_method
168
+ after_upsert :my_method, :my_second_method
166
169
 
167
170
  def my_method(record)
168
171
  end
172
+
173
+ def my_second_method(record)
174
+ end
169
175
  end
170
176
  ```
171
177
 
data/lib/materialist.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Materialist
2
- VERSION = '0.1.0'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -36,6 +36,15 @@ module Materialist
36
36
  attr_reader :key, :mapping
37
37
  end
38
38
 
39
+ class LinkHrefMapping
40
+ def initialize(key:, as:)
41
+ @key = key
42
+ @as = as
43
+ end
44
+
45
+ attr_reader :key, :as
46
+ end
47
+
39
48
  module ClassMethods
40
49
  attr_reader :__materialist_options, :__materialist_dsl_mapping_stack
41
50
 
@@ -55,6 +64,10 @@ module Materialist
55
64
  __materialist_dsl_mapping_stack.last << FieldMapping.new(key: key, as: as)
56
65
  end
57
66
 
67
+ def capture_link_href(key, as:)
68
+ __materialist_dsl_mapping_stack.last << LinkHrefMapping.new(key: key, as: as)
69
+ end
70
+
58
71
  def link(key)
59
72
  link_mapping = LinkMapping.new(key: key)
60
73
  __materialist_dsl_mapping_stack.last << link_mapping
@@ -67,12 +80,12 @@ module Materialist
67
80
  __materialist_options[:model_class] = klass
68
81
  end
69
82
 
70
- def after_upsert(method_name)
71
- __materialist_options[:after_upsert] = method_name
83
+ def after_upsert(*method_array)
84
+ __materialist_options[:after_upsert] = method_array
72
85
  end
73
86
 
74
- def after_destroy(method_name)
75
- __materialist_options[:after_destroy] = method_name
87
+ def after_destroy(*method_array)
88
+ __materialist_options[:after_destroy] = method_array
76
89
  end
77
90
  end
78
91
 
@@ -89,7 +102,7 @@ module Materialist
89
102
 
90
103
  if materialize_self?
91
104
  upsert_record.tap do |entity|
92
- instance.send(after_upsert, entity) if after_upsert
105
+ send_messages(after_upsert, entity) unless after_upsert.nil?
93
106
  end
94
107
  end
95
108
 
@@ -109,7 +122,7 @@ module Materialist
109
122
  return unless materialize_self?
110
123
  model_class.find_by(source_url: url).tap do |entity|
111
124
  entity.destroy!.tap do |entity|
112
- instance.send(after_destroy, entity) if after_destroy
125
+ send_messages(after_destroy, entity) unless after_destroy.nil?
113
126
  end if entity
114
127
  end
115
128
  end
@@ -177,7 +190,13 @@ module Materialist
177
190
  mapping.inject({}) do |result, m|
178
191
  case m
179
192
  when FieldMapping
180
- result.tap { |r| r[m.as] = resource.body[m.key] }
193
+ result.tap { |r| r[m.as] = serializable_value(resource.body[m.key]) }
194
+ when LinkHrefMapping
195
+ result.tap do |r|
196
+ if resource.body._links.include?(m.key)
197
+ r[m.as] = resource.body._links[m.key].href
198
+ end
199
+ end
181
200
  when LinkMapping
182
201
  resource.body._links.include?(m.key) ?
183
202
  result.merge(build_attributes(resource_at(resource.send(m.key).url), m.mapping || [])) :
@@ -188,6 +207,11 @@ module Materialist
188
207
  end
189
208
  end
190
209
 
210
+ def serializable_value(value)
211
+ value_is_complex_object = value.is_a?(Hash) || value.is_a?(Array)
212
+ value_is_complex_object ? value.to_json : value
213
+ end
214
+
191
215
  def resource_at(url)
192
216
  api_client.get(url, options: { enable_caching: false })
193
217
  rescue Routemaster::Errors::ResourceNotFound
@@ -202,6 +226,10 @@ module Materialist
202
226
  response_class: Routemaster::Responses::HateoasResponse
203
227
  )
204
228
  end
229
+
230
+ def send_messages(messages, arguments)
231
+ messages.each { |message| instance.send(message, arguments) }
232
+ end
205
233
  end
206
234
  end
207
235
  end
@@ -13,6 +13,8 @@ RSpec.describe Materialist::Materializer do
13
13
  persist_to :foobar
14
14
  capture :name
15
15
  capture :age, as: :how_old
16
+ capture_link_href :city, as: :city_url
17
+ capture_link_href :account, as: :account_url
16
18
 
17
19
  materialize_link :city
18
20
 
@@ -99,7 +101,8 @@ RSpec.describe Materialist::Materializer do
99
101
  end
100
102
 
101
103
  class Foobar < BaseModel
102
- attr_accessor :source_url, :name, :how_old, :age, :timezone, :country_tld
104
+ attr_accessor :source_url, :name, :how_old, :age, :timezone,
105
+ :country_tld, :city_url, :account_url
103
106
  end
104
107
 
105
108
  class City < BaseModel
@@ -117,6 +120,8 @@ RSpec.describe Materialist::Materializer do
117
120
  let(:city_body) {{ _links: { country: { href: country_url }}, name: 'paris', timezone: 'Europe/Paris' }}
118
121
  let(:source_url) { 'https://service.dev/foobars/1' }
119
122
  let(:source_body) {{ _links: { city: { href: city_url }}, name: 'jack', age: 30 }}
123
+ let(:complex_url) { 'https://service.dev/hashes/1' }
124
+ let(:complex_body) {{ _links: { city: { href: city_url }}, name: { first_name: 'Mo', last_name: 'Town' }, age: [30,31,44] }}
120
125
 
121
126
  def stub_resource(url, body)
122
127
  stub_request(:get, url).to_return(
@@ -133,6 +138,7 @@ RSpec.describe Materialist::Materializer do
133
138
  stub_resource source_url, source_body
134
139
  stub_resource country_url, country_body
135
140
  stub_resource city_url, city_body
141
+ stub_resource complex_url, complex_body
136
142
  end
137
143
 
138
144
  let(:action) { :create }
@@ -145,6 +151,7 @@ RSpec.describe Materialist::Materializer do
145
151
  expect(inserted.how_old).to eq source_body[:age]
146
152
  expect(inserted.timezone).to eq city_body[:timezone]
147
153
  expect(inserted.country_tld).to eq country_body[:tld]
154
+ expect(inserted.account_url).to be_nil
148
155
  end
149
156
 
150
157
  it "materializes linked record separately in db" do
@@ -154,6 +161,17 @@ RSpec.describe Materialist::Materializer do
154
161
  expect(inserted.name).to eq city_body[:name]
155
162
  end
156
163
 
164
+ context "when there are complex value types" do
165
+ let(:perform) { FoobarMaterializer.perform(complex_url, action) }
166
+
167
+ it "serialises the complex value into json" do
168
+ expect{perform}.to change{Foobar.count}.by 1
169
+ inserted = Foobar.find_by(source_url: complex_url)
170
+ expect(inserted.name).to eq complex_body[:name].to_json
171
+ expect(inserted.how_old).to eq complex_body[:age].to_json
172
+ end
173
+ end
174
+
157
175
  context "when record already exists" do
158
176
  let!(:record) { Foobar.create!(source_url: source_url, name: 'mo') }
159
177
 
@@ -255,6 +273,18 @@ RSpec.describe Materialist::Materializer do
255
273
  it "calls after_upsert method" do
256
274
  expect{ perform }.to change { record.actions_called[:after_upsert] }
257
275
  end
276
+
277
+ it "calls more than one after_upsert method" do
278
+ class FoobarMaterializer
279
+ after_upsert :my_method, :my_method2
280
+
281
+ def my_method2(entity)
282
+ entity.actions_called[:after_upsert2] = true
283
+ end
284
+ end
285
+ expect{ perform }.to change { record.actions_called[:after_upsert] }
286
+ .and change { record.actions_called[:after_upsert2] }
287
+ end
258
288
  end
259
289
  end
260
290
 
@@ -299,6 +329,18 @@ RSpec.describe Materialist::Materializer do
299
329
  expect{ perform }.to change { record.actions_called[:after_destroy] }
300
330
  end
301
331
 
332
+ it "calls more than one after_destroy method" do
333
+ class FoobarMaterializer
334
+ after_destroy :my_method, :my_method2
335
+
336
+ def my_method2(entity)
337
+ entity.actions_called[:after_destroy2] = true
338
+ end
339
+ end
340
+ expect{ perform }.to change { record.actions_called[:after_destroy] }
341
+ .and change { record.actions_called[:after_destroy2] }
342
+ end
343
+
302
344
  context "when resource doesn't exist locally" do
303
345
  it "does not raise error" do
304
346
  Foobar.destroy_all
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: 0.1.0
4
+ version: 1.0.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-09-12 00:00:00.000000000 Z
11
+ date: 2017-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq