tdc 0.4.2 → 0.4.6

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: 83b4405ab9ec996fbab35d7228931e03d5bf18966df916b631d36d6aecca4393
4
- data.tar.gz: 942728ff3d354bb5dc516c777606766b798ae218b4fd85ec4823cfad7e9d1875
3
+ metadata.gz: a605f44cef27e72e80f13f582363886ca57b61238bec36ff2f3367c2c0cd4973
4
+ data.tar.gz: a61883e606e164fa260f02c3b2588a352600b54b6c0fc9e8b0ae9fc7df6d3970
5
5
  SHA512:
6
- metadata.gz: 1a783d54d2a3af00fcd0d8366b1a55190503fda3350308179f5eb778f2fab6f3601b7c6eded92bd27a123a39303160ffa19381902228e8e11ab5f4213deda20c
7
- data.tar.gz: 5cc30405e4369c739e5a77370bf663d0813a2a72e2bdbaa7791bd8c1f966c5337c477689c4f968b82d20ee41bc3d22f94baa0731fb0d38948f6001137d4f56c6
6
+ metadata.gz: 2f2d9ac1591cf59bbc6c4bc2c128f5a891cef41c5399b480215f4644dae499f24a8f68bc4e3aef729e66d4f99aee978b4be523d82d58e5757b536bec19ae973e
7
+ data.tar.gz: 5b69a6c7393477eab60ffea42f8c0764ab1a289fb791c952e3f56f7ad6e9e368f9dfbc9229b82cddb431f6bd5fe637a9fa99dbc3428eb52f75940a0984004a47
@@ -15,9 +15,16 @@ Layout/LineLength:
15
15
  Layout/MultilineMethodCallBraceLayout:
16
16
  Enabled: false
17
17
 
18
- Metrics/BlockLength:
18
+ # Revisit. Seems a little harsh.
19
+ Lint/MissingSuper:
19
20
  Enabled: false
20
21
 
22
+ Metrics/BlockLength:
23
+ Exclude:
24
+ - 'tdc.gemspec'
25
+ - '**/*_shared_example.rb'
26
+ - '**/*_spec.rb'
27
+
21
28
  Naming/MemoizedInstanceVariableName:
22
29
  EnforcedStyleForLeadingUnderscores: required
23
30
 
@@ -6,8 +6,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.4.6] - 2020-09-26
10
+
11
+ - Better error message when a tag cannot be resolved
12
+
13
+ Note: version `0.4.5` was yanked from RubyGems.
14
+
15
+ ## [0.4.4.1] - 2020-09-12
16
+
17
+ - Avoid registering the same class of interpreter a second time
18
+
19
+ ## [0.4.4] - 2020-08-25
20
+
21
+ #### Breaking Changes
22
+
23
+ - Enable ERB expansion of the YAML source with a `.yam.erb` filename suffix.
24
+
25
+ ## [0.4.3] - 2020-08-25
26
+
27
+ #### New Features
28
+
29
+ - Support optional definitions
30
+
9
31
  ## [0.4.2] - 2020-08-22
10
32
 
33
+ #### Breaking Changes
34
+
11
35
  - Extended attributes use `_xa` suffix
12
36
 
13
37
  ## [0.4.1] - 2020-08-22
data/Gemfile CHANGED
@@ -2,6 +2,3 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in tdc.gemspec
4
4
  gemspec
5
-
6
- gem "rake", "~> 12.0"
7
- gem "rspec", "~> 3.0"
data/Rakefile CHANGED
@@ -1,8 +1,17 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
3
  require "rubocop/rake_task"
4
+ require "rubycritic/rake_task"
4
5
 
5
- RuboCop::RakeTask.new
6
6
  RSpec::Core::RakeTask.new(:spec)
7
+ RuboCop::RakeTask.new
8
+
9
+ RubyCritic::RakeTask.new do |task|
10
+ files = FileList["**/*.rb"]
11
+ files.exclude("**/*_spec.rb")
12
+ files.exclude("**/*_shared_example.rb")
13
+
14
+ task.paths = files
15
+ end
7
16
 
8
17
  task :default => [:rubocop, :spec]
data/lib/tdc.rb CHANGED
@@ -41,6 +41,14 @@ require "tdc/generators/definition_sourcable"
41
41
  require "tdc/generators/generator_base"
42
42
  require "tdc/generators/standard_generator"
43
43
 
