trailblazer-context 0.1.2 → 0.1.3
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 +5 -5
- data/.gitignore +1 -0
- data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +136 -0
- data/.rubocop.yml +40 -0
- data/.travis.yml +8 -0
- data/CHANGES.md +4 -0
- data/Gemfile +2 -2
- data/Rakefile +5 -2
- data/lib/trailblazer-context.rb +1 -1
- data/lib/trailblazer/container_chain.rb +7 -3
- data/lib/trailblazer/context.rb +25 -12
- data/lib/trailblazer/context/indifferent_access.rb +23 -0
- data/lib/trailblazer/context/version.rb +1 -1
- data/lib/trailblazer/option.rb +1 -1
- data/test/context_test.rb +122 -0
- data/test/option_test.rb +186 -0
- data/test/test_helper.rb +4 -0
- data/trailblazer-context.gemspec +13 -11
- metadata +42 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 65fadb8598cd610a092a09bc79d5ebc754d8f09372dd2dd7a044e2435aea6759
|
4
|
+
data.tar.gz: 9b12d7531efdedaf4786cf0af148657f1db85a500db82538e093254c0ab662bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80552f09f7744038d0d821abea3ed69e085cd5fea0d8416734f3e2fd9b825c8532743049d0a43123023c58cd2162237360542d5256dc382c4fc2d9c434e43f1a
|
7
|
+
data.tar.gz: e32733db3688e262e11ae3a955ca75ab3a9546ae172b8815c6c9c1a4d1566ac604d8d0b752707c19dd59b7f8534b8579bf8e013fcdfe9a08968cc531fc261e4d
|
data/.gitignore
CHANGED
@@ -0,0 +1,136 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.5.0
|
3
|
+
DisplayCopNames: true
|
4
|
+
Layout/CaseIndentation:
|
5
|
+
IndentOneStep: true
|
6
|
+
Layout/FirstArrayElementLineBreak:
|
7
|
+
Enabled: true
|
8
|
+
Layout/FirstHashElementLineBreak:
|
9
|
+
Enabled: true
|
10
|
+
Layout/FirstMethodArgumentLineBreak:
|
11
|
+
Enabled: true
|
12
|
+
Layout/FirstMethodParameterLineBreak:
|
13
|
+
Enabled: true
|
14
|
+
Layout/MultilineAssignmentLayout:
|
15
|
+
Enabled: true
|
16
|
+
EnforcedStyle: same_line
|
17
|
+
Layout/SpaceInsideHashLiteralBraces:
|
18
|
+
EnforcedStyle: no_space
|
19
|
+
Metrics/LineLength:
|
20
|
+
Max: 130
|
21
|
+
Metrics/ParameterLists:
|
22
|
+
Max: 5
|
23
|
+
Naming/VariableNumber:
|
24
|
+
EnforcedStyle: snake_case
|
25
|
+
Style/AndOr:
|
26
|
+
EnforcedStyle: conditionals
|
27
|
+
Style/AutoResourceCleanup:
|
28
|
+
Enabled: true
|
29
|
+
Style/CollectionMethods:
|
30
|
+
Enabled: true
|
31
|
+
Style/Documentation:
|
32
|
+
Enabled: false
|
33
|
+
Style/EmptyLiteral:
|
34
|
+
Enabled: false
|
35
|
+
Style/EmptyMethod:
|
36
|
+
EnforcedStyle: expanded
|
37
|
+
Style/FormatStringToken:
|
38
|
+
EnforcedStyle: template
|
39
|
+
Style/ImplicitRuntimeError:
|
40
|
+
Enabled: true
|
41
|
+
Style/MethodCalledOnDoEndBlock:
|
42
|
+
Enabled: true
|
43
|
+
Style/MethodDefParentheses:
|
44
|
+
EnforcedStyle: require_parentheses
|
45
|
+
Style/MissingElse:
|
46
|
+
Enabled: true
|
47
|
+
EnforcedStyle: case
|
48
|
+
Style/NumericLiterals:
|
49
|
+
Enabled: false
|
50
|
+
Style/OptionHash:
|
51
|
+
Enabled: true
|
52
|
+
Style/PercentLiteralDelimiters:
|
53
|
+
PreferredDelimiters:
|
54
|
+
"%w": "[]"
|
55
|
+
"%W": "[]"
|
56
|
+
"%i": "[]"
|
57
|
+
"%I": "[]"
|
58
|
+
"%r": "()"
|
59
|
+
Style/ReturnNil:
|
60
|
+
Enabled: true
|
61
|
+
Style/SafeNavigation:
|
62
|
+
Enabled: false
|
63
|
+
Style/Send:
|
64
|
+
Enabled: true
|
65
|
+
Style/SignalException:
|
66
|
+
EnforcedStyle: semantic
|
67
|
+
Style/StringLiterals:
|
68
|
+
EnforcedStyle: double_quotes
|
69
|
+
Style/StringLiteralsInInterpolation:
|
70
|
+
EnforcedStyle: double_quotes
|
71
|
+
Style/StringMethods:
|
72
|
+
Enabled: true
|
73
|
+
Style/SymbolArray:
|
74
|
+
Enabled: true
|
75
|
+
# this allows in rspec to have expect { } with multiple lines
|
76
|
+
Style/BlockDelimiters:
|
77
|
+
EnforcedStyle: braces_for_chaining
|
78
|
+
Layout/EndOfLine:
|
79
|
+
Enabled: false
|
80
|
+
# don't need these checks in test folders
|
81
|
+
Metrics/ModuleLength:
|
82
|
+
Exclude:
|
83
|
+
- "spec/**/*"
|
84
|
+
- "test/**/*"
|
85
|
+
Metrics/BlockLength:
|
86
|
+
Exclude:
|
87
|
+
- "spec/**/*"
|
88
|
+
- "test/**/*"
|
89
|
+
- "*.gemspec" # definitely not in the gemspec
|
90
|
+
Metrics/MethodLength:
|
91
|
+
Max: 20
|
92
|
+
Lint/UnreachableCode:
|
93
|
+
Description: 'Unreachable code.'
|
94
|
+
Enabled: false
|
95
|
+
Lint/Void:
|
96
|
+
Enabled: false
|
97
|
+
Layout/AlignHash:
|
98
|
+
EnforcedLastArgumentHashStyle: ignore_implicit
|
99
|
+
Metrics/AbcSize:
|
100
|
+
Max: 25
|
101
|
+
Style/LambdaCall:
|
102
|
+
Enabled: false
|
103
|
+
Style/Semicolon:
|
104
|
+
Enabled: false
|
105
|
+
Naming/UncommunicativeMethodParamName:
|
106
|
+
Enabled: false
|
107
|
+
Style/ClassAndModuleChildren:
|
108
|
+
Enabled: false
|
109
|
+
Layout/LeadingCommentSpace:
|
110
|
+
Exclude:
|
111
|
+
- 'test/docs/**/*'
|
112
|
+
Layout/AlignHash:
|
113
|
+
EnforcedHashRocketStyle: table
|
114
|
+
Style/FrozenStringLiteralComment:
|
115
|
+
Enabled: false
|
116
|
+
Layout/AlignHash:
|
117
|
+
EnforcedColonStyle: table
|
118
|
+
SingleLineMethods:
|
119
|
+
Enabled: false
|
120
|
+
Style/Lambda:
|
121
|
+
EnforcedStyle: literal
|
122
|
+
Style/AsciiComments:
|
123
|
+
Enabled: false
|
124
|
+
Style/CollectionMethods:
|
125
|
+
Enabled: false
|
126
|
+
Style/RedundantReturn:
|
127
|
+
Enabled: false
|
128
|
+
Style/PercentLiteralDelimiters:
|
129
|
+
PreferredDelimiters:
|
130
|
+
default: {}
|
131
|
+
"%q": '()'
|
132
|
+
"%r": '{}'
|
133
|
+
"%w": '[]'
|
134
|
+
"%": '{}'
|
135
|
+
Style/HashSyntax:
|
136
|
+
Enabled: false
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.2
|
3
|
+
|
4
|
+
inherit_from:
|
5
|
+
- https://raw.githubusercontent.com/trailblazer/meta/master/rubocop.yml
|
6
|
+
|
7
|
+
Lint/UnusedMethodArgument:
|
8
|
+
Exclude:
|
9
|
+
- 'lib/trailblazer/option.rb'
|
10
|
+
|
11
|
+
Metrics/ClassLength:
|
12
|
+
Exclude:
|
13
|
+
- 'test/**'
|
14
|
+
|
15
|
+
Style/ImplicitRuntimeError:
|
16
|
+
Exclude:
|
17
|
+
- 'lib/trailblazer/option.rb'
|
18
|
+
|
19
|
+
Naming/UncommunicativeMethodParamName:
|
20
|
+
Exclude:
|
21
|
+
- 'test/option_test.rb'
|
22
|
+
|
23
|
+
Style/ClassAndModuleChildren:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
# wants to use map instead of collect
|
27
|
+
Style/CollectionMethods:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
# wants to use fail instea of raise
|
31
|
+
Style/SignalException:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
# because in gemspec we say >= 2.0.0 wants to have 2.0 as target ruby version here but
|
35
|
+
# it's not supported anymore from rubocop
|
36
|
+
Gemspec/RequiredRubyVersion:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
Style/Lambda:
|
40
|
+
EnforcedStyle: literal
|
data/.travis.yml
ADDED
data/CHANGES.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# 0.1.3
|
2
|
+
|
3
|
+
* Introduce `Context::IndifferentAccess` which converts all keys to symbol. This, in turn, allows to use both string and symbol keys everywhere. Currently, the implementation is set via the global method `Context.implementation` and defaults to the new `IndifferentAccess`.
|
4
|
+
|
1
5
|
# 0.1.2
|
2
6
|
|
3
7
|
* More meaningful error message: "No :exec_context given.".
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
|
+
require "rubocop/rake_task"
|
3
4
|
|
4
5
|
Rake::TestTask.new(:test) do |t|
|
5
6
|
t.libs << "test"
|
6
7
|
t.libs << "lib"
|
7
|
-
t.test_files = FileList[
|
8
|
+
t.test_files = FileList["test/*_test.rb"]
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
+
RuboCop::RakeTask.new(:rubocop)
|
12
|
+
|
13
|
+
task default: %i[test rubocop]
|
data/lib/trailblazer-context.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# @private
|
2
|
-
|
2
|
+
# used to be called Resolver.
|
3
|
+
class Trailblazer::Context::ContainerChain
|
3
4
|
# Keeps a list of containers. When looking up a key/value, containers are traversed in
|
4
5
|
# the order they were added until key is found.
|
5
6
|
#
|
@@ -28,18 +29,21 @@ class Trailblazer::Context::ContainerChain # used to be called Resolver.
|
|
28
29
|
|
29
30
|
def keys
|
30
31
|
@containers.collect(&:keys).flatten
|
31
|
-
end
|
32
|
+
end
|
32
33
|
|
33
34
|
# @private
|
34
35
|
def to_hash
|
35
|
-
|
36
|
+
# FIXME: introduce pattern matching so we can have different "transformers" for each container type.
|
37
|
+
return @to_hash.(@containers) if @to_hash
|
36
38
|
@containers.each_with_object({}) { |container, hash| hash.merge!(container.to_hash) }
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
42
|
+
# rubocop:disable Style/AsciiComments
|
40
43
|
# alternative implementation:
|
41
44
|
# containers.reverse.each do |container| @mutable_options.merge!(container) end
|
42
45
|
#
|
43
46
|
# benchmark, merging in #initialize vs. this resolver.
|
44
47
|
# merge 39.678k (± 9.1%) i/s - 198.700k in 5.056653s
|
45
48
|
# resolver 68.928k (± 6.4%) i/s - 342.836k in 5.001610s
|
49
|
+
# rubocop:enable Style/AsciiComments
|
data/lib/trailblazer/context.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "trailblazer/option"
|
1
2
|
# TODO: mark/make all but mutable_options as frozen.
|
2
3
|
# The idea of Skill is to have a generic, ordered read/write interface that
|
3
4
|
# collects mutable runtime-computed data while providing access to compile-time
|
@@ -11,10 +12,24 @@ module Trailblazer
|
|
11
12
|
# activity (aka wrapped_options).
|
12
13
|
|
13
14
|
# only public creator: Build
|
14
|
-
|
15
|
+
# :data object:
|
16
|
+
class Context
|
17
|
+
# NOTE: in the future, we might look up the Context to use in the ctx.
|
18
|
+
# The options we pass in here to be forward-compatible.
|
19
|
+
def self.for(wrapped_options, (ctx, flow_options), circuit_options)
|
20
|
+
implementation.new(wrapped_options, {})
|
21
|
+
end
|
22
|
+
|
23
|
+
# I hate globals, but currently this is the only easy way for setting the implementation.
|
24
|
+
def self.implementation
|
25
|
+
IndifferentAccess
|
26
|
+
end
|
27
|
+
|
15
28
|
def initialize(wrapped_options, mutable_options)
|
16
|
-
@wrapped_options
|
17
|
-
|
29
|
+
@wrapped_options = wrapped_options
|
30
|
+
@mutable_options = mutable_options
|
31
|
+
# TODO: wrapped_options should be optimized for lookups here since
|
32
|
+
# it could also be a Context instance, but should be a ContainerChain.
|
18
33
|
end
|
19
34
|
|
20
35
|
def [](name)
|
@@ -39,26 +54,22 @@ module Trailblazer
|
|
39
54
|
end
|
40
55
|
|
41
56
|
# @private
|
42
|
-
#
|
43
|
-
# This method might be removed.
|
44
57
|
def merge(hash)
|
45
58
|
original, mutable_options = decompose
|
46
59
|
|
47
|
-
|
60
|
+
self.class.new(original, mutable_options.merge(hash))
|
48
61
|
end
|
49
62
|
|
50
63
|
# Return the Context's two components. Used when computing the new output for
|
51
64
|
# the next activity.
|
52
65
|
def decompose
|
53
|
-
[
|
66
|
+
[@wrapped_options, @mutable_options]
|
54
67
|
end
|
55
68
|
|
56
69
|
def keys
|
57
70
|
@mutable_options.keys + @wrapped_options.keys # FIXME.
|
58
71
|
end
|
59
72
|
|
60
|
-
|
61
|
-
|
62
73
|
# TODO: maybe we shouldn't allow to_hash from context?
|
63
74
|
# TODO: massive performance bottleneck. also, we could already "know" here what keys the
|
64
75
|
# transformation wants.
|
@@ -66,14 +77,16 @@ module Trailblazer
|
|
66
77
|
def to_hash
|
67
78
|
{}.tap do |hash|
|
68
79
|
# the "key" here is to call to_hash on all containers.
|
69
|
-
[
|
80
|
+
[@wrapped_options.to_hash, @mutable_options.to_hash].each do |options|
|
70
81
|
options.each { |k, v| hash[k.to_sym] = v }
|
71
82
|
end
|
72
83
|
end
|
73
84
|
end
|
74
85
|
end
|
75
86
|
|
76
|
-
def self.Context(wrapped_options, mutable_options={})
|
87
|
+
def self.Context(wrapped_options, mutable_options = {})
|
77
88
|
Context.new(wrapped_options, mutable_options)
|
78
89
|
end
|
79
|
-
end
|
90
|
+
end
|
91
|
+
|
92
|
+
require "trailblazer/context/indifferent_access"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Trailblazer
|
2
|
+
class Context
|
3
|
+
class IndifferentAccess < Context
|
4
|
+
def [](name)
|
5
|
+
super(name.to_sym)
|
6
|
+
end
|
7
|
+
|
8
|
+
def []=(name, value)
|
9
|
+
super(name.to_sym, value)
|
10
|
+
end
|
11
|
+
|
12
|
+
def key?(name)
|
13
|
+
super(name.to_sym)
|
14
|
+
end
|
15
|
+
|
16
|
+
def merge(hash)
|
17
|
+
hash = Hash[hash.collect { |k,v| [k.to_sym, v] }]
|
18
|
+
|
19
|
+
super(hash)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/trailblazer/option.rb
CHANGED
@@ -33,7 +33,7 @@ module Trailblazer
|
|
33
33
|
|
34
34
|
# Make the context's instance method a "lambda" and reuse #call!.
|
35
35
|
# @private
|
36
|
-
def self.evaluate_method(proc, *args, exec_context:raise("No :exec_context given."), **flow_options, &block)
|
36
|
+
def self.evaluate_method(proc, *args, exec_context: raise("No :exec_context given."), **flow_options, &block)
|
37
37
|
call!(exec_context.method(proc), *args, &block)
|
38
38
|
end
|
39
39
|
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "trailblazer/container_chain"
|
3
|
+
|
4
|
+
class ArgsTest < Minitest::Spec
|
5
|
+
Context = Trailblazer::Context
|
6
|
+
|
7
|
+
let(:immutable) { {repository: "User"} }
|
8
|
+
|
9
|
+
let(:ctx) { Trailblazer::Context(immutable) }
|
10
|
+
|
11
|
+
it do
|
12
|
+
ctx = Trailblazer::Context(immutable)
|
13
|
+
|
14
|
+
# it { }
|
15
|
+
#-
|
16
|
+
# options[] and options[]=
|
17
|
+
ctx[:model] = Module
|
18
|
+
ctx[:contract] = Integer
|
19
|
+
ctx[:model] .must_equal Module
|
20
|
+
ctx[:contract].must_equal Integer
|
21
|
+
|
22
|
+
# it { }
|
23
|
+
immutable.inspect.must_equal %({:repository=>\"User\"})
|
24
|
+
end
|
25
|
+
|
26
|
+
it "allows false/nil values" do
|
27
|
+
ctx["x"] = false
|
28
|
+
ctx["x"].must_equal false
|
29
|
+
|
30
|
+
ctx["x"] = nil
|
31
|
+
assert_nil ctx["x"]
|
32
|
+
end
|
33
|
+
|
34
|
+
#- #to_hash
|
35
|
+
it do
|
36
|
+
ctx = Trailblazer::Context(immutable)
|
37
|
+
|
38
|
+
# it { }
|
39
|
+
ctx.to_hash.must_equal(repository: "User")
|
40
|
+
|
41
|
+
# last added has precedence.
|
42
|
+
# only symbol keys.
|
43
|
+
# it { }
|
44
|
+
ctx[:a] = Symbol
|
45
|
+
ctx["a"] = String
|
46
|
+
|
47
|
+
ctx.to_hash.must_equal(repository: "User", a: String)
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#merge" do
|
51
|
+
it do
|
52
|
+
ctx = Trailblazer::Context(immutable)
|
53
|
+
|
54
|
+
merged = ctx.merge(current_user: Module)
|
55
|
+
|
56
|
+
merged.to_hash.must_equal(repository: "User", current_user: Module)
|
57
|
+
ctx.to_hash.must_equal(repository: "User")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#-
|
62
|
+
it do
|
63
|
+
immutable = {repository: "User", model: Module, current_user: Class}
|
64
|
+
|
65
|
+
Trailblazer::Context(immutable) do |_original, mutable|
|
66
|
+
mutable
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class ContextWithIndifferentAccessTest < Minitest::Spec
|
72
|
+
it do
|
73
|
+
flow_options = {}
|
74
|
+
circuit_options = {}
|
75
|
+
|
76
|
+
immutable = {model: Object}
|
77
|
+
|
78
|
+
ctx = Trailblazer::Context.for(immutable, [immutable, flow_options], circuit_options)
|
79
|
+
|
80
|
+
ctx[:model].must_equal Object
|
81
|
+
ctx["model"].must_equal Object
|
82
|
+
|
83
|
+
ctx["contract.default"] = Module
|
84
|
+
ctx["contract.default"].must_equal Module
|
85
|
+
ctx[:"contract.default"].must_equal Module
|
86
|
+
|
87
|
+
# key?
|
88
|
+
ctx.key?("contract.default").must_equal true
|
89
|
+
ctx.key?(:"contract.default").must_equal true
|
90
|
+
|
91
|
+
# context in context
|
92
|
+
ctx2 = Trailblazer::Context.for(ctx, [ctx, flow_options], circuit_options)
|
93
|
+
|
94
|
+
ctx2[:model].must_equal Object
|
95
|
+
ctx2["model"].must_equal Object
|
96
|
+
|
97
|
+
ctx2["contract.default"] = Class
|
98
|
+
ctx2["contract.default"].must_equal Class
|
99
|
+
ctx2[:"contract.default"].must_equal Class
|
100
|
+
|
101
|
+
# key?
|
102
|
+
ctx2.key?("contract.default").must_equal true
|
103
|
+
ctx2.key?(:"contract.default").must_equal true
|
104
|
+
ctx2.key?("model").must_equal true
|
105
|
+
|
106
|
+
# wrapped ctx doesn't change
|
107
|
+
ctx["contract.default"].must_equal Module
|
108
|
+
ctx[:"contract.default"].must_equal Module
|
109
|
+
|
110
|
+
|
111
|
+
ctx3 = ctx.merge("result" => false)
|
112
|
+
|
113
|
+
ctx3["contract.default"].must_equal Module
|
114
|
+
ctx3[:"contract.default"].must_equal Module
|
115
|
+
ctx3["result"].must_equal false
|
116
|
+
ctx3[:result].must_equal false
|
117
|
+
ctx3.key?("result").must_equal true
|
118
|
+
ctx3.key?(:result).must_equal true
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# TODO: test overriding Context.implementation.
|
data/test/option_test.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class OptionTest < Minitest::Spec
|
4
|
+
def assert_result(result, block = nil)
|
5
|
+
result.must_equal([{a: 1}, 2, {b: 3}, block])
|
6
|
+
|
7
|
+
positional.inspect.must_equal %({:a=>1})
|
8
|
+
keywords.inspect.must_equal %({:a=>2, :b=>3})
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "positional and kws" do
|
12
|
+
class Step
|
13
|
+
def with_positional_and_keywords(options, a: nil, **more_options, &block)
|
14
|
+
[options, a, more_options, block]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
WITH_POSITIONAL_AND_KEYWORDS = ->(options, a: nil, **more_options, &block) do
|
19
|
+
[options, a, more_options, block]
|
20
|
+
end
|
21
|
+
|
22
|
+
class WithPositionalAndKeywords
|
23
|
+
def self.call(options, a: nil, **more_options, &block)
|
24
|
+
[options, a, more_options, block]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:positional) { {a: 1} }
|
29
|
+
let(:keywords) { {a: 2, b: 3} }
|
30
|
+
|
31
|
+
let(:block) { ->(*) { snippet } }
|
32
|
+
|
33
|
+
describe ":method" do
|
34
|
+
let(:option) { Trailblazer::Option(:with_positional_and_keywords) }
|
35
|
+
|
36
|
+
it "passes through all args" do
|
37
|
+
step = Step.new
|
38
|
+
|
39
|
+
# positional = { a: 1 }
|
40
|
+
# keywords = { a: 2, b: 3 }
|
41
|
+
assert_result option.(positional, keywords, exec_context: step)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "allows passing a block, too" do
|
45
|
+
step = Step.new
|
46
|
+
|
47
|
+
assert_result option.(positional, keywords, {exec_context: step}, &block), block
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "lambda" do
|
52
|
+
let(:option) { Trailblazer::Option(WITH_POSITIONAL_AND_KEYWORDS) }
|
53
|
+
|
54
|
+
it "-> {} lambda" do
|
55
|
+
assert_result option.(positional, keywords, {})
|
56
|
+
end
|
57
|
+
|
58
|
+
it "allows passing a block, too" do
|
59
|
+
assert_result option.(positional, keywords, {}, &block), block
|
60
|
+
end
|
61
|
+
|
62
|
+
it "doesn't mind :exec_context" do
|
63
|
+
assert_result option.(positional, keywords, exec_context: "bogus")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "Callable" do
|
68
|
+
let(:option) { Trailblazer::Option(WithPositionalAndKeywords) }
|
69
|
+
|
70
|
+
it "passes through all args" do
|
71
|
+
assert_result option.(positional, keywords, exec_context: nil)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "allows passing a block, too" do
|
75
|
+
assert_result option.(positional, keywords, {exec_context: nil}, &block), block
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "positionals" do
|
81
|
+
def assert_result_pos(result)
|
82
|
+
result.must_equal([1, 2, [3, 4]])
|
83
|
+
positionals.must_equal [1, 2, 3, 4]
|
84
|
+
end
|
85
|
+
|
86
|
+
class Step
|
87
|
+
def with_positionals(a, b, *args)
|
88
|
+
[a, b, args]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
WITH_POSITIONALS = ->(a, b, *args) do
|
93
|
+
[a, b, args]
|
94
|
+
end
|
95
|
+
|
96
|
+
class WithPositionals
|
97
|
+
def self.call(a, b, *args)
|
98
|
+
[a, b, args]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
let(:positionals) { [1, 2, 3, 4] }
|
103
|
+
|
104
|
+
it ":method" do
|
105
|
+
step = Step.new
|
106
|
+
|
107
|
+
option = Trailblazer::Option(:with_positionals)
|
108
|
+
|
109
|
+
assert_result_pos option.(*positionals, exec_context: step)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "-> {} lambda" do
|
113
|
+
option = Trailblazer::Option(WITH_POSITIONALS)
|
114
|
+
|
115
|
+
assert_result_pos option.(*positionals, exec_context: "something")
|
116
|
+
end
|
117
|
+
|
118
|
+
it "callable" do
|
119
|
+
option = Trailblazer::Option(WithPositionals)
|
120
|
+
|
121
|
+
assert_result_pos option.(*positionals, exec_context: "something")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "Option::KW" do
|
126
|
+
def assert_result_kws(result)
|
127
|
+
result.must_equal([{a: 1, b: 2, c: 3}, 1, 2, {c: 3}])
|
128
|
+
end
|
129
|
+
|
130
|
+
class Step
|
131
|
+
def with_kws(options, a: nil, b: nil, **rest)
|
132
|
+
[options, a, b, rest]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
module Task
|
137
|
+
def self.with_kws(options, a: nil, b: nil, **rest)
|
138
|
+
[options, a, b, rest]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
WITH_KWS = ->(options, a: nil, b: nil, **rest) do
|
143
|
+
[options, a, b, rest]
|
144
|
+
end
|
145
|
+
|
146
|
+
class WithKWs
|
147
|
+
def self.call(options, a: nil, b: nil, **rest)
|
148
|
+
[options, a, b, rest]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
let(:options) { {a: 1, b: 2, c: 3} }
|
153
|
+
|
154
|
+
it ":method" do
|
155
|
+
step = Step.new
|
156
|
+
|
157
|
+
option = Trailblazer::Option::KW(:with_kws)
|
158
|
+
|
159
|
+
assert_result_kws option.(options, exec_context: step)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "Method instance" do
|
163
|
+
option = Trailblazer::Option::KW(Task.method(:with_kws))
|
164
|
+
|
165
|
+
assert_result_kws option.(options, {})
|
166
|
+
end
|
167
|
+
|
168
|
+
it "-> {} lambda" do
|
169
|
+
option = Trailblazer::Option::KW(WITH_KWS)
|
170
|
+
|
171
|
+
assert_result_kws option.(options, {})
|
172
|
+
end
|
173
|
+
|
174
|
+
it "lambda ignores :exec_context" do
|
175
|
+
option = Trailblazer::Option::KW(WITH_KWS)
|
176
|
+
|
177
|
+
assert_result_kws option.(options, exec_context: "something")
|
178
|
+
end
|
179
|
+
|
180
|
+
it "callable" do
|
181
|
+
option = Trailblazer::Option::KW(WithKWs)
|
182
|
+
|
183
|
+
assert_result_kws option.(options, {})
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/test/test_helper.rb
ADDED
data/trailblazer-context.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
lib = File.expand_path(
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require
|
3
|
+
require "trailblazer/context/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "trailblazer-context"
|
@@ -8,21 +8,23 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ["Nick Sutterer"]
|
9
9
|
spec.email = ["apotonick@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
11
|
+
spec.summary = "Argument-specific data structures for Trailblazer."
|
12
|
+
spec.description = "Argument-specific data structures for Trailblazer such as Context, Option and ContainerChain."
|
13
13
|
spec.homepage = "http://trailblazer.to/gems/workflow"
|
14
14
|
spec.licenses = ["MIT"]
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
-
f.match(%r
|
17
|
+
f.match(%r(^test/))
|
18
18
|
end
|
19
|
-
spec.
|
20
|
-
|
19
|
+
spec.test_files = `git ls-files -z test`.split("\x0")
|
20
|
+
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler"
|
24
|
-
spec.add_development_dependency "
|
25
|
-
spec.add_development_dependency "
|
23
|
+
spec.add_development_dependency "bundler"
|
24
|
+
spec.add_development_dependency "minitest"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rubocop"
|
26
27
|
|
27
|
-
|
28
|
+
# maybe we could remove this?
|
29
|
+
spec.required_ruby_version = ">= 2.0.0"
|
28
30
|
end
|
metadata
CHANGED
@@ -1,57 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-context
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- - "
|
45
|
+
- - ">="
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
47
|
+
version: '0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- - "
|
52
|
+
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: rubocop
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - "
|
59
|
+
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - "
|
66
|
+
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '0'
|
55
69
|
description: Argument-specific data structures for Trailblazer such as Context, Option
|
56
70
|
and ContainerChain.
|
57
71
|
email:
|
@@ -61,6 +75,9 @@ extensions: []
|
|
61
75
|
extra_rdoc_files: []
|
62
76
|
files:
|
63
77
|
- ".gitignore"
|
78
|
+
- ".rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml"
|
79
|
+
- ".rubocop.yml"
|
80
|
+
- ".travis.yml"
|
64
81
|
- CHANGES.md
|
65
82
|
- Gemfile
|
66
83
|
- LICENSE
|
@@ -69,8 +86,12 @@ files:
|
|
69
86
|
- lib/trailblazer-context.rb
|
70
87
|
- lib/trailblazer/container_chain.rb
|
71
88
|
- lib/trailblazer/context.rb
|
89
|
+
- lib/trailblazer/context/indifferent_access.rb
|
72
90
|
- lib/trailblazer/context/version.rb
|
73
91
|
- lib/trailblazer/option.rb
|
92
|
+
- test/context_test.rb
|
93
|
+
- test/option_test.rb
|
94
|
+
- test/test_helper.rb
|
74
95
|
- trailblazer-context.gemspec
|
75
96
|
homepage: http://trailblazer.to/gems/workflow
|
76
97
|
licenses:
|
@@ -92,8 +113,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
113
|
version: '0'
|
93
114
|
requirements: []
|
94
115
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.
|
116
|
+
rubygems_version: 2.7.3
|
96
117
|
signing_key:
|
97
118
|
specification_version: 4
|
98
119
|
summary: Argument-specific data structures for Trailblazer.
|
99
|
-
test_files:
|
120
|
+
test_files:
|
121
|
+
- test/context_test.rb
|
122
|
+
- test/option_test.rb
|
123
|
+
- test/test_helper.rb
|