magic-decorator 0.1.0 → 0.2.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 +25 -4
- data/README.md +69 -7
- data/lib/enumerable_decorator.rb +9 -0
- data/lib/magic/decorator/base.rb +42 -0
- data/lib/magic/decorator/version.rb +1 -1
- data/lib/magic/decorator.rb +2 -0
- data/sig/enumerable_decorator.rbs +9 -0
- data/sig/magic/decorator/base.rbs +6 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 910cb75b4dedfce18a494e39779b65821642feb96a24f3cda7228deea96ccd04
|
4
|
+
data.tar.gz: 98603bb63196fa955b4aec3172ff6326f5be10371b0fffb96404a9f5cd84a86b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b4bfb9bbb3838ac81dc35527caddd9d42d86887e1019ad75c7aad5f21af03607a1540523555aa0669baef7705a989af99487d3fa0a925fe8fedca96749070e3
|
7
|
+
data.tar.gz: 9f1cc4b1b608fd9b795b2a296c7919e513ed0a9ea7a9c0d1957fe23e5f5b537edc7ea30985ccc02ce72ca5fac1c7707d8b44769502a4f702e426dd26c2ce1260
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,31 @@
|
|
1
|
+
## [0.2.0] — 2024-10-17
|
2
|
+
|
3
|
+
### Changed
|
4
|
+
|
5
|
+
- For almost any method called on a decorated object, both its result and `yield`ed arguments get decorated.
|
6
|
+
Some methods aren’t meant to be decorated though:
|
7
|
+
- `deconstruct` & `deconstruct_keys` for _pattern matching_,
|
8
|
+
- _converting_ methods: those starting with `to_`,
|
9
|
+
- _system_ methods: those starting with `_`.
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- `Magic::Decorator::Base.undecorated` to exclude methods from being decorated automagically.
|
14
|
+
|
15
|
+
#### Default decorators
|
16
|
+
|
17
|
+
- `EnumerableDecorator` to decorate `Enumerable`s.
|
18
|
+
- enables _splat_ operator: `*decorated` ,
|
19
|
+
- enables _double-splat_ operator: `**decorated`,
|
20
|
+
- enumerating methods yield decorated items.
|
21
|
+
|
1
22
|
## [0.1.0] — 2024-10-13
|
2
23
|
|
3
24
|
### Added
|
4
25
|
|
5
26
|
- `Magic::Decorator::Base` — a basic decorator class.
|
6
27
|
- `Magic::Decoratable` to be included in decoratable classes.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
28
|
+
- `#decorate`,
|
29
|
+
- `#decorate!`,
|
30
|
+
- `#decorated`,
|
31
|
+
- `#decorated?`.
|
data/README.md
CHANGED
@@ -47,20 +47,55 @@ person.name # => "John Smith"
|
|
47
47
|
This module adds three methods to decorate an object.
|
48
48
|
Decorator class is being inferred automatically.
|
49
49
|
When no decorator is found,
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
- `#decorate` returns `nil`,
|
51
|
+
- `#decorate!` raises `Magic::Lookup::Error`,
|
52
|
+
- `#decorated` returns the original object.
|
53
53
|
|
54
54
|
One can test for the object is actually decorated with `#decorated?`.
|
55
55
|
|
56
56
|
```ruby
|
57
|
-
'with no decorator for String'.decorated
|
58
|
-
|
57
|
+
'with no decorator for String'.decorated
|
58
|
+
.decorated? # => false
|
59
|
+
['with a decorator for Array'].decorated
|
60
|
+
.decorated? # => true
|
59
61
|
```
|
60
62
|
|
61
|
-
|
63
|
+
## Magic
|
62
64
|
|
63
|
-
|
65
|
+
### Decoratable scope
|
66
|
+
|
67
|
+
`Magic::Decoratable` is mixed into `Object` by default. It means that effectively any object is _magically decoratable_.
|
68
|
+
|
69
|
+
### Decoration expansion
|
70
|
+
|
71
|
+
For almost any method called on a decorated object, both its result and `yield`ed arguments get decorated.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
'with no decorator for String'.decorated.chars
|
75
|
+
.decorated? # => false
|
76
|
+
['with a decorator for Array'].decorated.map(&:chars).first.grep(/\S/).group_by(&:upcase).transform_values(&:size).sort_by(&:last).reverse.first(5).map(&:first)
|
77
|
+
.decorated? # => true
|
78
|
+
```
|
79
|
+
|
80
|
+
#### Undecorated methods
|
81
|
+
|
82
|
+
Some methods aren’t meant to be decorated though:
|
83
|
+
|
84
|
+
- `deconstruct` & `deconstruct_keys` for _pattern matching_,
|
85
|
+
- _converting_ methods: those starting with `to_`,
|
86
|
+
- _system_ methods: those starting with `_`.
|
87
|
+
|
88
|
+
#### `undecorated` modifier
|
89
|
+
|
90
|
+
`Magic::Decorator::Base.undecorated` can be used to exclude methods from being decorated automagically.
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
class MyDecorator < Magic::Decorator::Base
|
94
|
+
undecorated %i[to_s inspect]
|
95
|
+
undecorated :raw_method
|
96
|
+
undecorated :m1, :m2
|
97
|
+
end
|
98
|
+
```
|
64
99
|
|
65
100
|
### Decorator class inference
|
66
101
|
|
@@ -72,6 +107,33 @@ powered by [Magic Lookup](
|
|
72
107
|
For example, `MyNamespace::MyModel.new.decorate` looks for `MyNamespace::MyModelDecorator` first.
|
73
108
|
When missing, it further looks for decorators for its ancestor classes, up to `ObjectDecorator`.
|
74
109
|
|
110
|
+
### Default decorators
|
111
|
+
|
112
|
+
#### `EnumerableDecorator`
|
113
|
+
|
114
|
+
It automagically decorates all its decoratable items.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
[1, [2], { 3 => 4 }, '5'].decorated
|
118
|
+
.map &:decorated? # => [false, true, true, false]
|
119
|
+
|
120
|
+
{ 1 => 2, [3] => [4] }.decorated.keys
|
121
|
+
.map &:decorated? # => [false, true]
|
122
|
+
{ 1 => 2, [3] => [4] }.decorated.values
|
123
|
+
.map &:decorated? # => [false, true]
|
124
|
+
|
125
|
+
{ 1 => 2, [3] => [4] }.decorated[1]
|
126
|
+
.decorated? # => false
|
127
|
+
{ 1 => 2, [3] => [4] }.decorated[[3]]
|
128
|
+
.decorated? # => true
|
129
|
+
```
|
130
|
+
|
131
|
+
##### Side effects for decorated collections
|
132
|
+
|
133
|
+
- enables _splat_ operator: `*decorated` ,
|
134
|
+
- enables _double-splat_ operator: `**decorated`,
|
135
|
+
- enumerating methods yield decorated items.
|
136
|
+
|
75
137
|
## Development
|
76
138
|
|
77
139
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class EnumerableDecorator < Magic::Decorator::Base
|
4
|
+
def to_a(...) = super.map &:decorated
|
5
|
+
def to_ary(...) = super.map &:decorated
|
6
|
+
|
7
|
+
def to_h(...) = super.to_h { |*h| h.map! &:decorated }
|
8
|
+
def to_hash(...) = super.to_h { |*h| h.map! &:decorated }
|
9
|
+
end
|
data/lib/magic/decorator/base.rb
CHANGED
@@ -9,9 +9,51 @@ module Magic
|
|
9
9
|
|
10
10
|
class << self
|
11
11
|
def name_for(object_class) = "#{object_class}Decorator"
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def undecorated method, *methods
|
16
|
+
return [ method, *methods ].map { undecorated _1 } if
|
17
|
+
methods.any?
|
18
|
+
return undecorated *method if
|
19
|
+
method.is_a? Array
|
20
|
+
raise TypeError, "#{method} is not a symbol nor a string" unless
|
21
|
+
method in Symbol | String
|
22
|
+
|
23
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
24
|
+
def #{method}(...) = __getobj__.#{method}(...)
|
25
|
+
RUBY
|
26
|
+
end
|
12
27
|
end
|
13
28
|
|
14
29
|
def decorated? = true
|
30
|
+
|
31
|
+
undecorated %i[
|
32
|
+
deconstruct
|
33
|
+
deconstruct_keys
|
34
|
+
]
|
35
|
+
|
36
|
+
def method_missing(method, ...)
|
37
|
+
return super if method.start_with? 'to_' # converter
|
38
|
+
return super if method.start_with? '_' # system
|
39
|
+
|
40
|
+
if block_given?
|
41
|
+
super { |*args| yield *args.map(&:decorated) }
|
42
|
+
else
|
43
|
+
super
|
44
|
+
end.decorated
|
45
|
+
rescue NoMethodError => error
|
46
|
+
__raise__ error.class.new(
|
47
|
+
error.message.sub(self.class.name, __getobj__.class.name),
|
48
|
+
error.name,
|
49
|
+
error.args,
|
50
|
+
# error.private_call?, # FIXME: not implemented in TruffleRuby
|
51
|
+
|
52
|
+
receiver: __getobj__
|
53
|
+
).tap {
|
54
|
+
_1.set_backtrace error.backtrace[2..] # FIXME: use `backtrace_locations` with Ruby 3.4+
|
55
|
+
}
|
56
|
+
end
|
15
57
|
end
|
16
58
|
end
|
17
59
|
end
|
data/lib/magic/decorator.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: magic-decorator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Senko
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2024-10-
|
10
|
+
date: 2024-10-17 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: magic-lookup
|
@@ -38,11 +38,13 @@ files:
|
|
38
38
|
- LICENSE.txt
|
39
39
|
- README.md
|
40
40
|
- Rakefile
|
41
|
+
- lib/enumerable_decorator.rb
|
41
42
|
- lib/magic/decoratable.rb
|
42
43
|
- lib/magic/decorator.rb
|
43
44
|
- lib/magic/decorator/authors.rb
|
44
45
|
- lib/magic/decorator/base.rb
|
45
46
|
- lib/magic/decorator/version.rb
|
47
|
+
- sig/enumerable_decorator.rbs
|
46
48
|
- sig/gem.rbs
|
47
49
|
- sig/magic/decoratable.rbs
|
48
50
|
- sig/magic/decorator.rbs
|
@@ -53,7 +55,7 @@ licenses:
|
|
53
55
|
metadata:
|
54
56
|
homepage_uri: https://github.com/Alexander-Senko/magic-decorator
|
55
57
|
source_code_uri: https://github.com/Alexander-Senko/magic-decorator
|
56
|
-
changelog_uri: https://github.com/Alexander-Senko/magic-decorator/blob/v0.
|
58
|
+
changelog_uri: https://github.com/Alexander-Senko/magic-decorator/blob/v0.2.0/CHANGELOG.md
|
57
59
|
rdoc_options: []
|
58
60
|
require_paths:
|
59
61
|
- lib
|
@@ -61,7 +63,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
61
63
|
requirements:
|
62
64
|
- - "~>"
|
63
65
|
- !ruby/object:Gem::Version
|
64
|
-
version: '3.
|
66
|
+
version: '3.2'
|
65
67
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
68
|
requirements:
|
67
69
|
- - ">="
|