tdc 0.2.3 → 0.3.3

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
  SHA256:
3
- metadata.gz: 3ea4c40daa383ebc80a1109132a3a8ded7bb6f89a77cb49b928bed2db838fbf6
4
- data.tar.gz: fda5f7f22c87bcb36a7b4c072ad85809bb1f1f78e7bb621396fa746511c34dd0
3
+ metadata.gz: e58c0fcfbfa32aa0dde6627786e39bbfaff4140d3326f144925113031163faf8
4
+ data.tar.gz: e9b5f186a199bd2cc3479fd9fd48087fd0f1d433006c03f2502c2cb48c6f300d
5
5
  SHA512:
6
- metadata.gz: d085e28662d3038b7609fb58d7e8b50fceca95a624cc9d0192b27d803f31bbaa1fff87996a93500a91557a8c45fc1b5adad26f4f6b6fe4dbf7bffafb11782640
7
- data.tar.gz: 1ae1baacafb85ec5fbc8ed58d7f2de790cf68b75fa84461712f0b7e3cbf7f361335005cfdb8c23dd8e3c39576bdc496aa27b9272ef059f54ef2fb8f6f9638a73
6
+ metadata.gz: 10a3a536987b80e57169defc47b65496550fc3c9ba4fa91d9c6ec448b8debd77d24d44cf5dbe047d708979fd4d29e4b1186ef712d0cfcb0b094cd0418d6d2524
7
+ data.tar.gz: cfd63f4adcb438992e71a4e9ac8c20024c9b1f0d68d4a8eda5765456cb7054c602a3b7f97178f66f5c5e0876314180fd42404c7100d29382d544834e2239f010
@@ -10,6 +10,9 @@ AllCops:
10
10
  Layout/EmptyLinesAroundAttributeAccessor:
11
11
  Enabled: true
12
12
 
13
+ Metrics/LineLength:
14
+ Max: 120
15
+
13
16
  # Rubocop and I cannot agree.
14
17
  Layout/MultilineMethodCallBraceLayout:
15
18
  Enabled: false
@@ -17,6 +20,15 @@ Layout/MultilineMethodCallBraceLayout:
17
20
  Layout/SpaceAroundMethodCallOperator:
18
21
  Enabled: true
19
22
 
23
+ Lint/DeprecatedOpenSSLConstant:
24
+ Enabled: true
25
+
26
+ Lint/DuplicateElsifCondition:
27
+ Enabled: true
28
+
29
+ Lint/MixedRegexpCaptureTypes:
30
+ Enabled: true
31
+
20
32
  Lint/RaiseException:
21
33
  Enabled: true
22
34
 
@@ -35,9 +47,6 @@ RSpec/AnyInstance:
35
47
  RSpec/ExampleLength:
36
48
  Max: 15
37
49
 
38
- Metrics/LineLength:
39
- Max: 120
40
-
41
50
  RSpec/DescribeClass:
42
51
  Enabled: false
43
52
 
@@ -59,11 +68,24 @@ RSpec/MultipleExpectations:
59
68
  RSpec/SubjectStub:
60
69
  Enabled: false
61
70
 
71
+ Style/AccessorGrouping:
72
+ Enabled: true
73
+
74
+ Style/ArrayCoercion:
75
+ Enabled: true
76
+
77
+ Style/BisectedAttrAccessor:
78
+ Enabled: true
79
+
62
80
  Style/BlockDelimiters:
63
81
  Enabled: true
64
82
  EnforcedStyle: line_count_based
65
83
  BracesRequiredMethods:
66
84
  - 'let'
85
+ - 'subject'
86
+
87
+ Style/CaseLikeIf:
88
+ Enabled: true
67
89
 
68
90
  Style/Documentation:
69
91
  Enabled: false
@@ -78,9 +100,15 @@ Style/ExponentialNotation:
78
100
  Style/FrozenStringLiteralComment:
79
101
  Enabled: false
80
102
 
103
+ Style/HashAsLastArrayItem:
104
+ Enabled: true
105
+
81
106
  Style/HashEachMethods:
82
107
  Enabled: true
83
108
 
