otoroshi 0.0.1
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 +7 -0
- data/lib/otoroshi/sanctuary.rb +165 -0
- metadata +43 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2993a278f341533c1590cd6bdea9291033167104f94018808577f67cbcd2f0ae
|
4
|
+
data.tar.gz: 725a187567625f428485a80edd5025b0ae7e3a859bebd4d73ea14557353a89ad
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c14d31b349b599ff5ef0db40dbaed8723b47bd53de648589ace6ac8ccfeba85b926d263070fe7d13a0746168399508127cd4e3a33df032ff8cfef5d5a9d5380c
|
7
|
+
data.tar.gz: 19311d09a63ee50e89bd3b3c7dead8faeaba0bd1a4803dfba363c422b0c13704fbeb3bb60799cfac9d681736e209d1587b44be76840bc5736aff4822c6cf9c24
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Otoroshi
|
4
|
+
# help setting and validating instance arguments
|
5
|
+
class Sanctuary
|
6
|
+
class << self
|
7
|
+
# Add a new property to the class (called by inherited class)
|
8
|
+
# Example: property name, type: String, validate: ->(v) { v.length > 3 }, optional: true
|
9
|
+
def property(name, type = Object, validate: ->(_) { true }, optional: false, default: nil)
|
10
|
+
define_default(name, default)
|
11
|
+
define_validate_type!(name, type, optional)
|
12
|
+
define_validate!(name, validate, optional)
|
13
|
+
define_getter(name)
|
14
|
+
define_setter(name)
|
15
|
+
add_to_properties(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Return the (inherited) class properties
|
19
|
+
# (this method will be updated by ::add_to_properties(name))
|
20
|
+
def properties
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Update the ::properties method to add new property to the current list
|
27
|
+
def add_to_properties(name)
|
28
|
+
current = properties
|
29
|
+
define_singleton_method :properties do
|
30
|
+
current << name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Define a private method that returns the default value
|
35
|
+
#
|
36
|
+
# ::define_default("score", 0)
|
37
|
+
# --------------------------
|
38
|
+
# def default_score
|
39
|
+
# 0
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
def define_default(name, default)
|
43
|
+
define_method(:"default_#{name}") { default }
|
44
|
+
private :"default_#{name}"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Define a private method that raises an error if type is not respected
|
48
|
+
#
|
49
|
+
# ::define_validate_type!("score", Integer, false)
|
50
|
+
# ----------------------------------------------
|
51
|
+
# def validate_score_type!(value)
|
52
|
+
# return if optional && value.nil?
|
53
|
+
# return if value.is_a?(Integer)
|
54
|
+
#
|
55
|
+
# raise ArgumentError, ":score does not match type validation"
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
def define_validate_type!(name, type, optional)
|
59
|
+
lambda = type_validation(type)
|
60
|
+
define_method :"validate_#{name}_type!" do |value|
|
61
|
+
return if type.nil? || optional && value.nil?
|
62
|
+
return if lambda.call(value)
|
63
|
+
|
64
|
+
raise ArgumentError, ":#{name} does not match type validation"
|
65
|
+
end
|
66
|
+
private :"validate_#{name}_type!"
|
67
|
+
end
|
68
|
+
|
69
|
+
# Define a lambda to be call to validate that value match the type
|
70
|
+
#
|
71
|
+
# ::type_validation(Integer)
|
72
|
+
# ----------------------------------------------
|
73
|
+
# ->(v) { v.is_a? Integer }
|
74
|
+
#
|
75
|
+
def type_validation(type)
|
76
|
+
if type.is_a? Array
|
77
|
+
->(v) { type.any? { |t| v.is_a? t } }
|
78
|
+
else
|
79
|
+
->(v) { v.is_a? type }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Define a private method that raises an error if validate block returns false
|
84
|
+
#
|
85
|
+
# ::define_validate!("score", ->(v) { v >= 0 }, false)
|
86
|
+
# --------------------------------------------------
|
87
|
+
# def validate_score!(value)
|
88
|
+
# return if false && value.nil?
|
89
|
+
# return if value >= 0
|
90
|
+
#
|
91
|
+
# raise ArgumentError, ":score does not match validation"
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
def define_validate!(name, validate, optional)
|
95
|
+
define_method :"validate_#{name}!" do |value|
|
96
|
+
return if optional && value.nil?
|
97
|
+
return if instance_exec(value, &validate)
|
98
|
+
|
99
|
+
raise ArgumentError, ":#{name} does not match validation"
|
100
|
+
end
|
101
|
+
private :"validate_#{name}!"
|
102
|
+
end
|
103
|
+
|
104
|
+
# Define a getter method for the property
|
105
|
+
#
|
106
|
+
# ::define_getter("score")
|
107
|
+
# ----------------------
|
108
|
+
# def score
|
109
|
+
# @score
|
110
|
+
# end
|
111
|
+
#
|
112
|
+
def define_getter(name)
|
113
|
+
define_method(name) { instance_variable_get("@#{name}") }
|
114
|
+
end
|
115
|
+
|
116
|
+
# Define a setter method for the property
|
117
|
+
#
|
118
|
+
# ::define_setter("score")
|
119
|
+
# ----------------------
|
120
|
+
# def score=(value)
|
121
|
+
# validate_score_type!(value)
|
122
|
+
# validate_score!(value)
|
123
|
+
# @score = value
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
def define_setter(name)
|
127
|
+
define_method :"#{name}=" do |value|
|
128
|
+
__send__(:"validate_#{name}_type!", value)
|
129
|
+
__send__(:"validate_#{name}!", value)
|
130
|
+
instance_variable_set("@#{name}", value)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Initialize an instance and validate provided args
|
136
|
+
def initialize(args = {}) # rubocop:disable Style/OptionHash
|
137
|
+
validate_keys!(args.keys)
|
138
|
+
assign_values(args)
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
# validate that provided keys match class properties
|
144
|
+
def validate_keys!(keys)
|
145
|
+
errors = keys.reject { |key| self.class.properties.include? key }
|
146
|
+
return if errors.empty?
|
147
|
+
|
148
|
+
message =
|
149
|
+
if errors.one?
|
150
|
+
":#{errors[0]} is not a valid property"
|
151
|
+
else
|
152
|
+
":#{errors.join(', :')} are not valid properties"
|
153
|
+
end
|
154
|
+
raise ArgumentError, message
|
155
|
+
end
|
156
|
+
|
157
|
+
# assign value to each property
|
158
|
+
def assign_values(args)
|
159
|
+
self.class.properties.each do |property|
|
160
|
+
value = args.key?(property) ? args[property] : __send__(:"default_#{property}")
|
161
|
+
public_send(:"#{property}=", value)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
metadata
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: otoroshi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Edouard Piron
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-10-10 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Help setting and validating instance arguments
|
14
|
+
email: ed.piron@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/otoroshi/sanctuary.rb
|
20
|
+
homepage: https://rubygems.org/gems/otoroshi
|
21
|
+
licenses:
|
22
|
+
- MIT
|
23
|
+
metadata: {}
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.6'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirements: []
|
39
|
+
rubygems_version: 3.1.4
|
40
|
+
signing_key:
|
41
|
+
specification_version: 4
|
42
|
+
summary: Otoroshi
|
43
|
+
test_files: []
|