44
+ # YAML Readers
45
+ require "tdc/yaml_readers"
46
+ require "tdc/yaml_readers/null_yaml_reader"
47
+ require "tdc/yaml_readers/yaml_reader_base"
48
+ require "tdc/yaml_readers/yaml_reader"
49
+ require "tdc/yaml_readers/yaml_reader_with_expansion"
50
+ require "tdc/yaml_readers/yaml_reader_factory"
51
+
44
52
  #
45
53
  # A framework for building a Test Data Catalog
46
54
  #
@@ -6,44 +6,13 @@ module Tdc
6
6
  EMPTY_DEFINITIONS = []
7
7
 
8
8
  def initialize(catalog_root_directory)
9
- super()
10
-
11
9
  @catalog_root_directory = catalog_root_directory
12
10
  end
13
11
 
14
12
  def read(*path_elements)
15
- data_definition_from(definitions_file(path_elements))
16
- end
17
-
18
- private
19
-
20
- def definitions_file(path_elements)
21
- fully_qualified_path_elements = [@catalog_root_directory].concat(path_elements.map(&:to_s))
22
-
23
- fully_qualified_path_elements.last.concat(".yml")
24
-
25
- File.join(*fully_qualified_path_elements)
26
- end
27
-
28
- def data_definition_from(definitions_file)
29
- if File.exist?(definitions_file)
30
- load_yaml(definitions_file) || EMPTY_DEFINITIONS
31
- else
32
- EMPTY_DEFINITIONS
33
- end
34
- end
35
-
36
- def load_yaml(definitions_file)
37
- YAML.load(expand_erb(definitions_file)) # rubocop:disable Security/YAMLLoad
38
- rescue => e
39
- raise Tdc::FatalError, <<~MSG
40
- Unable to load YAML from #{definitions_file}
41
- Cause: #{e.message}"
42
- MSG
43
- end
13
+ reader = Tdc::YamlReaders::YamlReaderFactory.new(@catalog_root_directory, path_elements).create
44
14
 
45
- def expand_erb(definitions_file)
46
- ERB.new(File.read(definitions_file)).result
15
+ reader.data_definitions
47
16
  end
48
17
  end
49
18
  end
@@ -8,8 +8,6 @@ module Tdc
8
8
  attr_reader :key, :source
9
9
 
10
10
  def initialize(key:, source:)
11
- super()
12
-
13
11
  @key = key
14
12
  @source = source
15
13
  end
@@ -26,15 +24,23 @@ module Tdc
26
24
  # Use the tag to source an object from the current catalog.
27
25
  sourced_object = catalog_entry.send(tag)
28
26
 
29
- unless sourced_object
30
- message = "Could not find a tag reference for '#{key}' in the catalog entries provided."
31
-
32
- raise Tdc::FatalError, message
33
- end
27
+ unresolvable_tag(tag, catalog_entry) unless sourced_object
34
28
 
35
29
  # Replace the tag value with the sourced object.
36
30
  instance_definition[key] = sourced_object
37
31
  end
32
+
33
+ private
34
+
35
+ def unresolvable_tag(tag, catalog_entry)
36
+ source_tags = catalog_entry.entries.sort.map { |entry| "'#{entry}'" }.to_sentence
37
+
38
+ raise Tdc::FatalError, <<~MESSAGE
39
+ Could not resolve key '#{key}' from source '#{source}'.
40
+
41
+ Attempted to resolve tag '#{tag}' from these tags: #{source_tags}
42
+ MESSAGE
43
+ end
38
44
  end
39
45
  end
40
46
  end
@@ -14,6 +14,10 @@ module Tdc
14
14
  @interpreters = []
15
15
  end
16
16
 
17
+ def clear
18
+ @interpreters = []
19
+ end
20
+
17
21
  def interpreters
18
22
  @interpreters.empty? ? [default_interpreter] : @interpreters
19
23
  end
@@ -23,6 +27,9 @@ module Tdc
23
27
  Cannot register an interpreter unless it inherits from Tdc::ExtendedAttributes::InterpreterBase
24
28
  MSG
25
29
 
30
+ # Avoid registering the same class of interpreter a second time.
31
+ return if @interpreters.map(&:class).include?(interpreter.class)
32
+
26
33
  @interpreters << interpreter
27
34
  end
28
35
 
@@ -1,7 +1,4 @@
1
1
  module Tdc
2
2
  class FatalError < RuntimeError
3
- def initialize(msg = nil)
4
- super
5
- end
6
3
  end
7
4
  end
@@ -13,6 +13,10 @@ module Tdc
13
13
  to_h.empty?