109
+ Style/HashLikeCase:
110
+ Enabled: true
111
+
84
112
  Style/HashTransformKeys:
85
113
  Enabled: true
86
114
 
@@ -92,6 +120,21 @@ Style/HashSyntax:
92
120
  Exclude:
93
121
  - 'Rakefile'
94
122
 
123
+ Style/RedundantAssignment:
124
+ Enabled: true
125
+
126
+ Style/RedundantFetchBlock:
127
+ Enabled: true
128
+
129
+ Style/RedundantFileExtensionInRequire:
130
+ Enabled: true
131
+
132
+ Style/RedundantRegexpCharacterClass:
133
+ Enabled: true
134
+
135
+ Style/RedundantRegexpEscape:
136
+ Enabled: true
137
+
95
138
  # No need to mention StandardError.
96
139
  Style/RescueStandardError:
97
140
  EnforcedStyle: implicit
@@ -6,6 +6,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.3] - 2020-08-04
10
+
11
+ - Add the `empty?` method to `CatalogEntries`
12
+ - Evaluate `_atx` attribute values against a `Time.zone` instance
13
+
14
+ ## [0.3.2] - 2020-07-27
15
+
16
+ - Return `self` from `DefinitionResolver#configure_current_catalog` to make it chainable
17
+
18
+ ## [0.3.1] - 2020-07-25
19
+
20
+ - Support DefinitionResolver instance registration
21
+
22
+ ## [0.3.0] - 2020-07-19
23
+
24
+ - Introduce the DefinitionResolver abstraction
25
+
26
+ ## [0.2.4] - 2020-07-19
27
+
28
+ - Improve Tdc::MissingOverrideError diagnostics
29
+
9
30
  ## [0.2.3] - 2020-05-21
10
31
 
11
32
  - Update the diagram in the README
data/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  **Extension Points**
6
6
 
7
- Define your own test data generators by inheriting from ```StandardGenerator``` or ```Singular Generator```.
7
+ Define your own test data generators by inheriting from ```StandardGenerator``` or ```SingularGenerator```. Best practice is to define an ```ApplicationStandardGenerator``` and an ```ApplicationSingularGenerator``` and have all other generators inherit from them.
8
+
9
+ Define your own definition resolvers by inheriting from ```DefinitionResolver```. Best practice is to define an ```ApplicationDefinitionResolver``` and all other definition resolvers inherit from it.
8
10
 
9
11
  During generation the test data catalog will be represented by ```CatalogEntries``` that are populated by reading from ```YAML``` files with a ```DataDefinitionReader``` or provided directly by an ```InMemoryDataDefinition```.
10
12
 
Binary file
data/lib/tdc.rb CHANGED
@@ -33,6 +33,11 @@ require "tdc/generators/configurable_generator"
33
33
  require "tdc/generators/singular_generator"
34
34
  require "tdc/generators/standard_generator"
35
35
 
36
+ # Definition Resolvers
37
+ require "tdc/definition_resolvers"
38
+ require "tdc/definition_resolvers/definition_resolver"
39
+ require "tdc/definition_resolvers/tag_resolver"
40
+
36
41
  #
37
42
  # A framework for building a Test Data Catalog
38
43
  #
@@ -4,7 +4,7 @@ module Tdc
4
4
  #
5
5
  class DataDefinition
6
6
  def read(*_path_elements)
7
- raise MissingOverrideError
7
+ raise MissingOverrideError, "Implement the 'read' method"
8
8
  end
9
9
 
10
10
  def with_indifferent_access
