adornable 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +3 -0
- data/.rubocop.yml +6 -1
- data/Gemfile +1 -0
- data/README.md +5 -1
- data/adornable.gemspec +1 -1
- data/bin/asdf_switch +24 -0
- data/lib/adornable/context.rb +13 -1
- data/lib/adornable/machinery.rb +24 -14
- data/lib/adornable/utils.rb +23 -0
- data/lib/adornable/version.rb +1 -1
- data/lib/adornable.rb +16 -4
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f70e9c6dc00ff446a979d776bb8effbe0063b8e3cb1269081fe3dd78749b1a6d
|
4
|
+
data.tar.gz: dd2ee8ef02b67f5c1c48f83d3f04e9869bac1705c8eb12101c5e90e06274e6d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cc9f4866c9e130ca8fc7d8cf2988a43c252604bf9030b919526d289badc3554d91c2eb4f825462ff6ac491f0f6519aaacff2e2bdd5c5c8a16dda33bd865c735
|
7
|
+
data.tar.gz: 1ecc141ccfff6820a76811bef1427ff90ca4072c35690b732dfbae24a45c6f7c901b8aa83e8172e57d69ad3eca84a50736f8835cfaf3339b56b980a1b72dd1c6
|
data/.github/workflows/main.yml
CHANGED
data/.rubocop.yml
CHANGED
@@ -7,6 +7,7 @@ require:
|
|
7
7
|
|
8
8
|
AllCops:
|
9
9
|
NewCops: enable
|
10
|
+
TargetRubyVersion: 2.5
|
10
11
|
|
11
12
|
# Gemspec
|
12
13
|
|
@@ -29,6 +30,7 @@ Layout/FirstArrayElementIndentation:
|
|
29
30
|
# Metrics
|
30
31
|
|
31
32
|
Metrics/AbcSize:
|
33
|
+
Max: 20
|
32
34
|
CountRepeatedAttributes: false
|
33
35
|
Exclude:
|
34
36
|
- 'spec/**/*_spec.rb'
|
@@ -65,10 +67,13 @@ Metrics/ModuleLength:
|
|
65
67
|
Exclude:
|
66
68
|
- 'spec/**/*_spec.rb'
|
67
69
|
|
70
|
+
Metrics/ParameterLists:
|
71
|
+
CountKeywordArgs: false
|
72
|
+
|
68
73
|
# Rspec
|
69
74
|
|
70
75
|
RSpec/ExampleLength:
|
71
|
-
Max:
|
76
|
+
Max: 40
|
72
77
|
|
73
78
|
RSpec/MessageSpies:
|
74
79
|
Enabled: false
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -4,6 +4,8 @@ Adornable provides the ability to cleanly decorate methods in Ruby. You can make
|
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
+
**NOTE:** This library is tested with Ruby versions 2.5.x through 3.2.x.
|
8
|
+
|
7
9
|
### Locally (to your application)
|
8
10
|
|
9
11
|
Add the gem to your application's `Gemfile`:
|
@@ -232,7 +234,9 @@ The **required argument** is an instance of `Adornable::Context`, which has some
|
|
232
234
|
|
233
235
|
- `Adornable::Context#method_name`: the name of the decorated method being called (a symbol; e.g., `:some_method` or `:other_method`)
|
234
236
|
- `Adornable::Context#method_receiver`: the actual object that the decorated method (the `#method_name`) belongs to/is being called on (an object/class; e.g., the class `Foo` if it's a decorated class method, or an instance of `Foo` if it's a decorated instance method)
|
235
|
-
- `Adornable::Context#method_arguments`: an array of arguments passed to the decorated method, including keyword arguments as a final hash (e.g., if `:yet_another_method` was called like `Foo.new.yet_another_method(123, bar: true)` then `
|
237
|
+
- `Adornable::Context#method_arguments`: an array of arguments passed to the decorated method, including keyword arguments as a final hash (e.g., if `:yet_another_method` was called like `Foo.new.yet_another_method(123, bar: true, baz: 456)` then `method_arguments` would be `[123, {:bar=>true,:baz=>456}]`)
|
238
|
+
- `Adornable::Context#method_positional_args`: an array of just the positional arguments passed to the decorated method, excluding keyword arguments (e.g., if `:yet_another_method` was called like `Foo.new.yet_another_method(123, bar: true, baz: 456)` then `method_positional_args` would be `[123]`)
|
239
|
+
- `Adornable::Context#method_kwargs`: a hash of just the keyword arguments passed to the decorated method (e.g., if `:yet_another_method` was called like `Foo.new.yet_another_method(123, { bam: "hi" }, bar: true, baz: 456)` then `method_kwargs` would be `{:bar=>true,:baz=>456}`)
|
236
240
|
|
237
241
|
##### Custom keyword arguments (optional)
|
238
242
|
|
data/adornable.gemspec
CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.description = "Adornable provides the ability to cleanly decorate methods in Ruby. You can make and use your own decorators, and you can also use some of the built-in ones that the gem provides. _Decorating_ methods is as simple as slapping a `decorate :some_decorator` above your method definition. _Defining_ decorators can be as simple as defining a method that yields to a block, or as complex as manipulating the decorated method's receiver and arguments, and/or changing the functionality of the decorator based on custom options supplied to it when initially applying the decorator." # rubocop:disable Layout/LineLength
|
15
15
|
spec.homepage = "https://github.com/kjleitz/adornable"
|
16
16
|
spec.license = "MIT"
|
17
|
-
spec.required_ruby_version = ">= 2.
|
17
|
+
spec.required_ruby_version = ">= 2.5.0"
|
18
18
|
|
19
19
|
# Specify which files should be added to the gem when it is released.
|
20
20
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
data/bin/asdf_switch
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# First argument should be desired ruby version. If a partial version is given
|
4
|
+
# (e.g., 2.6) and multiple versions are found to be installed (e.g., 2.6.9 and
|
5
|
+
# 2.6.10), then the highest version (in semver version order) will be selected.
|
6
|
+
SELECTED_RUBY_VERSION=$(asdf list ruby | sort -V | sed -e 's/^[[:space:]]*//' | grep "^$1" | tail -n 1)
|
7
|
+
|
8
|
+
if [ -z "$SELECTED_RUBY_VERSION" ]; then
|
9
|
+
echo "Ruby version $1 is not installed. Try running:"
|
10
|
+
echo " asdf install ruby $1"
|
11
|
+
exit 1
|
12
|
+
fi
|
13
|
+
|
14
|
+
echo "Using Ruby version $SELECTED_RUBY_VERSION"
|
15
|
+
|
16
|
+
echo "(setting global Ruby)"
|
17
|
+
asdf global ruby $SELECTED_RUBY_VERSION
|
18
|
+
|
19
|
+
echo "(reshimming for this version)"
|
20
|
+
asdf reshim ruby $SELECTED_RUBY_VERSION
|
21
|
+
|
22
|
+
echo "(reinstalling bundled gems)"
|
23
|
+
bundle install --redownload
|
24
|
+
|
data/lib/adornable/context.rb
CHANGED
@@ -8,14 +8,26 @@ module Adornable
|
|
8
8
|
method_receiver
|
9
9
|
method_name
|
10
10
|
method_arguments
|
11
|
+
method_positional_args
|
12
|
+
method_kwargs
|
11
13
|
decorator_name
|
12
14
|
decorator_options
|
13
15
|
])
|
14
16
|
|
15
|
-
def initialize(
|
17
|
+
def initialize(
|
18
|
+
method_receiver:,
|
19
|
+
method_name:,
|
20
|
+
method_arguments:,
|
21
|
+
method_positional_args:,
|
22
|
+
method_kwargs:,
|
23
|
+
decorator_name:,
|
24
|
+
decorator_options:
|
25
|
+
)
|
16
26
|
@method_receiver = method_receiver
|
17
27
|
@method_name = method_name
|
18
28
|
@method_arguments = method_arguments
|
29
|
+
@method_positional_args = method_positional_args
|
30
|
+
@method_kwargs = method_kwargs
|
19
31
|
@decorator_name = decorator_name
|
20
32
|
@decorator_options = decorator_options
|
21
33
|
end
|
data/lib/adornable/machinery.rb
CHANGED
@@ -38,14 +38,14 @@ module Adornable
|
|
38
38
|
clear_accumulated_decorators!
|
39
39
|
end
|
40
40
|
|
41
|
-
def run_decorated_instance_method(bound_method, *args)
|
41
|
+
def run_decorated_instance_method(bound_method, *args, **kwargs)
|
42
42
|
decorators = get_instance_method_decorators(bound_method.name)
|
43
|
-
run_decorators(decorators, bound_method, *args)
|
43
|
+
run_decorators(decorators, bound_method, *args, **kwargs)
|
44
44
|
end
|
45
45
|
|
46
|
-
def run_decorated_class_method(bound_method, *args)
|
46
|
+
def run_decorated_class_method(bound_method, *args, **kwargs)
|
47
47
|
decorators = get_class_method_decorators(bound_method.name)
|
48
|
-
run_decorators(decorators, bound_method, *args)
|
48
|
+
run_decorators(decorators, bound_method, *args, **kwargs)
|
49
49
|
end
|
50
50
|
|
51
51
|
private
|
@@ -88,8 +88,10 @@ module Adornable
|
|
88
88
|
@class_method_decorators[name] = decorators || []
|
89
89
|
end
|
90
90
|
|
91
|
-
def run_decorators(decorators, bound_method, *
|
92
|
-
|
91
|
+
def run_decorators(decorators, bound_method, *method_positional_args, **method_kwargs)
|
92
|
+
if Adornable::Utils.blank?(decorators)
|
93
|
+
return Adornable::Utils.empty_aware_send(bound_method, :call, method_positional_args, method_kwargs)
|
94
|
+
end
|
93
95
|
|
94
96
|
decorator, *remaining_decorators = decorators
|
95
97
|
decorator_name = decorator[:name]
|
@@ -97,22 +99,30 @@ module Adornable
|
|
97
99
|
decorator_options = decorator[:options]
|
98
100
|
validate_decorator!(decorator_name, decorator_receiver, bound_method)
|
99
101
|
|
102
|
+
# This is for backwards-compatibility between Ruby 2.x and Ruby 3.x; in v3
|
103
|
+
# keyword arguments are treated differently than in v2 with respect to
|
104
|
+
# hash parameter equivalency. Previously, it was easy to just assume
|
105
|
+
# `method_arguments` could be an array with a hash at the end representing
|
106
|
+
# any given keyword arguments. However, in Ruby 3.x, we have to be able to
|
107
|
+
# distinguish between kwargs and trailing positional args of type `Hash`,
|
108
|
+
# so we'll shim `Adornable::Context#method_arguments` to look like it used
|
109
|
+
# to and then provide two new properties, `#method_positional_args` and
|
110
|
+
# `#method_kwargs`, to `Adornable::Context` for explicitness.
|
111
|
+
method_arguments = method_positional_args.dup
|
112
|
+
method_arguments << method_kwargs if Adornable::Utils.present?(method_kwargs)
|
113
|
+
|
100
114
|
context = Adornable::Context.new(
|
101
115
|
method_receiver: bound_method.receiver,
|
102
116
|
method_name: bound_method.name,
|
103
117
|
method_arguments: method_arguments,
|
118
|
+
method_positional_args: method_positional_args,
|
119
|
+
method_kwargs: method_kwargs,
|
104
120
|
decorator_name: decorator_name,
|
105
121
|
decorator_options: decorator_options,
|
106
122
|
)
|
107
123
|
|
108
|
-
|
109
|
-
|
110
|
-
else
|
111
|
-
[decorator_name, context]
|
112
|
-
end
|
113
|
-
|
114
|
-
decorator_receiver.send(*send_parameters) do
|
115
|
-
run_decorators(remaining_decorators, bound_method, *method_arguments)
|
124
|
+
Adornable::Utils.empty_aware_send(decorator_receiver, decorator_name, [context], decorator_options) do
|
125
|
+
run_decorators(remaining_decorators, bound_method, *method_positional_args, **method_kwargs)
|
116
126
|
end
|
117
127
|
end
|
118
128
|
|
data/lib/adornable/utils.rb
CHANGED
@@ -23,6 +23,29 @@ module Adornable
|
|
23
23
|
end
|
24
24
|
"`#{receiver_name}#{name_delimiter}#{method_name}`"
|
25
25
|
end
|
26
|
+
|
27
|
+
# This craziness is here because Ruby 2.6 and below don't like when you
|
28
|
+
# pass even _empty_ arguments to `#call` or `#send` or any other method
|
29
|
+
# with a splat, for callables that take no arguments. For example, this
|
30
|
+
# takes the place of:
|
31
|
+
#
|
32
|
+
# receiver.send(method_name, *splat_args, **splat_kwargs)
|
33
|
+
#
|
34
|
+
# ...or:
|
35
|
+
#
|
36
|
+
# receiver.some_method(*splat_args, **splat_kwargs)
|
37
|
+
#
|
38
|
+
# ...which is not cool <= 2.6.x apparently, if `#some_method` takes zero
|
39
|
+
# arguments even if both `splat_args` and `splat_kwargs` are empty (thus
|
40
|
+
# passing it zero arguments in actuality). Oh well.
|
41
|
+
#
|
42
|
+
def empty_aware_send(receiver, method_name, splat_args, splat_kwargs, &block)
|
43
|
+
return receiver.send(method_name, &block) if splat_args.empty? && splat_kwargs.empty?
|
44
|
+
return receiver.send(method_name, *splat_args, &block) if splat_kwargs.empty?
|
45
|
+
return receiver.send(method_name, **splat_kwargs, &block) if splat_args.empty?
|
46
|
+
|
47
|
+
receiver.send(method_name, *splat_args, **splat_kwargs, &block)
|
48
|
+
end
|
26
49
|
end
|
27
50
|
end
|
28
51
|
end
|
data/lib/adornable/version.rb
CHANGED
data/lib/adornable.rb
CHANGED
@@ -36,10 +36,16 @@ module Adornable
|
|
36
36
|
|
37
37
|
machinery.apply_accumulated_decorators_to_instance_method!(method_name)
|
38
38
|
original_method = instance_method(method_name)
|
39
|
-
|
39
|
+
|
40
|
+
# NB: If you only supply `*args` to the block, you get kwargs as a trailing
|
41
|
+
# Hash member in the `args` array. If you supply both `*args, **kwargs` to
|
42
|
+
# the block, kwargs are excluded from the `args` array and only appear in
|
43
|
+
# the `kwargs` argument as a Hash.
|
44
|
+
define_method(method_name) do |*args, **kwargs|
|
40
45
|
bound_method = original_method.bind(self)
|
41
|
-
machinery.run_decorated_instance_method(bound_method, *args)
|
46
|
+
machinery.run_decorated_instance_method(bound_method, *args, **kwargs)
|
42
47
|
end
|
48
|
+
|
43
49
|
super
|
44
50
|
end
|
45
51
|
|
@@ -49,9 +55,15 @@ module Adornable
|
|
49
55
|
|
50
56
|
machinery.apply_accumulated_decorators_to_class_method!(method_name)
|
51
57
|
original_method = method(method_name)
|
52
|
-
|
53
|
-
|
58
|
+
|
59
|
+
# NB: If you only supply `*args` to the block, you get kwargs as a trailing
|
60
|
+
# Hash member in the `args` array. If you supply both `*args, **kwargs` to
|
61
|
+
# the block, kwargs are excluded from the `args` array and only appear in
|
62
|
+
# the `kwargs` argument as a Hash.
|
63
|
+
define_singleton_method(method_name) do |*args, **kwargs|
|
64
|
+
machinery.run_decorated_class_method(original_method, *args, **kwargs)
|
54
65
|
end
|
66
|
+
|
55
67
|
super
|
56
68
|
end
|
57
69
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adornable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keegan Leitz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Adornable provides the ability to cleanly decorate methods in Ruby. You
|
14
14
|
can make and use your own decorators, and you can also use some of the built-in
|
@@ -33,6 +33,7 @@ files:
|
|
33
33
|
- README.md
|
34
34
|
- Rakefile
|
35
35
|
- adornable.gemspec
|
36
|
+
- bin/asdf_switch
|
36
37
|
- bin/console
|
37
38
|
- bin/setup
|
38
39
|
- lib/adornable.rb
|
@@ -55,14 +56,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
56
|
requirements:
|
56
57
|
- - ">="
|
57
58
|
- !ruby/object:Gem::Version
|
58
|
-
version: 2.
|
59
|
+
version: 2.5.0
|
59
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
61
|
requirements:
|
61
62
|
- - ">="
|
62
63
|
- !ruby/object:Gem::Version
|
63
64
|
version: '0'
|
64
65
|
requirements: []
|
65
|
-
rubygems_version: 3.1
|
66
|
+
rubygems_version: 3.4.1
|
66
67
|
signing_key:
|
67
68
|
specification_version: 4
|
68
69
|
summary: Method decorators for Ruby
|