magic-decorator 0.1.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +5 -3
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
|