trailblazer 2.1.0.rc1 → 2.1.0.rc12

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,46 +0,0 @@
1
- module Trailblazer
2
- module Deprecation
3
- module Operation
4
- # This is super hacky. Fix you call calls everywhere (shouldn't take too long) and never load this file, again.
5
- module Call
6
- def self.options_for_call(params, *containers)
7
- if containers == []
8
- if params.is_a?(Hash) # this means we assume everything is cool. Create.( {...} )
9
-
10
- else # this means someone did Create.( #<WeirdParamsObject> )
11
- deprecate_positional_params(params, *containers)
12
- return { params: params }, *containers
13
- end
14
- else # Create.( params, "current_user" => ... )
15
- options, containers = containers[0], (containers[1..-1] || [])
16
- if options.is_a?(Hash) # old API
17
- warn "[Trailblazer] Please don't pass the `params` object as a positional argument into `Operation.()`, use the `:params` key and one hash for all: `Operation.( params: my_params, current_user: ... )` ."
18
- return options.merge( params: params ), *containers
19
- end
20
- end
21
-
22
- return params, *containers
23
- end
24
-
25
- def self.deprecate_positional_params(params, *containers)
26
- warn "[Trailblazer] Please don't pass the `params` object as a positional argument into `Operation.()`, use the `:params` key: `Operation.( params: my_params )` ."
27
- end
28
- end
29
- end
30
- end
31
- end
32
-
33
- Trailblazer::Operation.module_eval do
34
- # this sucks:
35
- def self.call(options={}, *containers)
36
- options, *containers = Trailblazer::Deprecation::Operation::Call.options_for_call(options, *containers)
37
-
38
- ctx = Trailblazer::Operation::PublicCall.options_for_public_call(options, *containers)
39
-
40
- # call the activity.
41
- last_signal, (options, flow_options) = __call__( [ctx, {}] ) # Railway::call # DISCUSS: this could be ::call_with_context.
42
-
43
- # Result is successful if the activity ended with an End event derived from Railway::End::Success.
44
- Trailblazer::Operation::Railway::Result(last_signal, options, flow_options)
45
- end
46
- end
@@ -1,43 +0,0 @@
1
- module Trailblazer
2
- module Deprecation
3
- class ContextWithIndifferentAccess < Trailblazer::Context
4
- def [](key)
5
- return super unless Trailblazer::Operation::PublicCall.deprecatable?(key)
6
- key, _ = Trailblazer::Operation::PublicCall.deprecate_string(key, nil)
7
- super(key)
8
- end
9
-
10
- def []=(key, value)
11
- return super unless Trailblazer::Operation::PublicCall.deprecatable?(key)
12
- key, _ = Trailblazer::Operation::PublicCall.deprecate_string(key, nil)
13
- super(key, value)
14
- end
15
- end
16
- end
17
- end
18
-
19
- Trailblazer::Operation::PublicCall.module_eval do
20
- def self.options_for_public_call(options={}, *containers)
21
- hash_transformer = ->(containers) { containers[0].to_hash } # FIXME: don't transform any containers into kw args.
22
-
23
- options = deprecate_strings(options)
24
-
25
- immutable_options = Trailblazer::Context::ContainerChain.new( [options, *containers], to_hash: hash_transformer ) # Runtime options, immutable.
26
-
27
- Trailblazer::Deprecation::ContextWithIndifferentAccess.new(immutable_options, {})
28
- end
29
-
30
- def self.deprecatable?(key)
31
- key.is_a?(String) && key.split(".").size == 1
32
- end
33
-
34
- def self.deprecate_strings(options)
35
- ary = options.collect { |k,v| deprecatable?(k) ? deprecate_string(k, v) : [k,v] }
36
- Hash[ary]
37
- end
38
-
39
- def self.deprecate_string(key, value)
40
- warn "[Trailblazer] Using a string key for non-namespaced keys is deprecated. Please use `:#{key}` instead of `#{key.inspect}`."
41
- [ key.to_sym, value ]
42
- end
43
- end
@@ -1,47 +0,0 @@
1
- module Trailblazer
2
- module DSL
3
- # Boring DSL code that allows to set a skill class, or define it ad-hoc using a block.
4
- # passing a constant always wipes out the existing class.
5
- #
6
- # Used in Contract, Representer, Callback, ..
7
- class Build
8
- # options[:prefix]
9
- # options[:class]
10
- # options[:container]
11
-
12
- # Currently, adds .class only to classes. this could break builder instances?
13
-
14
- def call(options, name=nil, constant=nil, dsl_block, &block)
15
- # contract MyForm
16
- if name.is_a?(Class)
17
- constant = name
18
- name = :default
19
- end
20
-
21
- is_instance = !(constant.kind_of?(Class) || dsl_block) # i don't like this magic too much, but since it's the only DSL method in TRB, it should be ok. # DISCUSS: options[:is_instance]
22
-
23
- path = path_name(options[:prefix], name, is_instance ? nil : "class") # "contract.default.class"
24
-
25
- if is_instance
26
- skill = constant
27
- else
28
- extended = options[:container][path] # Operation["contract.default.class"]
29
- extended = yield extended if extended && block_given?
30
-
31
- # only extend an existing skill class when NO constant was passed.
32
- constant = (extended || options[:class]) if constant.nil?# && block_given?
33
-
34
- skill = Class.new(constant)
35
- skill.class_eval(&dsl_block) if dsl_block
36
- end
37
-
38
- [path, skill]
39
- end
40
-
41
- private
42
- def path_name(prefix, name, suffix)
43
- [prefix, name, suffix].compact.join(".") # "contract.class" for default, otherwise "contract.params.class" etc.
44
- end
45
- end
46
- end
47
- end
@@ -1,47 +0,0 @@
1
- require "dry/auto_inject"
2
-
3
- class Trailblazer::Operation
4
- # Thanks, @timriley! <3
5
- # https://gist.github.com/timriley/d314a58da9784912159006e208ba8ea9
6
- module AutoInject
7
- class InjectStrategy < Module
8
- ClassMethods = Class.new(Module)
9
-
10
- attr_reader :container
11
- attr_reader :dependency_map
12
- attr_reader :class_mod
13
-
14
- def initialize(container, *dependency_names)
15
- @container = container
16
- @dependency_map = Dry::AutoInject::DependencyMap.new(*dependency_names)
17
- @class_mod = ClassMethods.new
18
- end
19
-
20
- def included(klass)
21
- define_call
22
-
23
- klass.singleton_class.prepend @class_mod
24
-
25
- super
26
- end
27
-
28
- private
29
-
30
- def define_call
31
- class_mod.class_exec(container, dependency_map) do |container, dependency_map|
32
- define_method :call_with_public_interface do |ctx={}, *dependencies|
33
- ctx_with_deps = dependency_map.to_h.each_with_object({}) { |(name, identifier), obj|
34
- obj[name] = ctx[name] || container[identifier]
35
- }.merge(ctx)
36
-
37
- super(ctx_with_deps, *dependencies)
38
- end
39
- end
40
- end
41
- end
42
- end
43
-
44
- def self.AutoInject(container)
45
- Dry::AutoInject(container, strategies: {default: AutoInject::InjectStrategy})
46
- end
47
- end
@@ -1,21 +0,0 @@
1
- module Trailblazer
2
- class Operation
3
- class DeprecatedOptions < Option
4
- def self.call!(proc, direction, options, flow_options, *args)
5
- if proc.is_a?(Proc) && proc.arity == 1
6
- deprecate(proc)
7
- proc.(options)
8
- elsif proc.method(:call).arity == 1
9
- deprecate(proc)
10
- proc.(options)
11
- else
12
- super
13
- end
14
- end
15
-
16
- def self.deprecate(proc)
17
- warn "[Trailblazer] Please use the step API `def my_step!(options, **)` for your step: #{proc}"
18
- end
19
- end # DeprecatedOptions
20
- end
21
- end
@@ -1,29 +0,0 @@
1
- module Trailblazer::Operation::Module
2
- def self.included(base)
3
- base.extend ClassMethods
4
- base.extend Included
5
- end
6
-
7
- module Included # TODO: use representable's inheritance mechanism.
8
- def included(base)
9
- super
10
- instructions.each { |cfg|
11
- method = cfg[0]
12
- args = cfg[1].dup
13
- block = cfg[2]
14
- # options = args.extract_options!.dup # we need to duplicate options has as AM::Validations messes it up later.
15
-
16
- base.send(method, *args, &block) } # property :name, {} do .. end
17
- end
18
- end
19
-
20
- module ClassMethods
21
- def method_missing(method, *args, &block)
22
- instructions << [method, args, block]
23
- end
24
-
25
- def instructions
26
- @instructions ||= []
27
- end
28
- end
29
- end
@@ -1,17 +0,0 @@
1
- module Trailblazer
2
- module Test
3
- module Run
4
- # DISCUSS: use Endpoint here?
5
- # DISCUSS: use Controller code here?
6
- module_function
7
- def run(operation_class, *args)
8
- result = operation_class.(*args)
9
-
10
- raise "[Trailblazer] #{operation_class} wasn't run successfully. #{result.inspect}" if result.failure?
11
-
12
- result
13
-
14
- end
15
- end
16
- end
17
- end
@@ -1,63 +0,0 @@
1
- require "test_helper"
2
-
3
- require "benchmark/ips"
4
-
5
-
6
- def positional_vs_decompose
7
- arg = [ [1, 2], 3 ]
8
-
9
- def a((one, two), three)
10
- one + two + three
11
- end
12
-
13
- def b(arr, three)
14
- arr[0] + arr[1] + three
15
- end
16
-
17
- Benchmark.ips do |x|
18
- x.report("decompose") { a(*arg) }
19
- x.report("positional") { b(*arg) }
20
- x.compare!
21
- end
22
-
23
- # decompose 5.646M (± 3.1%) i/s - 28.294M in 5.015759s
24
- # positional 5.629M (± 8.0%) i/s - 28.069M in 5.029745s
25
- end
26
-
27
- # positional_vs_decompose
28
-
29
- ##########################################################
30
-
31
- class Callable
32
- def initialize(proc, i)
33
- @proc = proc
34
- @i = i
35
- end
36
-
37
- def call(args)
38
- @proc.(@i, args)
39
- end
40
- end
41
-
42
- def scoped(proc, i)
43
- ->(args) { proc.(i, args) }
44
- end
45
-
46
- def object_vs_method_scope
47
- proc = ->(i, args) { i + args }
48
-
49
- callable = Callable.new(proc, 2)
50
- scoped = scoped(proc, 2)
51
-
52
- Benchmark.ips do |x|
53
- x.report("callable") { callable.(1) }
54
- x.report("scoped") { scoped.(1) }
55
- x.compare!
56
- end
57
- end
58
-
59
- object_vs_method_scope
60
-
61
- # Comparison:
62
- # callable: 4620906.3 i/s
63
- # scoped: 3388535.6 i/s - 1.36x slower
@@ -1,42 +0,0 @@
1
- require "test_helper"
2
-
3
- require "trailblazer/deprecation/context"
4
- require "trailblazer/deprecation/call"
5
-
6
- class DeprecationCallTest < Minitest::Spec
7
- class Create < Trailblazer::Operation
8
- step :create_model
9
-
10
- def create_model(options, params:, **)
11
- options["model"] = params.inspect
12
- options[:user] = options["current_user"]
13
- end
14
- end
15
-
16
- it "works with correct style" do
17
- result = Create.( params: { title: "Hello" } )
18
- result.inspect(:model, :user, :current_user, :params).must_equal %{<Result:false ["{:title=>\\\"Hello\\\"}", nil, nil, {:title=>\"Hello\"}] >}
19
- end
20
-
21
- it "works with correct style plus dependencies" do
22
- result = Create.( params: { title: "Hello" }, current_user: Object )
23
- result.inspect(:model, :user, :current_user, :params).must_equal %{<Result:true ["{:title=>\\\"Hello\\\"}", Object, Object, {:title=>\"Hello\"}] >}
24
- end
25
-
26
- it "converts old positional style" do
27
- result = Create.( { title: "Hello" }, "current_user" => user=Object )
28
- result.inspect(:model, :user, :current_user, :params).must_equal %{<Result:true ["{:title=>\\\"Hello\\\"}", Object, Object, {:title=>\"Hello\"}] >}
29
- end
30
-
31
- class WeirdStrongParameters < Hash
32
- end
33
-
34
- it "converts old positional style with StrongParameters" do
35
- params = WeirdStrongParameters.new
36
- params[:title] = "Hello"
37
-
38
- result = Create.( params, "current_user" => user=Object )
39
-
40
- result.inspect(:model, :user, :current_user, :params).must_equal %{<Result:true ["{:title=>\\\"Hello\\\"}", Object, Object, {:title=>\"Hello\"}] >}
41
- end
42
- end
@@ -1,19 +0,0 @@
1
- require "test_helper"
2
-
3
- require "trailblazer/deprecation/context"
4
-
5
- class DeprecationContextTest < Minitest::Spec
6
- class Create < Trailblazer::Operation
7
- step :create_model
8
-
9
- def create_model(options, params:, **)
10
- options["model"] = params.inspect
11
- options[:user] = options["current_user"]
12
- end
13
- end
14
-
15
- it do
16
- result = Create.( "params"=> {title: "Hello"}, "current_user" => user=Object)
17
- result.inspect(:model, :user, :current_user, :params).must_equal %{<Result:true ["{:title=>\\\"Hello\\\"}", Object, Object, {:title=>\"Hello\"}] >}
18
- end
19
- end
@@ -1,37 +0,0 @@
1
- require "test_helper"
2
- require "dry/container"
3
- require "trailblazer/operation/auto_inject"
4
-
5
- class DryAutoInjectTest < Minitest::Spec
6
- my_container = Dry::Container.new
7
- my_container.register(:user_repository, -> { Object })
8
-
9
- AutoInject = Trailblazer::Operation::AutoInject(my_container)
10
-
11
- class Create < Trailblazer::Operation
12
- include AutoInject[:user_repository]
13
-
14
- pass :use_it!
15
-
16
- def use_it!(ctx, user_repository:, **)
17
- ctx[:my_repo] = user_repository
18
- end
19
- end
20
-
21
- it "auto-injects user_repository" do
22
- res = Create.(params: {})
23
- res[:user_repository].must_equal Object
24
- res[:my_repo].must_equal Object
25
- end
26
-
27
- it "allows dependency injection via ::call" do
28
- Create.(params: {}, user_repository: String)[:user_repository].must_equal String
29
- end
30
-
31
- describe "inheritance" do
32
- class Update < Create
33
- end
34
-
35
- it { Update.()[:user_repository].must_equal Object }
36
- end
37
- end
@@ -1,284 +0,0 @@
1
- require "test_helper"
2
-
3
- class DocsFailFastOptionTest < Minitest::Spec
4
- Song = Struct.new(:id, :title) do
5
- def self.find_by(id); nil end
6
- end
7
-
8
- class MyContract < Reform::Form
9
- end
10
-
11
-
12
- #:ffopt
13
- class Update < Trailblazer::Operation
14
- step Model( Song, :find_by )
15
- failure :abort!, fail_fast: true
16
- step Contract::Build( constant: MyContract )
17
- step Contract::Validate( )
18
- failure :handle_invalid_contract! # won't be executed if #abort! is executed.
19
-
20
- def abort!(options, params:, **)
21
- options["result.model.song"] = "Something went wrong with ID #{params[:id]}!"
22
- end
23
- # ..
24
- end
25
- #:ffopt end
26
-
27
- it { Update.(params: {id: 1}).inspect("result.model.song", "contract.default").must_equal %{<Result:false [\"Something went wrong with ID 1!\", nil] >} }
28
- it do
29
- #:ffopt-res
30
- result = Update.(params: {id: 1})
31
- result["result.model.song"] #=> "Something went wrong with ID 1!"
32
- #:ffopt-res end
33
- end
34
- end
35
-
36
- class DocsFailFastOptionWithStepTest < Minitest::Spec
37
- Song = Class.new do
38
- def self.find_by(*); Object end
39
- end
40
-
41
- #:ffopt-step
42
- class Update < Trailblazer::Operation
43
- step :empty_id?, fail_fast: true
44
- step Model( Song, :find_by )
45
- failure :handle_empty_db! # won't be executed if #empty_id? returns falsey.
46
-
47
- def empty_id?(options, params:, **)
48
- params[:id] # returns false if :id missing.
49
- end
50
- end
51
- #:ffopt-step end
52
-
53
- it { Update.(params: { id: nil }).inspect(:model).must_equal %{<Result:false [nil] >} }
54
- it { Update.(params: { id: 1 }).inspect(:model).must_equal %{<Result:true [Object] >} }
55
- it do
56
- #:ffopt-step-res
57
- result = Update.(params: { id: nil })
58
-
59
- result.failure? #=> true
60
- result["model"] #=> nil
61
- #:ffopt-step-res end
62
- end
63
- end
64
-
65
- class DocsPassFastWithStepOptionTest < Minitest::Spec
66
- Song = Struct.new(:id, :title) do
67
- def self.find_by(id); nil end
68
- end
69
-
70
- class MyContract < Reform::Form
71
- end
72
-
73
- #:pfopt-step
74
- class Update < Trailblazer::Operation
75
- step Model( Song, :find_by )
76
- failure :abort!, fail_fast: true
77
- step Contract::Build( constant: MyContract )
78
- step Contract::Validate( )
79
- failure :handle_invalid_contract! # won't be executed if #abort! is executed.
80
-
81
- def abort!(options, params:, **)
82
- options["result.model.song"] = "Something went wrong with ID #{params[:id]}!"
83
- end
84
- # ..
85
- end
86
- #:pfopt-step end
87
-
88
- it { Update.(params: {id: 1}).inspect("result.model.song", "contract.default").must_equal %{<Result:false [\"Something went wrong with ID 1!\", nil] >} }
89
- it do
90
- #:pfopt-step-res
91
- result = Update.(params: {id: 1})
92
- result["result.model.song"] #=> "Something went wrong with ID 1!"
93
- #:pfopt-step-res end
94
- end
95
- end
96
-
97
- class DocsFailFastMethodTest < Minitest::Spec
98
- Song = Struct.new(:id, :title) do
99
- def self.find_by(id); nil end
100
- end
101
-
102
- #:ffmeth
103
- class Update < Trailblazer::Operation
104
- step :filter_params!, fast_track: true # emits fail_fast!
105
- step Model( Song, :find_by )
106
- failure :handle_fail!
107
-
108
- def filter_params!(options, params:, **)
109
- unless params[:id]
110
- options["result.params"] = "No ID in params!"
111
- return Railway.fail_fast!
112
- end
113
- end
114
-
115
- def handle_fail!(options, **)
116
- options["my.status"] = "Broken!"
117
- end
118
- end
119
- #:ffmeth end
120
-
121
- it { Update.(params: {}).inspect("result.params", "my.status").must_equal %{<Result:false [\"No ID in params!\", nil] >} }
122
- it do
123
- #:ffmeth-res
124
- result = Update.(params: {id: 1})
125
- result["result.params"] #=> "No ID in params!"
126
- result["my.status"] #=> nil
127
- #:ffmeth-res end
128
- end
129
- end
130
-
131
- class DocsPassFastMethodTest < Minitest::Spec
132
- Song = Struct.new(:id, :title) do
133
- def save; end
134
- end
135
-
136
- class MyContract < Reform::Form
137
- end
138
-
139
- #:pfmeth
140
- class Create < Trailblazer::Operation
141
- step Model( Song, :new )
142
- step :empty_model!, fast_track: true # emits pass_fast!
143
- step Contract::Build( constant: MyContract )
144
- # ..
145
-
146
- def empty_model!(options, is_empty:, model:, **)
147
- return unless is_empty
148
- model.save
149
- Railway.pass_fast!
150
- end
151
- end
152
- #:pfmeth end
153
-
154
- it { Create.(params: { title: "Tyrant"}, "is_empty" => true).inspect(:model).must_equal %{<Result:true [#<struct DocsPassFastMethodTest::Song id=nil, title=nil>] >} }
155
- it do
156
- #:pfmeth-res
157
- result = Create.(params: {}, "is_empty" => true)
158
- result["model"] #=> #<Song id=nil, title=nil>
159
- #:pfmeth-res end
160
- end
161
- end
162
-
163
-
164
- class FastTrackWithNestedTest < Minitest::Spec
165
- module Lib; end
166
- module Memo; end
167
-
168
- #:ft-nested
169
- class Lib::Authenticate < Trailblazer::Operation
170
- step :verify_input, fail_fast: true
171
- step :user_ok?
172
- #~ign
173
- def verify_input(options, w:true, **); options[:w] = true; w; end
174
- def user_ok?(options, u:true, **); options[:u] = true; u; end
175
- #~ign end
176
- end
177
- #:ft-nested end
178
-
179
- #:ft-create
180
- class Memo::Create < Trailblazer::Operation
181
- step :validate
182
- step Nested( Lib::Authenticate ) # fail_fast goes to End.fail_fast
183
- step :create_model
184
- step :save
185
- #~igncr
186
- def validate(options, v:true, **); options[:v] = true; v; end
187
- def create_model(options, c:true, **); options[:c] = true; c; end
188
- def save(options, s:true, **); options[:s] = true; s; end
189
- #~igncr end
190
- end
191
- #:ft-create end
192
-
193
- it "everything goes :success ===> End.success" do
194
- result = Memo::Create.()
195
-
196
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:true [true, true, true, true, true] >}
197
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Success
198
- end
199
-
200
- it "validate => failure ===> End.failure" do
201
- result = Memo::Create.(v: false)
202
-
203
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:false [true, nil, nil, nil, nil] >}
204
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
205
- end
206
-
207
- it "verify_input? => fail_fast ===> End.fail_fast" do
208
- result = Memo::Create.(w: false)
209
-
210
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:false [true, true, nil, nil, nil] >}
211
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::FailFast
212
- end
213
-
214
- it "user_ok? => fail ===> End.failure" do
215
- result = Memo::Create.(u: false)
216
-
217
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:false [true, true, true, nil, nil] >}
218
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
219
- end
220
-
221
- it "create_model? => fail ===> End.failure" do
222
- result = Memo::Create.(c: false)
223
-
224
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:false [true, true, true, true, nil] >}
225
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
226
- end
227
-
228
- module Rewire
229
- module Memo; end
230
-
231
- #:ft-rewire
232
- class Memo::Create < Trailblazer::Operation
233
- step :validate
234
- step Nested( Lib::Authenticate ), Output(:fail_fast) => Track(:failure)
235
- step :create_model
236
- step :save
237
- #~ignrw
238
- def validate(options, v:true, **); options[:v] = true; v; end
239
- def create_model(options, c:true, **); options[:c] = true; c; end
240
- def save(options, s:true, **); options[:s] = true; s; end
241
- #~ignrw end
242
- end
243
- #:ft-rewire end
244
- end
245
-
246
- it "everything goes :success ===> End.success" do
247
- result = Rewire::Memo::Create.()
248
-
249
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:true [true, true, true, true, true] >}
250
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Success
251
- end
252
-
253
- it "validate => failure ===> End.failure" do
254
- result = Rewire::Memo::Create.(v: false)
255
-
256
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:false [true, nil, nil, nil, nil] >}
257
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
258
- end
259
-
260
- # this is the only test differing.
261
- it "verify_input? => fail_fast ===> End.failure" do
262
- result = Rewire::Memo::Create.(w: false)
263
-
264
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:false [true, true, nil, nil, nil] >}
265
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
266
- end
267
-
268
- it "user_ok? => fail ===> End.failure" do
269
- result = Rewire::Memo::Create.(u: false)
270
-
271
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:false [true, true, true, nil, nil] >}
272
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
273
- end
274
-
275
- it "create_model? => fail ===> End.failure" do
276
- result = Rewire::Memo::Create.(c: false)
277
-
278
- result.inspect(:v,:w,:u,:c,:s).must_equal %{<Result:false [true, true, true, true, nil] >}
279
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
280
- end
281
- end
282
-
283
- # fail!
284
- # pass!