adornable 1.2.1 → 1.3.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/.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
|