@@ -0,0 +1,7 @@
1
+ module Tdc
2
+ #
3
+ # Namespace to host definition resolvers.
4
+ #
5
+ module DefinitionResolvers
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ module Tdc
2
+ module DefinitionResolvers
3
+ #
4
+ # Base class for any definition resolver.
5
+ #
6
+ class DefinitionResolver
7
+ attr_reader :current_catalog
8
+
9
+ def configure_current_catalog(current_catalog)
10
+ @current_catalog = current_catalog
11
+
12
+ self
13
+ end
14
+
15
+ def resolve(_instance_definition)
16
+ raise Tdc::MissingOverrideError, "Implement the 'resolve' method"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ module Tdc
2
+ module DefinitionResolvers
3
+ #
4
+ # Knows how to resolve the tag value for the specified instance_definition key by replacing it
5
+ # with an object sourced from the current catalog.
6
+ #
7
+ class TagResolver < Tdc::DefinitionResolvers::DefinitionResolver
8
+ attr_reader :key, :source
9
+
10
+ def initialize(key:, source:)
11
+ @key = key
12
+ @source = source
13
+ end
14
+
15
+ def resolve(instance_definition)
16
+ return unless instance_definition.key?(key)
17
+
18
+ # Lookup the source catalog entry in the current_catalog.
19
+ catalog_entry = instance_eval("current_catalog.#{source}", __FILE__, __LINE__)
20
+
21
+ # Before resolution the instance definition value is a tag.
22
+ tag = instance_definition[key]
23
+
24
+ # Use the tag to source an object from the current catalog.
25
+ sourced_object = catalog_entry.send(tag)
26
+
27
+ unless sourced_object
28
+ message = "Could not find a tag reference for '#{key}' in the catalog entries provided."
29
+
30
+ raise Tdc::FatalError, message
31
+ end
32
+
33
+ # Replace the tag value with the sourced object.
34
+ instance_definition[key] = sourced_object
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,6 +1,6 @@
1
1
  module Tdc
2
2
  #
3
- # Namespace to host generators
3
+ # Namespace to host generators.
4
4
  #
5
5
  module Generators
6
6
  end
@@ -8,6 +8,10 @@ module Tdc
8
8
  def add_catalog_entry(tag, entry)
9
9
  send("#{tag}=", entry)
10
10
  end
11
+
12
+ def empty?
13
+ to_h.empty?
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -14,7 +14,7 @@ module Tdc
14
14
 
15
15
  def run_resolvers_and_generate_instance
16
16
  run_atx_resolvers(instance_definition)
17
- run_tag_resolvers(instance_definition)
17
+ run_definition_resolvers(instance_definition)
18
18
 
19
19
  generate_instance
20
20
  end
@@ -23,13 +23,13 @@ module Tdc
23
23
  # Hook method: subclasses are expected to define how to generate a model instance.
24
24
  #
25
25
  def generate_instance
26
- raise Tdc::MissingOverrideError
26
+ raise Tdc::MissingOverrideError, "Implement the 'generate_instance' method"
27
27
  end
28
28
 
29
29
  #
30
30
  # Hook method: subclasses may include the DefinitionResolvable concern to override.
31
31
  #
32
- def run_tag_resolvers(_instance_definition)
32
+ def run_definition_resolvers(_instance_definition)
33
33
  # Do nothing
34
34
  end
35
35
 
@@ -44,12 +44,15 @@ module Tdc
44
44
  def run_atx_resolvers(instance_definition)
45
45
  atx_definitions = instance_definition.select { |k, _v| /_atx$/ =~ k }
46
46
 
47
+ # ARM (2020-08-04): Move all the way out so that all generators use the same atx_context.
48
+ atx_context = Time.zone
49
+
47
50
  atx_definitions.each do |k, v|
48
51
  # Remove the original _atx attribute.
49
52
  instance_definition.delete(k)
50
53
 
51
54
  # Add a standard _at attribute.
52
- instance_definition[k.delete_suffix("x")] = eval(v) # rubocop:disable Security/Eval
55
+ instance_definition[k.delete_suffix("x")] = atx_context.instance_eval(v)
53
56
  end
54
57
  end
55
58
  end
@@ -1,61 +1,48 @@
1
1
  module Tdc
2
2
  module Generators
3
3
  #
4
- # Knows how to resolve tag values in an instance definition. The tag value will be replaced
5
- # with a model instance from the current catalog.
4
+ # Knows how to resolve attribute values in an instance definition. The attribute value will be replaced
5
+ # by the result of invoking the registered resolver.
6
6
  #
7
- # The resolve_tag class macro is provided for generators to define tag resolution.
7
+ # The resolve_tag class macro is provided for generators to define tag resolution. The test data definition
8
+ # YAML file has attribute values than contain a catalog entry tag.
8
9
  #
9
10
  # Example:
