etcher 1.3.0 → 1.4.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
  SHA256:
3
- metadata.gz: 84180c8738954c3de89c404a1e069faae6131c648f66c58cf52cc895fa416d0b
4
- data.tar.gz: abe217a1b453316529fa6e23d01cda222835999f4e9ac5c0acbbd3f2a9c600f2
3
+ metadata.gz: 4a7381f41e75ad83f44a491f33f396be3ffb5b401a1a72fdcef2086984424fff
4
+ data.tar.gz: '09b9c86d96af82fbc821e23c92e7966c97234e61625d3d23838471b930906629'
5
5
  SHA512:
6
- metadata.gz: 21c134f172e4bf53fb6c9d4b8738b24af2871a3463ed1bf103786b75c5e40f98be5e3732366f474b037c055caed16c58a6673d4b7006625db94e285472c823a3
7
- data.tar.gz: d923a76699e9806bed54951436cb55e164d3a71780758890b27db27355206e32dc15475d7db701e988702659074aa50f03387b71485977160ce6ed231734f57f
6
+ metadata.gz: 3d3008b4581dfd66426ba9e9c2ed0158241d130c2e68372f124369dd42c5893fed86aff36fe9e1b14612fff2139f39cf7e4b07492b5faac13699a3f0d87f609c
7
+ data.tar.gz: 885d3f522cefba39eeb8765fe671ea822d52edefc700d1633997825fd7cb61c834db7d6111cbd92881c5c9d232519e70bb4aa120027cc6ad432e82286d15fb99
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -28,7 +28,7 @@ ____
28
28
  [Use] strong acid or mordant to cut into the unprotected parts of a metal surface to create a design in intaglio (incised) in the metal.
29
29
  ____
30
30
 
31
- By using Etcher, you have a reliable way to load default configurations (i.e. {environment_link}, {json_link}, {yaml_link}) which can be validated and etched into _frozen_ records (i.e. {hash_link}, {data_link}, {struct_link}) for consumption within your application which doesn't violate the {demeter_link}. This comes complete with transformations and validations all via a simple Object API. Pairs well with the {xdg_link}, {runcom_link}, and {sod_link} gems.
31
+ By using Etcher, you have a reliable way to load default configurations (i.e. {environment_link}, {json_link}, {yaml_link}) which can be validated and etched into _frozen_ records (i.e. {hash_link}, {data_link}, {struct_link}) for consumption within your application which doesn't violate the {demeter_link}. This comes complete with transformations and validations all via a simple Object API and pairs well with the {xdg_link}, {runcom_link}, and {sod_link} gems.
32
32
 
33
33
  toc::[]
34
34
 
@@ -106,8 +106,8 @@ end
106
106
 
107
107
  model = Data.define :user, :home
108
108
 
109
- transformer = lambda do |content, key = :user|
110
- Dry::Monads::Success content.merge! key => content[key].upcase
109
+ transformer = lambda do |attributes, key = :user|
110
+ Dry::Monads::Success attributes.merge! key => attributes[key].upcase
111
111
  end
112
112
 
113
113
  Etcher::Registry.new(contract:, model:, transformers: [transformer])
@@ -122,7 +122,7 @@ The above can be broken down into a series of steps:
122
122
  . A {dry_schema_link} contract -- loaded with {dry_monads_link} extensions -- is created to verify untrusted attributes.
123
123
  . A model is created with attributes: `user` and `home`.
124
124
  . A registry is constructed with a custom contract, model, loader, and transformer.
125
- . Finally, we see a _successfully_ built configuration for further use.
125
+ . Finally, we see a _successfully_ built configuration for further use within your application.
126
126
 
127
127
  While this is a more advanced use case, you'll usually only need to register a contract and model. The loaders and transformers provide additional firepower in situations where you need to do more with your data. We'll look at each of these components in greater detail next.
128
128
 
@@ -132,11 +132,11 @@ While this is a more advanced use case, you'll usually only need to register a c
132
132
 
133
133
  As hinted at above, the complete sequence of steps are performed in the order listed:
134
134
 
