trinkets 0.3.1 → 0.4.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/CHANGELOG.md +3 -0
- data/doc/class/init.md +31 -0
- data/lib/explicit/trinkets/extend/class/init.rb +74 -57
- data/lib/trinkets/version.rb +1 -1
- metadata +1 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b95bff0eaa948f0edc0375709fd3ec786ad10e970f5b5abcd501247dceb1e74
|
4
|
+
data.tar.gz: 3d4d1bce01e034167209cad41d9bf4ad356d79ddf100cfc1968d16b9686a06f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b3a7cc743fae16ee12cfab9d9efc4236b31d69d8a570fe1bbf009cc3558be08d3cef3a38aa110403fb40dea019a3236adbf4a00c983c5f1f4e148a909bfb884
|
7
|
+
data.tar.gz: e94881a3dc54ca93be7ea759b0b6aff8607b9d91d7d1247d3ec2f59d265ecb2ea4c7f014754ca9a4a351ee6994eabb2fcae0e93fe0d14d27a46b01985370c3f6
|
data/CHANGELOG.md
CHANGED
data/doc/class/init.md
CHANGED
@@ -9,6 +9,10 @@ To use it, define a class and call `::init` like you would call `::attr` methods
|
|
9
9
|
* can be `:accessor`, `:reader`, `:writer` or `:none`
|
10
10
|
* defaults to `:accessor`
|
11
11
|
* `kw` : if arguments are to be set as keyword arguments
|
12
|
+
* when `false`, it's a mandatory positional argument
|
13
|
+
* when `true`, it becomes a mandatory keyword argument, like `(a:)`
|
14
|
+
* when it's a hash, like `{ default: <VALUE> }`, it's an optional keyword argument
|
15
|
+
* an empty hash `{}` is equivalent to `{ default: nil }`
|
12
16
|
* defaults to `false`
|
13
17
|
|
14
18
|
The same options can be used per individual argument.
|
@@ -147,6 +151,33 @@ test.a = 5
|
|
147
151
|
# => raises NoMethodError
|
148
152
|
```
|
149
153
|
|
154
|
+
## Default values for keyword arguments
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
class TestDefaultKw
|
158
|
+
init [:a, kw: true],
|
159
|
+
:b,
|
160
|
+
kw: {default: 3}
|
161
|
+
end
|
162
|
+
|
163
|
+
# would be the same as
|
164
|
+
class TestDefaultKw
|
165
|
+
attr_accessor :a, :b
|
166
|
+
def initialize(a: , b: 3)
|
167
|
+
@a = a
|
168
|
+
@b = b
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
test = TestDefaultKw.new(a: 2)
|
173
|
+
|
174
|
+
test.a
|
175
|
+
# 2
|
176
|
+
|
177
|
+
test.b
|
178
|
+
# 3
|
179
|
+
```
|
180
|
+
|
150
181
|
## Mixed together
|
151
182
|
```ruby
|
152
183
|
class TestMixed
|
@@ -6,13 +6,9 @@ module Trinkets
|
|
6
6
|
ATTR = %i[accessor reader writer none].freeze
|
7
7
|
|
8
8
|
def init(*attrs, attr: ATTR.first, kw: false)
|
9
|
-
|
10
|
-
raise ArgumentError, '`attr` must be one of :accessor (default), :reader, :writer or :none' unless ATTR.include?(attr)
|
11
|
-
|
12
|
-
default_attr_options = { attr: attr, kw: kw }
|
13
|
-
|
14
|
-
attrs = ::Trinkets::Class.send(:sanitize_attrs, attrs, default_attr_options)
|
9
|
+
attrs = Init.send(:sanitize_attrs, attrs, attr: attr, kw: kw)
|
15
10
|
|
11
|
+
# @type [Hash[Symbol, Method]]
|
16
12
|
attr_methods = (ATTR - [:none])
|
17
13
|
.each_with_object({}) do |name, h|
|
18
14
|
h[name] = method("attr_#{name}")
|
@@ -21,77 +17,98 @@ module Trinkets
|
|
21
17
|
# even though options like `kw` aren't used, they serve here to validate the `attrs` options
|
22
18
|
attr_init = ->(name, attr: ATTR.first, kw: false) do
|
23
19
|
unless ATTR.include?(attr)
|
24
|
-
raise ArgumentError, "attr `#{name}
|
20
|
+
raise ArgumentError, "wrong `attr` type for `#{name.inspect}` (given #{attr.inspect}, expected :accessor (default), :reader, :writer or :none)"
|
25
21
|
end
|
26
22
|
attr_methods[attr].call(name) unless attr == :none
|
27
23
|
end
|
28
24
|
|
29
25
|
attrs.each { |name, opts| attr_init.call(name, **opts) }
|
30
26
|
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
27
|
+
# hash with 3 keys: {
|
28
|
+
# FalseClass => [] # positional args
|
29
|
+
# TrueClass => [] # mandatory kw args
|
30
|
+
# Hash => [] # optional kw args with default value
|
31
|
+
# }
|
32
|
+
grouped_params = attrs
|
33
|
+
.map { |name, opts| [name, opts[:kw] || false] }
|
34
|
+
.group_by { _1.last.class }
|
35
|
+
|
36
|
+
pos_params = [*grouped_params[FalseClass]].map(&:first)
|
37
|
+
kw_params = [*grouped_params[TrueClass]].map(&:first)
|
38
|
+
opt_kw_params = [*grouped_params[Hash]].to_h
|
39
|
+
.transform_values! { _1[:default] }
|
40
|
+
|
41
|
+
init_method = Init.send(:define_initialize, pos_params, kw_params, opt_kw_params)
|
38
42
|
define_method :initialize, init_method
|
39
43
|
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class << self
|
43
|
-
private def sanitize_attrs(attrs, default_attr_options)
|
44
|
-
# Normalize attrs into an array: [[:name, **options], ...]
|
45
|
-
# @type [Array[Array[Symbol, Hash]]]
|
46
|
-
attrs = attrs.map do |a|
|
47
|
-
name, opts = [*a]
|
48
|
-
name = name.to_s.sub(/^@/, '').to_sym
|
49
|
-
opts = default_attr_options.merge(opts || {})
|
50
|
-
[name, opts]
|
51
|
-
end
|
52
|
-
|
53
|
-
repeated_attrs = attrs.map(&:first)
|
54
|
-
.tally
|
55
|
-
.select { |_, count| count > 1 }
|
56
|
-
.keys
|
57
|
-
|
58
|
-
raise ArgumentError, "duplicated argument names: #{repeated_attrs.join(', ')}" if repeated_attrs.any?
|
59
44
|
|
60
|
-
|
61
|
-
|
45
|
+
class << self
|
46
|
+
private def sanitize_attrs(attrs, **default_options)
|
62
47
|
|
63
|
-
|
64
|
-
# @param [Hash[Symbol Boolean]] kw_attrs
|
65
|
-
private def define_initialize(attrs, kw_attrs)
|
66
|
-
->(*values, **kw_values) do
|
48
|
+
raise ArgumentError, 'At least 1 attribute is required.' if attrs.empty?
|
67
49
|
|
68
|
-
unless
|
69
|
-
|
50
|
+
unless ::Trinkets::Class::Init::ATTR.include?(default_options[:attr])
|
51
|
+
attr = default_options[:attr].inspect
|
52
|
+
raise ArgumentError, "wrong `attr` type (given #{attr}, expected :accessor (default), :reader, :writer or :none)"
|
70
53
|
end
|
71
54
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
55
|
+
# Normalize attrs into an array: [[:name, **options], ...]
|
56
|
+
# @type [Array[Array[Symbol, Hash]]]
|
57
|
+
attrs = attrs.map do |a|
|
58
|
+
name, opts = [*a]
|
59
|
+
name = name.to_s.sub(/^@/, '').to_sym
|
60
|
+
opts = default_options.merge(opts || {})
|
61
|
+
[name, opts]
|
76
62
|
end
|
77
63
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
64
|
+
repeated_attrs = attrs.map(&:first)
|
65
|
+
.tally
|
66
|
+
.select { |_, count| count > 1 }
|
67
|
+
.keys
|
83
68
|
|
84
|
-
|
85
|
-
instance_variable_set "@#{name}", value
|
86
|
-
end
|
69
|
+
raise ArgumentError, "duplicated argument names: #{repeated_attrs.join(', ')}" if repeated_attrs.any?
|
87
70
|
|
88
|
-
|
89
|
-
|
90
|
-
|
71
|
+
attrs.to_h
|
72
|
+
end
|
73
|
+
|
74
|
+
# @param [Array[Symbol]] pos_params
|
75
|
+
# @param [Array[Symbol]] kw_params
|
76
|
+
# @param [Hash[Symbol, Object]] opt_kw_params
|
77
|
+
private def define_initialize(pos_params, kw_params, opt_kw_params)
|
78
|
+
->(*values, **kw_values) do
|
79
|
+
|
80
|
+
unless pos_params.size == values.size
|
81
|
+
raise ArgumentError, "wrong number of arguments (given #{values.size}, expected #{pos_params.size})"
|
82
|
+
end
|
83
|
+
|
84
|
+
missing_keys = kw_params - kw_values.keys
|
85
|
+
unless missing_keys.empty?
|
86
|
+
missing_keys = missing_keys.map(&:inspect).join(', ')
|
87
|
+
raise ArgumentError, "missing keywords: #{missing_keys}"
|
88
|
+
end
|
89
|
+
|
90
|
+
unknown_keywords = kw_values.except(*kw_params, *opt_kw_params.keys)
|
91
|
+
unless unknown_keywords.empty?
|
92
|
+
unknown_keywords = unknown_keywords.keys.map(&:to_sym).map(&:inspect).join(', ')
|
93
|
+
raise ArgumentError, "unknown keywords: #{unknown_keywords}"
|
94
|
+
end
|
95
|
+
|
96
|
+
pos_params.zip(values).each do |name, value|
|
97
|
+
instance_variable_set "@#{name}", value
|
98
|
+
end
|
99
|
+
|
100
|
+
kw_params.each do |name|
|
101
|
+
instance_variable_set "@#{name}", kw_values[name]
|
102
|
+
end
|
103
|
+
|
104
|
+
opt_kw_params.each do |name, default_value|
|
105
|
+
value = kw_values.include?(name) ? kw_values[name] : default_value
|
106
|
+
instance_variable_set "@#{name}", value
|
107
|
+
end
|
91
108
|
|
109
|
+
end
|
92
110
|
end
|
93
111
|
end
|
94
112
|
end
|
95
|
-
|
96
113
|
end
|
97
114
|
end
|
data/lib/trinkets/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trinkets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SilverPhoenix99
|
@@ -65,7 +65,6 @@ homepage: https://github.com/SilverPhoenix99/trinkets
|
|
65
65
|
licenses:
|
66
66
|
- MIT
|
67
67
|
metadata:
|
68
|
-
homepage_uri: https://github.com/SilverPhoenix99/trinkets
|
69
68
|
source_code_uri: https://github.com/SilverPhoenix99/trinkets
|
70
69
|
changelog_uri: https://github.com/SilverPhoenix99/trinkets/blob/master/CHANGELOG.md
|
71
70
|
bug_tracker_uri: https://github.com/SilverPhoenix99/trinkets/issues
|