10
11
  #
11
- # Suppose a particular instance definition contained { subcomponent: sc_snackers_minis }
12
- # then a generator could resolve the subcomponent by defining:
12
+ # Suppose a particular instance definition contained { subcomponent: sc_snackers_minis } then a generator
13
+ # could resolve the subcomponent tag to the current catalog by defining:
13
14
  #
14
15
  # resolve_tag key: :subcomponent, source: "item_master.items"
15
16
  #
17
+ # The register_definition_resolver class macro is provided for generators to define and register their own
18
+ # definition resolvers. The test data definition YAML file has attribute values than contain an arbitrary
19
+ # value that will typically be replaced by an instance of an object returned by the specified resolver.
20
+ #
16
21
  module DefinitionResolvable
17
22
  extend ActiveSupport::Concern
18
23
 
19
24
  included do
20
- class_attribute :_tag_resolvers, instance_writer: false
21
- self._tag_resolvers = []
25
+ class_attribute :_definition_resolvers, instance_writer: false
26
+
27
+ self._definition_resolvers = []
22
28
  end
23
29
 
24
30
  class_methods do
25
- def resolve_tag(key:, source:)
26
- _tag_resolvers << [key, source]
31
+ def register_definition_resolver(resolver_instance)
32
+ _definition_resolvers << resolver_instance
27
33
  end
28
- end
29
34
 
30
- def run_tag_resolvers(instance_definition)
31
- _tag_resolvers.each { |key, source| _resolve_tag_reference(instance_definition, key, source) }
35
+ def resolve_tag(key:, source:)
36
+ register_definition_resolver(Tdc::DefinitionResolvers::TagResolver.new(key: key, source: source))
37
+ end
32
38
  end
33
39
 
34
- private
40
+ def run_definition_resolvers(instance_definition)
41
+ _definition_resolvers.each do |definition_resolver|
42
+ definition_resolver.configure_current_catalog(current_catalog)
35
43
 
36
- #
37
- # Replace the tag value for the specified instance_definition key with an object sourced from the current catalog.
38
- #
39
- def _resolve_tag_reference(instance_definition, key, source)
40
- return unless instance_definition.key?(key)
41
-
42
- # Lookup the source catalog entry in the current_catalog.
43
- catalog_entry = instance_eval("current_catalog.#{source}", __FILE__, __LINE__)
44
-
45
- # Before resolution the instance definition value is a tag.
46
- tag = instance_definition[key]
47
-
48
- # Use the tag to source an object from the current catalog.
49
- sourced_object = catalog_entry.send(tag)
50
-
51
- unless sourced_object
52
- message = "Could not find a tag reference for '#{key}' in the catalog entries provided."
53
-
54
- raise Tdc::FatalError, message
44
+ definition_resolver.resolve(instance_definition)
55
45
  end
56
-
57
- # Replace the tag value with the sourced object.
58
- instance_definition[key] = sourced_object
59
46
  end
60
47
  end
61
48
  end
@@ -12,11 +12,11 @@ module Tdc
12
12
  end
13
13
 
14
14
  def generate
15
- raise Tdc::MissingOverrideError
15
+ raise Tdc::MissingOverrideError, "Implement the 'generate' method"
16
16
  end
17
17
 
18
18
  def instance_definitions
19
- raise Tdc::MissingOverrideError
19
+ raise Tdc::MissingOverrideError, "Implement the 'instance_definitions' method"
20
20
  end
21
21
  end
22
22
  end
@@ -6,12 +6,6 @@ module Tdc
6
6
  # See also StandardGenerator.
7
7
  #
8
8
  class SingularGenerator < Tdc::Generators::ConfigurableGenerator
9
- def initialize(data_definition, current_catalog)
10
- super
11
-
12
- @additional_definitions = {}
13
- end
14
-
15
9
  def with_definition(additional_definitions)
16
10
  @additional_definitions = additional_definitions.stringify_keys.reject { |_, v| v == :missing_definition }
17
11
 
@@ -19,13 +13,17 @@ module Tdc
19
13
  end
20
14
 
21
15
  def generate
