class_composer 1.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|