materialist 3.2.0 → 3.3.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: 8665cde57cae1468db10b2d04ca02ee83baccef5
4
- data.tar.gz: a2fe18fbfdb6e1aa039b3c1dc9a5c7150e67acf0
3
+ metadata.gz: f551f35e47a806f9f5e3b475feb35358f4a034b5
4
+ data.tar.gz: 8134a56b74346d367618b99b09604c0ded38a815
5
5
  SHA512:
6
- metadata.gz: c630af56d05969a23fc7a19149b588eeda385e4d30f494f123ef7cc8f4971f7352fab65b81b6d92cbba919fe3d3e4a68bfa886638854b3997bff05836a224cc8
7
- data.tar.gz: 330d44afc53a5214e4e95a3a5335f0fb83c3559fbdfd79d1ae215a030337269a6db68c48f277f216eb8fda2ce76144b742dda34290a37fd4559b8147765781b5
6
+ metadata.gz: 2a647bde4177b45a090e8a91a1a34b1dde10f1ac38adbe8d1588c161182113cd8f065511edd59f08a82e38721ebaa1260650af9840d4e1f032160a4739561af1
7
+ data.tar.gz: c660872899ce6526370260e7852d886ecd34abf2a4c0cdaf7178b11680c524db318ade68d8640ce00aa2a50630158f4242f20eec20f79b49f496b877c6a0c678
data/README.md CHANGED
@@ -75,8 +75,9 @@ end
75
75
 
76
76
  - `topics` (only when using in `.subscribe`): A string array of topics to be used.
77
77
  If not provided nothing would be materialized.