135
- . *Load*: Each loader, if any, is called and merged with the previous loader to build initial content.
136
- . *Override*: Any overrides are merged with the result of the last loader to produce updated content. _In Version 2.0.0, this step happen after the Transform step._
137
- . *Transform*: Each transformer, if any, is called to transform and manipulate the content.
138
- . *Validate*: The contract is called to validate the content as previously loaded, overwritten, and transformed.
139
- . *Model*: The model consumes the content of the validated contract and creates a new record for you to use as needed.
135
+ . *Load*: Each loader, if any, is called and merged with the previous loader to build initial attributes.
136
+ . *Override*: Any overrides are merged with the result of the last loader to produce updated attributes. ⚠️ _In Version 2.0.0, this step will happen after the Transform step._
137
+ . *Transform*: Each transformer, if any, is called to transform and manipulate the attributes.
138
+ . *Validate*: The contract is called to validate the attributes as previously loaded, overwritten, and transformed.
139
+ . *Model*: The model consumes the attributes of the validated contract and creates a new record for you to use as needed.
140
140
 
141
141
  You can use the above steps as a reference when using this gem. Each step is explained in greater detail below.
142
142
 
@@ -150,7 +150,7 @@ Etcher::Registry.new
150
150
  # #<data Etcher::Registry contract=#<Proc:0x000000010e393550 contract.rb:7 (lambda)>, model=Hash, loaders=[], transformers=[]>
151
151
  ----
152
152
 
153
- Since the registry is a {data_link}, you can initialize with everything you need:
153
+ Since the registry is {data_link}, you can initialize with everything you need:
154
154
 
155
155
  [source,ruby]
156
156
  ----
@@ -175,11 +175,11 @@ registry = Etcher::Registry.new
175
175
 
176
176
  === Contracts
177
177
 
178
- Contracts are critical piece of this workflow as they provide a way to validate incoming data, remove unwanted data, and create a sanitized record for use in your application. Any contract that has the following behavior will work:
178
+ Contracts are a critical piece of this workflow as they provide a way to validate incoming data, remove unwanted data, and create a sanitized record for use in your application. Any contract that has the following behavior will work:
179
179
 
180
180
  * `#call`: Must be able to consume a {hash_link} and answer an object which can respond to `#to_monad`.
181
181
 
182
- The best gems which adhere to this interface are: {dry_schema_link} and {dry_validation_link}. You'll also want to make sure the {dry_monads_link} extensions are loaded as briefly shown earlier so the result will respond to `#to_monad`. Here's how to enable monad support if using both gems:
182
+ The best gems which adhere to this interface are: {dry_schema_link} and {dry_validation_link}. You'll also want to make sure the {dry_monads_link} extensions are loaded, as briefly shown earlier, so the result will respond to `#to_monad`. Here's how to enable monad support if using both gems:
183
183
 
184
184
  [source,ruby]
185
185
  ----
@@ -209,7 +209,7 @@ etcher.call from: "Mork", to: "Mindy"
209
209
  # Success({:from=>"Mork", :to=>"Mindy"})
210
210
  ----
211
211
 
212
- Here you can see the power of using a contract to validate your data both as a failure and a success. Unfortunately, with the success, we only get a {hash_link} as a record and it would be nice to structured model which which we'll look at next.
212
+ Here you can see the power of using a contract to validate your data both as a failure and a success. Unfortunately, with the success, we only get a {hash_link} as a record and it would be nice to structured record which will be explained shortly.
213
213
 
214
214
  === Types
215
215
 
@@ -267,7 +267,7 @@ model = Data.define :from, :to
267
267
  etcher = Etcher::Registry[model:].then { |registry| Etcher.new registry }
268
268
 
269
269
  etcher.call
270
- # Failure({:step=>:record, :payload=>"Missing keywords: :from, :to."})
270
+ # Failure({:step=>:model, :payload=>"Missing keywords: :from, :to."})
271
271
 
272
272
  etcher.call from: "Mork", to: "Mindy"
273
273
  # Success(#<data Model from="Mork", to="Mindy">)
@@ -344,7 +344,7 @@ loader = Etcher::Loaders::JSON.new "your/path/to/configuration.json",
344
344
  loader.call # Success({})