22
- configure_instance_definition(singular_instance_definition.merge(@additional_definitions))
16
+ configure_instance_definition(singular_instance_definition.merge(additional_definitions))
23
17
 
24
18
  run_resolvers_and_generate_instance
25
19
  end
26
20
 
27
21
  private
28
22
 
23
+ def additional_definitions
24
+ @additional_definitions || {}
25
+ end
26
+
29
27
  def singular_instance_definition
30
28
  all_instance_definitions = instance_definitions
31
29
 
@@ -1,7 +1,3 @@
1
1
  module Tdc
2
- class MissingOverrideError < Tdc::FatalError
3
- def initialize
4
- super("Must be implemented")
5
- end
6
- end
2
+ MissingOverrideError = Class.new(Tdc::FatalError)
7
3
  end
@@ -1,3 +1,3 @@
1
1
  module Tdc
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.3"
3
3
  end
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
8
8
 
9
9
  spec.summary = "A simple framework for creating a Test Data Catalog"
10
10
  spec.homepage = "https://github.com/nulogy/tdc"
11
+ spec.license = "MIT"
11
12
 
12
13
  spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
13
14
 
@@ -31,7 +32,7 @@ Gem::Specification.new do |spec|
31
32
 
32
33
  spec.add_development_dependency "rake", ">= 12.1", "< 13.1"
33
34
  spec.add_development_dependency "rspec", ">= 3.9", "< 4.0"
34
- spec.add_development_dependency "rubocop", "~> 0.82"
35
- spec.add_development_dependency "rubocop-rspec", "~> 1.38"
35
+ spec.add_development_dependency "rubocop", "~> 0.88"
36
+ spec.add_development_dependency "rubocop-rspec", "~> 1.42"
36
37
  spec.add_development_dependency "simplecov", "~> 0.17"
37
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tdc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alistair McKinnell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-21 00:00:00.000000000 Z
11
+ date: 2020-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -70,28 +70,28 @@ dependencies:
70
70
  requirements:
71
71
  - - "~>"
72
72
  - !ruby/object:Gem::Version
73
- version: '0.82'
73
+ version: '0.88'
74
74
  type: :development
75
75
  prerelease: false
76
76
  version_requirements: !ruby/object:Gem::Requirement
77
77
  requirements:
78
78
  - - "~>"
79
79
  - !ruby/object:Gem::Version
80
- version: '0.82'
80
+ version: '0.88'
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: rubocop-rspec
83
83
  requirement: !ruby/object:Gem::Requirement
84
84
  requirements:
85
85
  - - "~>"
86
86
  - !ruby/object:Gem::Version
87
- version: '1.38'
87
+ version: '1.42'
88
88
  type: :development
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
- version: '1.38'
94
+ version: '1.42'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: simplecov
97
97
  requirement: !ruby/object:Gem::Requirement
@@ -128,6 +128,9 @@ files:
128
128
  - lib/tdc.rb
129
129
  - lib/tdc/data_definition.rb
130
130
  - lib/tdc/data_definition_file_reader.rb
131
+ - lib/tdc/definition_resolvers.rb
132
+ - lib/tdc/definition_resolvers/definition_resolver.rb
133
+ - lib/tdc/definition_resolvers/tag_resolver.rb
131
134
  - lib/tdc/fatal_error.rb
132
135
  - lib/tdc/generators.rb
133
136
  - lib/tdc/generators/catalog_entries.rb
@@ -143,7 +146,8 @@ files:
143
146
  - lib/tdc/with_indifferent_access_decorator.rb
144
147
  - tdc.gemspec
145
148
  homepage: https://github.com/nulogy/tdc
146
- licenses: []
149
+ licenses:
150
+ - MIT
147
151
  metadata:
148
152
  homepage_uri: https://github.com/nulogy/tdc
149
153
  changelog_uri: https://github.com/nulogy/tdc/blob/master/CHANGELOG.md
@@ -164,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
168
  - !ruby/object:Gem::Version
165
169
  version: '0'
166
170
  requirements: []
167
- rubygems_version: 3.1.3
171
+ rubygems_version: 3.1.4
168
172
  signing_key:
169
173
  specification_version: 4
170
174
  summary: A simple framework for creating a Test Data Catalog