78
- - `sidekiq_options` (optional, default: `{ retry: 10 }`) -- See [Sidekiq docs](https://github.com/mperham/sidekiq/wiki/Advanced-Options#workers) for list of optiosn
78
+ - `sidekiq_options` (optional, default: `{ retry: 10 }`) -- See [Sidekiq docs](https://github.com/mperham/sidekiq/wiki/Advanced-Options#workers) for list of options
79
79
  - `metrics_client` (optional) -- You can pass your `STATSD` instance
80
+ - `notice_error` (optional) -- You can pass a lambda accepting two parameters (`exception` and `event`) -- Typical use case is to enrich error and send to NewRelic APM
80
81
 
81
82
  ### Routemaster Configuration
82
83
 
@@ -160,8 +161,8 @@ Here is what each part of the DSL mean:
160
161
 
161
162
  #### `sidekiq_options <options>`
162
163
  allows to override options for the Sidekiq job which does the materialization.
163
- Typically it will specify which queue to put the job on or how many times
164
- should the job try to retry. These options override the options specified in
164
+ Typically it will specify which queue to put the job on or how many times
165
+ should the job try to retry. These options override the options specified in
165
166
  `Materialist.configuration.sidekiq_options`.
166
167
 
167
168
  #### `persist_to <model_name>`
@@ -180,6 +181,14 @@ describes mapping a resource key to a database column.
180
181
  #### `capture_link_href <key>, as: <column>`
181
182
  describes mapping a link href (as it appears on the hateous response) to a database column.
182
183
 
184
+ You can optionally provide a block for parsing the url:
185
+
186
+ ```ruby
187
+ capture_link_href :rider, as: :rider_id do |url|
188
+ url.split('/').last
189
+ end
190
+ ```
191
+
183
192
  #### `link <key>, enable_caching: <enable_caching> (default: false)`
184
193
  describes materializing from a relation of the resource. This can be nested to any depth as shown above.
185
194
 
data/RELEASE_NOTES.md CHANGED
@@ -1,8 +1,18 @@
1
+ ## Next
2
+
3
+ _description of next release_
4
+
5
+ ## 3.3.0
6
+
7
+ Features:
8
+ - Add support for parsing url when using `capture_link_href`
9
+ - Add support for providing `notice_error` on configuration.
10
+
1
11
  ## 3.2.0
2
12
 
3
13
  Features:
4
14
  - For linked resources specified by `link` an option to `enable_caching` can now be explicitly set. This
5
- tells Routemaster to use or not use the drain cache.
15
+ tells Routemaster to use or not use the drain cache.
6
16
 
7
17
  ## 3.1.0
8
18
 
@@ -12,8 +22,8 @@ Features:
12
22
 
13
23
  Notes:
14
24
 
15
- Materialist::EventWorker has been moved to Materialist::Workers::Event, but the original has
16
- been left there for backwards compatibility. It will be removed in a later major release.
25
+ Materialist::EventWorker has been moved to Materialist::Workers::Event, but the original has
26
+ been left there for backwards compatibility. It will be removed in a later major release.
17
27
 
18
28
  ## 3.0.0
19
29
 
data/lib/configuration.rb CHANGED
@@ -14,12 +14,13 @@ module Materialist
14
14
  end
15
15
 
16
16
  class Configuration
17
- attr_accessor :topics, :sidekiq_options, :metrics_client
17
+ attr_accessor :topics, :sidekiq_options, :metrics_client, :notice_error
18
18
 
19
19
  def initialize
20
20
  @topics = []
21
21
  @sidekiq_options = {}
22
22
  @metrics_client = NullMetricsClient
23
+ @notice_error = nil
23
24
  end
24
25
 
25
26
  class NullMetricsClient
data/lib/materialist.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require_relative './configuration'
2
2
 
3
3
  module Materialist
4
- VERSION = '3.2.0'
4
+ VERSION = '3.3.0'
5
5
  end
@@ -10,8 +10,12 @@ module Materialist
10
10
  __materialist_dsl_mapping_stack.last << FieldMapping.new(key: key, as: as)
11
11
  end
12
12
 
13
- def capture_link_href(key, as:)
14
- __materialist_dsl_mapping_stack.last << LinkHrefMapping.new(key: key, as: as)
13
+ def capture_link_href(key, as:, &url_parser_block)
14
+ __materialist_dsl_mapping_stack.last << LinkHrefMapping.new(
15
+ key: key,
16
+ as: as,
17
+ url_parser: url_parser_block
18
+ )
15
19
  end
16
20
 
17
21
  def link(key, enable_caching: false)
@@ -7,7 +7,9 @@ module Materialist
7
7
  @as = as
8
8
  end
9
9
 
10
- attr_reader :key, :as
10
+ def map(resource)
11
+ { @as => resource.body[@key] }
12
+ end
11
13
  end
12
14
  end
13
15
  end
@@ -2,12 +2,22 @@ module Materialist
2
2
  module Materializer
3
3
  module Internals
4
4
  class LinkHrefMapping
5
- def initialize(key:, as:)
5
+ def initialize(key:, as:, url_parser: nil)
6
6
  @key = key
7
7
  @as = as
8
+ @url_parser = url_parser
8
9
  end
9
10
 
10
- attr_reader :key, :as
11
+ def map(resource)
12
+ return unless link = resource.body._links[@key]
13
+ { @as => url_parser.call(link.href) }
14
+ end
15
+
16
+ private
17
+
18
+ def url_parser
19
+ @url_parser || ->url { url }
20
+ end
11
21
  end
12
22
  end
13
23
  end
@@ -8,7 +8,22 @@ module Materialist
8
8
  @mapping = []
9
9
  end
10
10
 
11
- attr_reader :key, :enable_caching, :mapping
11
+ def map(resource)
12
+ return unless linked_resource = linked_resource(resource)
13
+ mapping.map{ |m| m.map(linked_resource) }.compact.reduce(&:merge)
14
+ end
15
+
16
+ attr_reader :mapping
17
+
18
+ private
19
+
20
+ def linked_resource(resource)
21
+ return unless resource.body._links.include?(@key)
22
+ return unless sub_resource = resource.send(@key)
23
+ sub_resource.show(enable_caching: @enable_caching)
24
+ rescue Routemaster::Errors::ResourceNotFound
25
+ nil
26
+ end
12
27
  end
13
28
  end
14
29
  end
@@ -75,7 +75,7 @@ module Materialist
75
75
  })
76
76
  end
77
77
 
78
- def mapping
78
+ def mappings
79
79
  options.fetch :mapping
80
80
  end
81
81
 
@@ -112,49 +112,17 @@ module Materialist
112
112
  end
113
113
 
114
114
  def attributes
115
- build_attributes root_resource, mapping
115
+ mappings.map{ |m| m.map(root_resource) }.compact.reduce(&:merge) || {}
116
116
  end
117
117
 
118
118
  def root_resource