14
14
  end
15
15
 
16
+ def entries
17
+ to_h.keys
18
+ end
19
+
16
20
  def first
17
21
  to_h.first&.second
18
22
  end
@@ -3,7 +3,10 @@ module Tdc
3
3
  #
4
4
  # Creates ghost methods for use in generators.
5
5
  #
6
- # All ghost methods are named 'key'_definition where 'key' is a key into the instance_definition hash.
6
+ # All ghost methods are named 'key'_definition or 'key'_definition_optional where 'key' is
7
+ # a key into the instance_definition hash.
8
+ #
9
+ # Choose optional if the key may not be present in the instance_definition.
7
10
  #
8
11
  # Example:
9
12
  #
@@ -11,6 +14,7 @@ module Tdc
11
14
  # ghost methods could be used to refer to the value associated with those keys:
12
15
  #
13
16
  # line_definition
17
+ # line_definition_optional
14
18
  # replenishment_parameters_definition
15
19
  #
16
20
  module DefinitionSourcable
@@ -33,19 +37,25 @@ module Tdc
33
37
  private
34
38
 
35
39
  def method_missing(method, *args)
36
- key = transform_method_to_definition_source_key(method)
37
-
38
- definition_source&.key?(key) ? definition_source.fetch(key) : super
40
+ if ghost_definition?(method)
41
+ definition_source.fetch(method.to_s.gsub(/_definition$/, ""))
42
+ elsif ghost_optional_definition?(method)
43
+ definition_source[method.to_s.gsub(/_definition_optional$/, "")]
44
+ else
45
+ super
46
+ end
39
47
  end
40
48
 
41
- def respond_to_missing?(method, include_all = false) # rubocop:disable Style/OptionalBooleanParameter
42
- key = transform_method_to_definition_source_key(method)
49
+ def respond_to_missing?(method, include_all = false)
50
+ ghost_definition?(method) || ghost_optional_definition?(method) ? true : super
51
+ end
43
52
 
44
- definition_source&.key?(key) ? true : super
53
+ def ghost_definition?(method)
54
+ method.to_s.end_with?("_definition")
45
55
  end
46
56
 
47
- def transform_method_to_definition_source_key(method)
48
- method.to_s.gsub(/_definition$/, "")
57
+ def ghost_optional_definition?(method)
58
+ method.to_s.end_with?("_definition_optional")
49
59
  end
50
60
  end
51
61
  end
@@ -4,8 +4,6 @@ module Tdc
4
4
  #
5
5
  class InMemoryDataDefinition < Tdc::DataDefinition
6
6
  def initialize(path_elements_data = {})
7
- super()
8
-
9
7
  @store = path_elements_data
10
8
  end
11
9
 
@@ -1,3 +1,3 @@
1
1
  module Tdc
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.6"
3
3
  end