345
345
  ----
346
346
 
347
- If the file did exist and had content, you'd get a `Success` with a `Hash` of the contents.
347
+ Otherwise, if the file exists with content, you'll get a `Hash` wrapped as a `Success`.
348
348
 
349
349
  ℹ️ The logger is only used to log debug information when issues are encountered when reading from the file. This is done to reduce noise in your console when a configuration might have issues and can safely revert to the fallback in order to load the rest of the configuration.
350
350
 
@@ -369,7 +369,7 @@ loader = Etcher::Loaders::YAML.new "your/path/to/configuration.yml",
369
369
  loader.call # Success({})
370
370
  ----
371
371
 
372
- If the file did exist and had content, you'd get a `Success` with a `Hash` of the contents.
372
+ Otherwise, if the file exists with content, you'll get a `Hash` wrapped as a `Success`.
373
373
 
374
374
  ℹ️ The logger is only used to log debug information when issues are encountered when reading from the file. This is done to reduce noise in your console when a configuration might have issues and can safely revert to the fallback in order to load the rest of the configuration.
375
375
 
@@ -417,9 +417,9 @@ registry = Etcher::Registry.new.add_transformer MyTransformer
417
417
  Here are a few guidelines to using them:
418
418
 
419
419
  * They can be initialized with whatever requirements you might need.
420
- * They must respond to `#call` which takes a required `content` positional argument and answers a modified representation of this content as a monad with a `Hash` for content.
421
- * A second _optional_ positional `key` parameter should follow your `content` parameter when implementing your transformer. This allows you to quickly refactor the key later while also reducing key duplication throughout your implementation.
422
- * The `content` passed to your transformer will have symbolized keys so you don't need to do this yourself.
420
+ * They must respond to `#call` which takes a required `attributes` positional argument and answers a modified version of these attributes (`Hash`) wrapped as a monad.
421
+ * A second _optional_ positional `key` parameter should follow your `attributes` parameter when implementing your transformer. This allows you to quickly refactor the key later while also reducing key duplication throughout your implementation.
422
+ * The `attributes` passed to your transformer will have symbolized keys so you don't need to transform them further.
423
423
 
424
424
  Here are a few examples of where you could go with this:
425
425
 
@@ -429,7 +429,7 @@ The following capitalizes all values (which may or may not be good depending on
429
429
  ----
430
430
  require "dry/monads"
431
431
 
432
- Capitalize = -> content { Dry::Monads::Success content.transform_values!(&:capitalize) }
432
+ Capitalize = -> attributes { Dry::Monads::Success attributes.transform_values!(&:capitalize) }
433
433
  Capitalize.call(name: "test")
434
434
 
435
435
  # Success({:name=>"Test"})
@@ -441,9 +441,9 @@ The following updates current time relative to when configuration was transforme
441
441
  ----
442
442
  require "dry/monads"
443
443
 
444
- CurrentTime = lambda do |content, key = :at, at: Time.now|
445
- content.fetch(key) { at }
446
- .then { |value| Dry::Monads::Success content.merge!(key => value) }
444
+ CurrentTime = lambda do |attributes, key = :at, at: Time.now|
445
+ attributes.fetch(key) { at }
446
+ .then { |value| Dry::Monads::Success attributes.merge!(key => value) }
447
447
  end
448
448
 
449
449
  CurrentTime.call({})
@@ -469,7 +469,7 @@ class GitEmail
469
469
  @git = git
470
470
  end
471
471
 
472
- def call(content) = git.get("user.email").fmap { |value| content[key] = value }
472
+ def call(attributes) = git.get("user.email").fmap { |value| attributes[key] = value }
473
473
 
474
474
  private
475
475
 
@@ -516,7 +516,7 @@ Etcher.call name: "demo"
516
516
  # {:name=>"demo"}
517
517
  ----
518
518
 
519
- When called _and there are no issues_, you'll get the fully formed record as a result (in this case a Hash which is the default model). You'll never a get a monad when using `Etcher.call` because this is meant to resolve the monadic pipeline for you. If any failure is encountered, then Etcher will _abort_ with a fatal log message. Here's a variation of earlier examples which demonstrates fatal errors:
519
+ When called -- and there are no issues -- you'll get the fully formed record as a result (in this case a Hash which is the default model). You'll never a get a monad when using `Etcher.call` because this is meant to resolve the monadic pipeline for you. If any failure is encountered, then Etcher will _abort_ with a fatal log message. Here's a variation of earlier examples which demonstrates fatals:
520
520
 
521
521
  [source,ruby]
522
522
  ----
data/etcher.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "etcher"
5
- spec.version = "1.3.0"
5
+ spec.version = "1.4.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/etcher"
@@ -16,42 +16,39 @@ module Etcher
16
16
  end
17
17
 
18
18
  def call(**overrides)
19
- load(overrides.symbolize_keys!).then { |content| transform content }
20
- .bind { |content| validate content }
21
- .bind { |content| record content }
19
+ load(overrides.symbolize_keys!).then { |attributes| transform attributes }
20
+ .bind { |attributes| validate attributes }
21
+ .bind { |attributes| model attributes }
22
22
  end
23
23
 
24
24
  private
25
25
 
26
26
  attr_reader :registry
27
27
 
28
- # :reek:NestedIterators
29
- # :reek:TooManyStatements
30
28
  def load overrides
31
29
  registry.loaders
32
- .map { |loader| loader.call.fmap { |content| content.flatten_keys.symbolize_keys! } }
30
+ .map { |loader| loader.call.fmap { |pairs| pairs.flatten_keys.symbolize_keys! } }
33
31
  .each
34
- .with_object({}) { |content, all| content.bind { |body| all.merge! body } }
32
+ .with_object({}) { |attributes, all| attributes.bind { |body| all.merge! body } }
35
33
  .merge!(overrides.flatten_keys)
36
- .then { |content| Success content }
34
+ .then { |attributes| Success attributes }
37
35
  end
38
36
 
39
- # :reek:NestedIterators
40
- def transform content
41
- registry.transformers.reduce content do |all, transformer|
37
+ def transform attributes
38
+ registry.transformers.reduce attributes do |all, transformer|
42
39
  all.bind { |body| transformer.call body }
43
40
  end
44
41
  end
45
42
 
46
- def validate content
43
+ def validate attributes
47
44
  registry.contract
48
- .call(content)
45
+ .call(attributes)
49
46
  .to_monad
50
47
  .or { |result| Failure step: __method__, payload: result.errors.to_h }
51
48
  end
52
49
 
53
- def record content
54
- Success registry.model[**content.to_h].freeze
50
+ def model attributes
51
+ Success registry.model[**attributes.to_h].freeze
55
52
  rescue ArgumentError => error
56
53
  Failure step: __method__, payload: "#{error.message.capitalize}."
57
54
  end
@@ -4,8 +4,8 @@ require "dry/monads"
4
4
 
5
5
  module Etcher
6
6
  # A simple passthrough contract.
7
- Contract = lambda do |content|
8
- def content.to_monad = Dry::Monads::Success self unless content.respond_to? :to_monad
9
- content
7
+ Contract = lambda do |result|
8
+ def result.to_monad = Dry::Monads::Success self unless result.respond_to? :to_monad
9
+ result
10
10
  end
11
11
  end
@@ -18,7 +18,7 @@ module Etcher
18
18
 
19
19
  def call(**overrides)
20
20
  case builder.call(**overrides)
21
- in Success(content) then content
21
+ in Success(attributes) then attributes
22
22
  in Failure(step:, payload: String => payload)
23
23
  logger.fatal { "Build failure: #{step.inspect}. #{payload}" }
24
24
  kernel.abort
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: etcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,7 +35,7 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2024-04-03 00:00:00.000000000 Z
38
+ date: 2024-05-11 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: cogger
@@ -182,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
182
182
  - !ruby/object:Gem::Version
183
183
  version: '0'
184
184
  requirements: []
185
- rubygems_version: 3.5.7
185
+ rubygems_version: 3.5.10
186
186
  signing_key:
187
187
  specification_version: 4
188
188
  summary: A monadic configuration loader, transformer, and validator.
metadata.gz.sig CHANGED
Binary file