119
- @_root_resource ||= resource_at(url)
120
- end
121
-
122
- def build_attributes(resource, mapping)
123
- return {} unless resource
124
-
125
- mapping.inject({}) do |result, m|
126
- case m
127
- when FieldMapping
128
- result.tap { |r| r[m.as] = resource.body[m.key] }
129
- when LinkHrefMapping
130
- result.tap do |r|
131
- if resource.body._links.include?(m.key)
132
- r[m.as] = resource.body._links[m.key].href
133
- end
134
- end
135
- when LinkMapping
136
- resource.body._links.include?(m.key) ?
137
- result.merge(build_attributes(linked_resource(resource, m), m.mapping || [])) :
138
- result
139
- else
140
- result
141
- end
119
+ @_root_resource ||= begin
120
+ api_client.get(url, options: { enable_caching: false })
121
+ rescue Routemaster::Errors::ResourceNotFound
122
+ nil
142
123
  end
143
124
  end
144
125
 
145
- def linked_resource(resource, mapping)
146
- resource_at(resource.send(mapping.key).url, enable_caching: mapping.enable_caching)
147
- end
148
-
149
- def resource_at(url, enable_caching: false)
150
- api_client.get(url, options: { enable_caching: enable_caching })
151
- rescue Routemaster::Errors::ResourceNotFound
152
- # this is due to a race condition between an upsert event
153
- # and a :delete event
154
- # when this happens we should silently ignore the case
155
- nil
156
- end
157
-
158
126
  def api_client
159
127
  @_api_client ||= Routemaster::APIClient.new(
160
128
  response_class: Routemaster::Responses::HateoasResponse
@@ -16,8 +16,9 @@ module Materialist
16
16
 
17
17
  report_latency(topic, timestamp) if timestamp
18
18
  report_stats(topic, action, :success)
19
- rescue
19
+ rescue Exception => exception
20
20
  report_stats(topic, action, :failure)
21
+ notice_error(exception, event)
21
22
  raise
22
23
  end
23
24
 
@@ -38,6 +39,11 @@ module Materialist
38
39
  tags: ["action:#{action}", "topic:#{topic}"]
39
40
  )
40
41
  end
42
+
43
+ def notice_error(exception, event)
44
+ return unless handler = Materialist.configuration.notice_error
45
+ handler.call(exception, event)
46
+ end
41
47
  end
42
48
  end
43
49
  end
@@ -15,6 +15,9 @@ RSpec.describe Materialist::Materializer do
15
15
  capture :name
16
16
  capture :age, as: :how_old
17
17
  capture_link_href :city, as: :city_url
18
+ capture_link_href :city, as: :city_id do |url|
19
+ url.split('/').last.to_i
20
+ end
18
21
  capture_link_href :account, as: :account_url
19
22
 
20
23
  materialize_link :city
@@ -81,6 +84,8 @@ RSpec.describe Materialist::Materializer do
81
84
  expect(inserted.timezone).to eq city_body[:timezone]
82
85
  expect(inserted.country_tld).to eq country_body[:tld]
83
86
  expect(inserted.account_url).to be_nil
87
+ expect(inserted.city_url).to eq city_url
88
+ expect(inserted.city_id).to eq 1
84
89
  end
85
90
 
86
91
  it "materializes linked record separately in db" do
@@ -48,6 +48,20 @@ RSpec.describe Materialist::Workers::Event do
48
48
  )
49
49
  expect{ perform }.to raise_error error
50
50
  end
51
+
52
+ context 'when there is notice_error configured' do
53
+ let(:configuration) { Materialist::Configuration.new.tap{ |c| c.notice_error = func } }
54
+ let(:func) { double }
55
+
56
+ before do
57
+ allow(Materialist).to receive(:configuration).and_return configuration
58
+ end
59
+
60
+ it 'calls the configured notice_error func' do
61
+ expect(func).to receive(:call).with(error, event)
62
+ expect{ perform }.to raise_error error
63
+ end
64
+ end
51
65
  end
52
66
 
53
67
  context 'when event has a timestamp' do
data/spec/schema.rb CHANGED
@@ -9,6 +9,7 @@ ActiveRecord::Schema.define do
9
9
  t.string :timezone
10
10
  t.string :country_tld
11
11
  t.string :city_url
12
+ t.integer :city_id
12
13
  t.string :account_url
13
14
 
14
15
  t.timestamps
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: 3.2.0
4
+ version: 3.3.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: 2018-04-16 00:00:00.000000000 Z
11
+ date: 2018-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq