class_composer 1.0.2 → 2.1.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 +4 -4
- data/.circleci/config.yml +2 -2
- data/.gitignore +1 -0
- data/CHANGELOG.md +23 -4
- data/Dockerfile +1 -1
- data/Gemfile +5 -5
- data/Gemfile.lock +24 -30
- data/README.md +14 -126
- data/bin/setup +0 -2
- data/class_composer.gemspec +1 -8
- data/docker-compose.yml +0 -2
- data/docs/array_usage.md +25 -0
- data/docs/basic_composer.md +133 -0
- data/docs/basic_composer_example.md +35 -0
- data/docs/composer_blocking.md +84 -0
- data/docs/freezing.md +58 -0
- data/docs/generating_initializer.md +74 -0
- data/lib/class_composer/generate_config.rb +143 -0
- data/lib/class_composer/generator/class_methods.rb +233 -0
- data/lib/class_composer/generator/instance_methods.rb +73 -0
- data/lib/class_composer/generator.rb +9 -118
- data/lib/class_composer/version.rb +1 -1
- data/lib/class_composer.rb +0 -1
- metadata +15 -62
@@ -1,129 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "class_composer/default_object"
|
4
|
+
require "class_composer/generate_config"
|
5
|
+
require "class_composer/generator/instance_methods"
|
6
|
+
require "class_composer/generator/class_methods"
|
4
7
|
|
5
8
|
module ClassComposer
|
9
|
+
FROZEN_TYPES = [
|
10
|
+
DEFAULT_FROZEN_TYPE = FROZEN_RAISE = :raise,
|
11
|
+
FROZEN_LOG_AND_ALLOW = :log_and_allow,
|
12
|
+
FROZEN_LOG_AND_SKIP = :log_and_skip,
|
13
|
+
]
|
6
14
|
module Generator
|
7
15
|
def self.included(base)
|
8
16
|
base.extend(ClassMethods)
|
9
|
-
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
COMPOSER_VALIDATE_METHOD_NAME = ->(name) { :"__composer_#{name}_is_valid__?" }
|
13
|
-
COMPOSER_ASSIGNED_ATTR_NAME = ->(name) { :"@__composer_#{name}_value_assigned__" }
|
14
|
-
COMPOSER_ASSIGNED_ARRAY_METHODS = ->(name) { :"@__composer_#{name}_array_methods_set__" }
|
15
|
-
|
16
|
-
def add_composer(name, allowed:, accessor: true, validator: ->(_) { true }, validation_error_klass: ::ClassComposer::ValidatorError, error_klass: ::ClassComposer::Error, **params)
|
17
|
-
default =
|
18
|
-
if params.has_key?(:default)
|
19
|
-
params[:default]
|
20
|
-
else
|
21
|
-
if allowed.is_a?(Array)
|
22
|
-
allowed << ClassComposer::DefaultObject
|
23
|
-
else
|
24
|
-
allowed = [allowed, ClassComposer::DefaultObject]
|
25
|
-
end
|
26
|
-
ClassComposer::DefaultObject
|
27
|
-
end
|
28
|
-
|
29
|
-
allowed.include?(ClassComposer::DefaultObject)
|
30
|
-
validate_proc = __composer_validator_proc__(validator: validator, allowed: allowed, name: name, error_klass: error_klass)
|
31
|
-
__composer_validate_options__!(name: name, validate_proc: validate_proc, default: default, validation_error_klass: validation_error_klass, error_klass: error_klass)
|
32
|
-
|
33
|
-
array_proc = __composer_array_proc__(name: name, validator: validator, allowed: allowed, params: params)
|
34
|
-
__composer_assignment__(name: name, allowed: allowed, params: params, validator: validate_proc, array_proc: array_proc, validation_error_klass: validation_error_klass, error_klass: error_klass)
|
35
|
-
__composer_retrieval__(name: name, default: default, array_proc: array_proc)
|
36
|
-
end
|
37
|
-
|
38
|
-
def __composer_validate_options__!(name:, validate_proc:, default:, params: {}, validation_error_klass:, error_klass:)
|
39
|
-
unless validate_proc.(default)
|
40
|
-
raise validation_error_klass, "Default value [#{default}] for #{self.class}.#{name} is not valid"
|
41
|
-
end
|
42
|
-
|
43
|
-
if instance_methods.include?(name.to_sym)
|
44
|
-
raise error_klass, "[#{name}] is already defined. Ensure composer names are all uniq and do not class with class instance methods"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def __composer_array_proc__(name:, validator:, allowed:, params:)
|
49
|
-
Proc.new do |value, _itself|
|
50
|
-
_itself.send(:"#{name}=", value)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# create assignment method for the incoming name
|
55
|
-
def __composer_assignment__(name:, params:, allowed:, validator:, array_proc:, validation_error_klass:, error_klass:)
|
56
|
-
define_method(:"#{name}=") do |value|
|
57
|
-
is_valid = validator.(value)
|
58
|
-
|
59
|
-
if is_valid
|
60
|
-
instance_variable_set(COMPOSER_ASSIGNED_ATTR_NAME.(name), true)
|
61
|
-
instance_variable_set(:"@#{name}", value)
|
62
|
-
else
|
63
|
-
message = ["#{self.class}.#{name} failed validation. #{name} is expected to be #{allowed}."]
|
64
|
-
|
65
|
-
message << (params[:invalid_message].is_a?(Proc) ? params[:invalid_message].(value) : params[:invalid_message].to_s)
|
66
|
-
if value.is_a?(Array)
|
67
|
-
# we assigned the array value...pop it from the array
|
68
|
-
# must be done after the message is created so that failing value can get passed appropriately
|
69
|
-
value.pop
|
70
|
-
end
|
71
|
-
raise validation_error_klass, message.compact.join(" ")
|
72
|
-
end
|
73
|
-
|
74
|
-
if value.is_a?(Array) && !value.instance_variable_get(COMPOSER_ASSIGNED_ARRAY_METHODS.(name))
|
75
|
-
_itself = itself
|
76
|
-
value.define_singleton_method(:<<) do |val|
|
77
|
-
array_proc.(super(val), _itself)
|
78
|
-
end
|
79
|
-
value.instance_variable_set(COMPOSER_ASSIGNED_ARRAY_METHODS.(name), true)
|
80
|
-
end
|
81
|
-
|
82
|
-
value
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
# retrieve the value for the name -- Or return the default value
|
87
|
-
def __composer_retrieval__(name:, default:, array_proc:)
|
88
|
-
define_method(:"#{name}") do
|
89
|
-
value = instance_variable_get(:"@#{name}")
|
90
|
-
return value if instance_variable_get(COMPOSER_ASSIGNED_ATTR_NAME.(name))
|
91
|
-
|
92
|
-
if default.is_a?(Array) && !default.instance_variable_get(COMPOSER_ASSIGNED_ARRAY_METHODS.(name))
|
93
|
-
_itself = itself
|
94
|
-
default.define_singleton_method(:<<) do |value|
|
95
|
-
array_proc.(super(value), _itself)
|
96
|
-
end
|
97
|
-
default.instance_variable_set(COMPOSER_ASSIGNED_ARRAY_METHODS.(name), true)
|
98
|
-
end
|
99
|
-
|
100
|
-
default == ClassComposer::DefaultObject ? ClassComposer::DefaultObject.value : default
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# create validator method for incoming name
|
105
|
-
def __composer_validator_proc__(validator:, allowed:, name:, error_klass:)
|
106
|
-
if validator && !validator.is_a?(Proc)
|
107
|
-
raise error_klass, "Expected validator to be a Proc. Received [#{validator.class}]"
|
108
|
-
end
|
109
|
-
|
110
|
-
# Proc will validate the entire attribute -- Full assignment must occur before validate is called
|
111
|
-
Proc.new do |value|
|
112
|
-
begin
|
113
|
-
allow =
|
114
|
-
if allowed.is_a?(Array)
|
115
|
-
allowed.include?(value.class)
|
116
|
-
else
|
117
|
-
allowed == value.class
|
118
|
-
end
|
119
|
-
# order is important -- Do not run validator if it is the default object
|
120
|
-
# Default object will likely raise an error if there is a custom validator
|
121
|
-
(allowed.include?(ClassComposer::DefaultObject) && value == ClassComposer::DefaultObject) || (allow && validator.(value))
|
122
|
-
rescue StandardError => e
|
123
|
-
raise error_klass, "#{e} occured during validation for value [#{value}]. Check custom validator for #{name}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
17
|
+
base.include(InstanceMethods)
|
127
18
|
end
|
128
19
|
end
|
129
20
|
end
|
data/lib/class_composer.rb
CHANGED
metadata
CHANGED
@@ -1,71 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: class_composer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Taylor
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: pry-byebug
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '12.0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '12.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rspec
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '3.0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '3.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: simplecov
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 0.17.0
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 0.17.0
|
11
|
+
date: 2024-12-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
69
13
|
description: Compose configurations for any class.
|
70
14
|
email:
|
71
15
|
- mattius.taylor@gmail.com
|
@@ -89,9 +33,18 @@ files:
|
|
89
33
|
- bin/setup
|
90
34
|
- class_composer.gemspec
|
91
35
|
- docker-compose.yml
|
36
|
+
- docs/array_usage.md
|
37
|
+
- docs/basic_composer.md
|
38
|
+
- docs/basic_composer_example.md
|
39
|
+
- docs/composer_blocking.md
|
40
|
+
- docs/freezing.md
|
41
|
+
- docs/generating_initializer.md
|
92
42
|
- lib/class_composer.rb
|
93
43
|
- lib/class_composer/default_object.rb
|
44
|
+
- lib/class_composer/generate_config.rb
|
94
45
|
- lib/class_composer/generator.rb
|
46
|
+
- lib/class_composer/generator/class_methods.rb
|
47
|
+
- lib/class_composer/generator/instance_methods.rb
|
95
48
|
- lib/class_composer/version.rb
|
96
49
|
homepage: https://github.com/matt-taylor/class_composer
|
97
50
|
licenses:
|
@@ -107,14 +60,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
60
|
requirements:
|
108
61
|
- - ">="
|
109
62
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
63
|
+
version: '3.1'
|
111
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
65
|
requirements:
|
113
66
|
- - ">="
|
114
67
|
- !ruby/object:Gem::Version
|
115
68
|
version: '0'
|
116
69
|
requirements: []
|
117
|
-
rubygems_version: 3.
|
70
|
+
rubygems_version: 3.5.9
|
118
71
|
signing_key:
|
119
72
|
specification_version: 4
|
120
73
|
summary: Easily compose a class via inline code or passed in YAML config. Add instance
|