@@ -0,0 +1,7 @@
1
+ module Tdc
2
+ #
3
+ # Namespace to host YAML readers.
4
+ #
5
+ module YamlReaders
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Tdc
2
+ module YamlReaders
3
+ #
4
+ # When we can't find a YAML source.
5
+ #
6
+ class NullYamlReader
7
+ def data_definitions
8
+ []
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ module Tdc
2
+ module YamlReaders
3
+ #
4
+ # YAML source is a YAML file.
5
+ #
6
+ class YamlReader < Tdc::YamlReaders::YamlReaderBase
7
+ def file_extension
8
+ ".yml"
9
+ end
10
+
11
+ def source_string
12
+ File.read(definitions_file)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,52 @@
1
+ module Tdc
2
+ module YamlReaders
3
+ #
4
+ # YAML source.
5
+ #
6
+ class YamlReaderBase
7
+ def initialize(catalog_root_directory, path_elements)
8
+ @catalog_root_directory = catalog_root_directory
9
+ @path_elements = path_elements
10
+ end
11
+
12
+ def applies?
13
+ File.exist?(definitions_file)
14
+ end
15
+
16
+ def data_definitions
17
+ definitions_source
18
+ end
19
+
20
+ def definitions_source
21
+ source_string.empty? ? [] : YAML.load(source_string) # rubocop:disable Security/YAMLLoad
22
+ rescue => e
23
+ raise Tdc::FatalError, <<~MSG
24
+ Unable to load YAML from #{definitions_file}
25
+ Cause: #{e.message}"
26
+ MSG
27
+ end
28
+
29
+ concerning :HookMethods do
30
+ def file_extension
31
+ raise MissingOverrideError, "Implement the 'file_extension' method"
32
+ end
33
+
34
+ def source_string
35
+ raise MissingOverrideError, "Implement the 'source_string' method"
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def definitions_file
42
+ @_definitions_file ||= begin
43
+ fully_qualified_path_elements = [@catalog_root_directory].concat(@path_elements.map(&:to_s))
44
+
45
+ fully_qualified_path_elements.last.concat(file_extension)
46
+
47
+ File.join(*fully_qualified_path_elements)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,38 @@
1
+ module Tdc
2
+ module YamlReaders
3
+ #
4
+ # Knows how to create the appropriate YAML reader.
5
+ #
6
+ class YamlReaderFactory
7
+ def initialize(catalog_root_directory, path_elements)
8
+ @catalog_root_directory = catalog_root_directory
9
+ @path_elements = path_elements
10
+ end
11
+
12
+ def create
13
+ if yaml_reader_with_expansion.applies?
14
+ yaml_reader_with_expansion
15
+ elsif yaml_reader.applies?
16
+ yaml_reader
17
+ else
18
+ null_reader
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def yaml_reader_with_expansion
25
+ @_yaml_reader_with_expansion ||=
26
+ Tdc::YamlReaders::YamlReaderWithExpansion.new(@catalog_root_directory, @path_elements)
27
+ end
28
+
29
+ def null_reader
30
+ @_null_reader ||= Tdc::YamlReaders::NullYamlReader.new
31
+ end
32
+
33
+ def yaml_reader
34
+ @_yaml_reader ||= Tdc::YamlReaders::YamlReader.new(@catalog_root_directory, @path_elements)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ module Tdc
2
+ module YamlReaders
3
+ #
4
+ # YAML source is a YAML file that undergoes ERB expansion.
5
+ #
6
+ class YamlReaderWithExpansion < Tdc::YamlReaders::YamlReaderBase
7
+ def file_extension
8
+ ".yml.erb"
9
+ end
10
+
11
+ def source_string
12
+ ERB.new(File.read(definitions_file)).result
13
+ end
14
+ end
15
+ end
16
+ end
@@ -33,6 +33,8 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency "rake", ">= 12.1", "< 13.1"
34
34
  spec.add_development_dependency "rspec", ">= 3.9", "< 4.0"
35
35
  spec.add_development_dependency "rubocop", "~> 0.89"
36
+ spec.add_development_dependency "rubocop-performance", "~> 1.8"
36
37
  spec.add_development_dependency "rubocop-rspec", "~> 1.42"
38
+ spec.add_development_dependency "rubycritic", "~> 4.5"
37
39
  spec.add_development_dependency "simplecov", "~> 0.17"
38
40
  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.4.2
4
+ version: 0.4.6
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-08-22 00:00:00.000000000 Z
11
+ date: 2020-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -78,6 +78,20 @@ dependencies:
78
78
  - - "~>"
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0.89'
81
+ - !ruby/object:Gem::Dependency
82
+ name: rubocop-performance
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '1.8'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '1.8'
81
95
  - !ruby/object:Gem::Dependency
82
96
  name: rubocop-rspec
83
97
  requirement: !ruby/object:Gem::Requirement
@@ -92,6 +106,20 @@ dependencies:
92
106
  - - "~>"
93
107
  - !ruby/object:Gem::Version
94
108
  version: '1.42'
109
+ - !ruby/object:Gem::Dependency
110
+ name: rubycritic
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '4.5'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '4.5'
95
123
  - !ruby/object:Gem::Dependency
96
124
  name: simplecov
97
125
  requirement: !ruby/object:Gem::Requirement
@@ -147,6 +175,12 @@ files:
147
175
  - lib/tdc/missing_override_error.rb
148
176
  - lib/tdc/version.rb
149
177
  - lib/tdc/with_indifferent_access_decorator.rb
178
+ - lib/tdc/yaml_readers.rb
179
+ - lib/tdc/yaml_readers/null_yaml_reader.rb
180
+ - lib/tdc/yaml_readers/yaml_reader.rb
181
+ - lib/tdc/yaml_readers/yaml_reader_base.rb
182
+ - lib/tdc/yaml_readers/yaml_reader_factory.rb
183
+ - lib/tdc/yaml_readers/yaml_reader_with_expansion.rb
150
184
  - tdc.gemspec
151
185
  homepage: https://github.com/nulogy/tdc
152
186
  licenses: