action_logic 0.2.0 → 0.2.1
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/README.md +70 -54
- data/lib/action_logic/action_validation.rb +7 -3
- data/lib/action_logic/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec1c25ca6b1d98aead3c8da72aaa11ae58c1b9fe
|
4
|
+
data.tar.gz: c27b50ad7c730bcf5b370b3016b8dc8fabca1cc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8340bda2fb890fdea4c2cf4177763c347dfdcbc247ab4a49b1def06851cd99cfc633c3c9c671272a16ce7dd960fee432d9e4abc5af341a499d33a83202c5b61f
|
7
|
+
data.tar.gz: c9f53e0e7f74cb63618e1b064a940027166ba8f9165c9dbdf0ac4cd289a25e19ce90d0fbfaa34433a13d82a65c654c6cc8144ddd8d27b78158a4c58253b900b9
|
data/README.md
CHANGED
@@ -162,9 +162,9 @@ To implement an `ActionTask` class you must define a `call` method. You can also
|
|
162
162
|
class ActionTaskExample
|
163
163
|
include ActionLogic::ActionTask
|
164
164
|
|
165
|
-
validates_before :expected_attribute1 => { :type =>
|
166
|
-
:expected_attribute2 => { :type =>
|
167
|
-
validates_after :example_attribute1 => { :type =>
|
165
|
+
validates_before :expected_attribute1 => { :type => String },
|
166
|
+
:expected_attribute2 => { :type => Fixnum, :presence => true }
|
167
|
+
validates_after :example_attribute1 => { :type => String, :presence => ->(example_attribute1) { !example_attribute1.empty? } }
|
168
168
|
|
169
169
|
def call
|
170
170
|
# adds `example_attribute1` to the shared `context` with the value "Example value"
|
@@ -179,30 +179,37 @@ result = ActionTaskExample.execute(:expected_attribute1 => "example", :expected_
|
|
179
179
|
result # => #<ActionLogic::ActionContext expected_attribute1="example", expected_attribute2=123, status=:success, example_attribute1="New value from context attributes: example 123">
|
180
180
|
```
|
181
181
|
|
182
|
-
The `ActionTaskExample` is invoked using the static method `execute` which takes an optional hash of attributes that is converted into an `ActionContext`.
|
182
|
+
The `ActionTaskExample` is invoked using the static method `execute` which takes an optional hash of attributes that is converted into an `ActionContext`.
|
183
|
+
Assuming the before validations are satisfied, the `call` method is invoked. In the body of the `call` method the `ActionTask` can access the shared `ActionContext`
|
184
|
+
instance via a `context` object. This shared `context` object allows for getting and setting attributes as needed. When the `call` method returns, the `context`
|
185
|
+
is validated against any defined after validations, and the `context` is then returned to the caller.
|
183
186
|
|
184
187
|
The diagram below is a visual representation of how an `ActionTask` is evaluted when its `execute` method is invoked from a caller:
|
185
188
|
|
186
189
|
<img src="https://raw.githubusercontent.com/rewinfrey/action_logic/master/resources/action_task_diagram.png" />
|
187
190
|
|
188
|
-
Although this example is for the `ActionTask` abstraction, `ActionUseCase` and `ActionCoordinator` follow the same pattern. The difference is that `ActionUseCase`
|
191
|
+
Although this example is for the `ActionTask` abstraction, `ActionUseCase` and `ActionCoordinator` follow the same pattern. The difference is that `ActionUseCase`
|
192
|
+
is designed to organize multiple `ActionTasks`, and `ActionCoordinator` is designed to organize many `ActionUseCases`.
|
189
193
|
|
190
194
|
### ActionUseCase
|
191
195
|
|
192
|
-
As business logic grows in complexity the number of steps or tasks required to fulfill that business logic tends to increase. Managing this complexity is a problem every team must face.
|
196
|
+
As business logic grows in complexity the number of steps or tasks required to fulfill that business logic tends to increase. Managing this complexity is a problem every team must face.
|
197
|
+
Abstractions can help teams of varying experience levels work together and promote code that remains modular and simple to understand and extend. `ActionUseCase` represents a layer of
|
198
|
+
abstraction that organizes multiple `ActionTasks` and executes each `ActionTask` in the order they are defined. Each task receives the same shared `context` so tasks can be composed together.
|
193
199
|
|
194
|
-
To implement an `ActionUseCase` class you must define a `call` method and a `tasks` method. You also can specify any before, after or around validations or an error handler.
|
200
|
+
To implement an `ActionUseCase` class you must define a `call` method and a `tasks` method. You also can specify any before, after or around validations or an error handler.
|
201
|
+
The following is an example showcasing how an `ActionUseCase` class organizes the execution of multiple `ActionTasks` and defines before and after validations on the shared `context`:
|
195
202
|
|
196
203
|
```ruby
|
197
204
|
class ActionUseCaseExample
|
198
205
|
include ActionLogic::ActionUseCase
|
199
206
|
|
200
|
-
validates_before :expected_attribute1 => { :type =>
|
201
|
-
:expected_attribute2 => { :type =>
|
202
|
-
validates_after :example_task1 => { :type =>
|
203
|
-
:example_task2 => { :type =>
|
204
|
-
:example_task3 => { :type =>
|
205
|
-
:example_usecase1 => { :type =>
|
207
|
+
validates_before :expected_attribute1 => { :type => String },
|
208
|
+
:expected_attribute2 => { :type => Fixnum, :presence => true }
|
209
|
+
validates_after :example_task1 => { :type => TrueClass, :presence => true },
|
210
|
+
:example_task2 => { :type => TrueClass, :presence => true },
|
211
|
+
:example_task3 => { :type => TrueClass, :presence => true },
|
212
|
+
:example_usecase1 => { :type => TrueClass, :presence => true }
|
206
213
|
|
207
214
|
# The `call` method is invoked prior to invoking any of the ActionTasks defined by the `tasks` method.
|
208
215
|
# The purpose of the `call` method allows us to prepare the shared `context` prior to invoking the ActionTasks.
|
@@ -220,7 +227,7 @@ end
|
|
220
227
|
|
221
228
|
class ActionTaskExample1
|
222
229
|
include ActionLogic::ActionTask
|
223
|
-
validates_after :example_task1 => { :type =>
|
230
|
+
validates_after :example_task1 => { :type => TrueClass, :presence => true }
|
224
231
|
|
225
232
|
def call
|
226
233
|
context # => #<ActionLogic::ActionContext expected_attribute1="example", expected_attribute2=123, status=:success, example_usecase1=true>
|
@@ -230,7 +237,7 @@ end
|
|
230
237
|
|
231
238
|
class ActionTaskExample2
|
232
239
|
include ActionLogic::ActionTask
|
233
|
-
validates_after :example_task2 => { :type =>
|
240
|
+
validates_after :example_task2 => { :type => TrueClass, :presence => true }
|
234
241
|
|
235
242
|
def call
|
236
243
|
context # => #<ActionLogic::ActionContext expected_attribute1="example", expected_attribute2=123, status=:success, example_usecase1=true, example_task1=true>
|
@@ -240,7 +247,7 @@ end
|
|
240
247
|
|
241
248
|
class ActionTaskExample3
|
242
249
|
include ActionLogic::ActionTask
|
243
|
-
validates_after :example_task3 => { :type =>
|
250
|
+
validates_after :example_task3 => { :type => TrueClass, :presence => true }
|
244
251
|
|
245
252
|
def call
|
246
253
|
context # => #<ActionLogic::ActionContext expected_attribute1="example", expected_attribute2=123, status=:success, example_usecase1=true, example_task1=true, example_task2=true>
|
@@ -254,17 +261,24 @@ result = ActionUseCaseExample.execute(:expected_attribute1 => "example", :expect
|
|
254
261
|
result # => #<ActionLogic::ActionContext expected_attribute1="example", expected_attribute2=123, status=:success, example_usecase1=true, example_task1=true, example_task2=true, example_task3=true>
|
255
262
|
```
|
256
263
|
|
257
|
-
By following the value of the shared `context` from the `ActionUseCaseExample` to each of the `ActionTask` classes, it is possible to see how the shared `context`
|
264
|
+
By following the value of the shared `context` from the `ActionUseCaseExample` to each of the `ActionTask` classes, it is possible to see how the shared `context`
|
265
|
+
is mutated to accomodate the various attributes and their values each execution context adds to the `context`. It also reveals the order in which the `ActionTasks`
|
266
|
+
are evaluated, and indicates that the `call` method of the `ActionUseCaseExample` is invoked prior to any of the `ActionTasks` defined in the `tasks` method.
|
258
267
|
|
259
|
-
To help visualize the flow of execution when an `ActionUseCase` is invoked, this diagram aims to illustrate the relationship between `ActionUseCase` and `ActionTasks`
|
268
|
+
To help visualize the flow of execution when an `ActionUseCase` is invoked, this diagram aims to illustrate the relationship between `ActionUseCase` and `ActionTasks`
|
269
|
+
and the order in which operations are performed:
|
260
270
|
|
261
271
|
<img src="https://raw.githubusercontent.com/rewinfrey/action_logic/master/resources/action_use_case_diagram.png" />
|
262
272
|
|
263
273
|
### ActionCoordinator
|
264
274
|
|
265
|
-
Sometimes the behavior we wish our Ruby or Rails application to provide requires us to coordinate work between various domains of our application's business logic.
|
275
|
+
Sometimes the behavior we wish our Ruby or Rails application to provide requires us to coordinate work between various domains of our application's business logic.
|
276
|
+
The `ActionCoordinator` abstraction is intended to help coordinate multiple `ActionUseCases` by allowing you to define a plan of which `ActionUseCases` to invoke
|
277
|
+
depending on the outcome of each `ActionUseCase` execution. The `ActionCoordinator` abstraction is the highest level of abstraction in `ActionLogic`.
|
266
278
|
|
267
|
-
To implement an `ActionCoordinator` class, you must define a `call` method in addition to a `plan` method. The purpose of the `plan` method is to define a state
|
279
|
+
To implement an `ActionCoordinator` class, you must define a `call` method in addition to a `plan` method. The purpose of the `plan` method is to define a state
|
280
|
+
transition map that links together the various `ActionUseCase` classes the `ActionCoordinator` is organizing, as well as allowing you to define error or halt
|
281
|
+
scenarios based on the result of each `ActionUseCase`. The following code example demonstrates a simple `ActionCoordinator`:
|
268
282
|
|
269
283
|
```ruby
|
270
284
|
class ActionCoordinatorExample
|
@@ -289,7 +303,7 @@ end
|
|
289
303
|
class ActionUseCaseExample1
|
290
304
|
include ActionLogic::ActionUseCase
|
291
305
|
|
292
|
-
validates_before :required_attribute1 => { :type =>
|
306
|
+
validates_before :required_attribute1 => { :type => String }
|
293
307
|
|
294
308
|
def call
|
295
309
|
context # => #<ActionLogic::ActionContext status=:success, required_attribute1="required attribute 1", required_attribute2="required attribute 2">
|
@@ -305,7 +319,7 @@ end
|
|
305
319
|
class ActionUseCaseExample2
|
306
320
|
include ActionLogic::ActionUseCase
|
307
321
|
|
308
|
-
validates_before :required_attribute2 => { :type =>
|
322
|
+
validates_before :required_attribute2 => { :type => String }
|
309
323
|
|
310
324
|
def call
|
311
325
|
context # => #<ActionLogic::ActionContext status=:success, required_attribute1="required attribute 1", required_attribute2="required attribute 2", example_usecase1=true, example_task1=true>
|
@@ -334,7 +348,7 @@ end
|
|
334
348
|
|
335
349
|
class ActionTaskExample1
|
336
350
|
include ActionLogic::ActionTask
|
337
|
-
validates_after :example_task1 => { :type =>
|
351
|
+
validates_after :example_task1 => { :type => TrueClass, :presence => true }
|
338
352
|
|
339
353
|
def call
|
340
354
|
context # => #<ActionLogic::ActionContext status=:success, required_attribute1="required attribute 1", required_attribute2="required attribute 2", example_usecase1=true>
|
@@ -344,7 +358,7 @@ end
|
|
344
358
|
|
345
359
|
class ActionTaskExample2
|
346
360
|
include ActionLogic::ActionTask
|
347
|
-
validates_after :example_task2 => { :type =>
|
361
|
+
validates_after :example_task2 => { :type => TrueClass, :presence => true }
|
348
362
|
|
349
363
|
def call
|
350
364
|
context # => #<ActionLogic::ActionContext status=:success, required_attribute1="required attribute 1", required_attribute2="required attribute 2", example_usecase1=true, example_task1=true, example_usecase2=true>
|
@@ -360,9 +374,9 @@ result # => #<ActionLogic::ActionContext status=:success, required_attribute1="r
|
|
360
374
|
<img src="https://raw.githubusercontent.com/rewinfrey/action_logic/master/resources/action_coordinator_diagram.png" />
|
361
375
|
|
362
376
|
### Succeeding an `ActionContext`
|
363
|
-
By default, the value of the `status` attribute of instances of `ActionContext` is `:success`. Normally this is useful information for the caller of an `ActionTask`,
|
364
|
-
because it informs the caller that the various execution context(s) were successful. In other words, a `:success` status
|
365
|
-
or halted execution.
|
377
|
+
By default, the value of the `status` attribute of instances of `ActionContext` is `:success`. Normally this is useful information for the caller of an `ActionTask`,
|
378
|
+
`ActionUseCase` or `ActionCoordinator` because it informs the caller that the various execution context(s) were successful. In other words, a `:success` status
|
379
|
+
indicates that none of the execution contexts had a failure or halted execution.
|
366
380
|
|
367
381
|
### Failing an `ActionContext`
|
368
382
|
Using `context.fail!` does two important things: it immediately stops the execution of any proceeding business logic (prevents any additional `ActionTasks` from executing)
|
@@ -589,20 +603,22 @@ of `ActionContext`. To understand the default types `ActionLogic` validates agai
|
|
589
603
|
class ActionTaskExample
|
590
604
|
include ActionLogic::ActionTask
|
591
605
|
|
592
|
-
validates_after :integer_test => { :type =>
|
593
|
-
:float_test => { :type =>
|
594
|
-
:string_test => { :type =>
|
595
|
-
:
|
596
|
-
:
|
597
|
-
:
|
598
|
-
:
|
599
|
-
:
|
606
|
+
validates_after :integer_test => { :type => Fixnum },
|
607
|
+
:float_test => { :type => Float },
|
608
|
+
:string_test => { :type => String },
|
609
|
+
:truthy_test => { :type => TrueClass },
|
610
|
+
:falsey_test => { :type => FalseClass },
|
611
|
+
:hash_test => { :type => Hash },
|
612
|
+
:array_test => { :type => Array },
|
613
|
+
:symbol_test => { :type => Symbol },
|
614
|
+
:nil_test => { :type => NilClass }
|
600
615
|
|
601
616
|
def call
|
602
617
|
context.integer_test = 123
|
603
618
|
context.float_test = 1.0
|
604
619
|
context.string_test = "test"
|
605
|
-
context.
|
620
|
+
context.truthy_test = true
|
621
|
+
context.falsey_test = false
|
606
622
|
context.hash_test = {}
|
607
623
|
context.array_test = []
|
608
624
|
context.symbol_test = :symbol
|
@@ -616,7 +632,8 @@ result # => #<ActionLogic::ActionContext status=:success,
|
|
616
632
|
# integer_test=123,
|
617
633
|
# float_test=1.0,
|
618
634
|
# string_test="test",
|
619
|
-
#
|
635
|
+
# truthy_test=true,
|
636
|
+
# falsey_test=false,
|
620
637
|
# hash_test={},
|
621
638
|
# array_test=[],
|
622
639
|
# symbol_test=:symbol,
|
@@ -624,7 +641,7 @@ result # => #<ActionLogic::ActionContext status=:success,
|
|
624
641
|
```
|
625
642
|
|
626
643
|
It's important to point out that Ruby's `true` and `false` are not `Boolean` but `TrueClass` and `FalseClass` respectively. Additionally, `nil`'s type is `NilClass` in Ruby.
|
627
|
-
|
644
|
+
Also potentially surprising to some is that Ruby's integer type is of class `Fixnum`, but floats are of class `Float`.
|
628
645
|
|
629
646
|
As we saw with attribute validations, if an attribute's value does not conform to the type expected, `ActionLogic` will raise an `ActionLogic::AttributeTypeError`
|
630
647
|
with a detailed description about which attribute's value failed the validation:
|
@@ -633,14 +650,14 @@ with a detailed description about which attribute's value failed the validation:
|
|
633
650
|
class ActionTaskExample
|
634
651
|
include ActionLogic::ActionTask
|
635
652
|
|
636
|
-
validates_after :integer_test => { :type =>
|
653
|
+
validates_after :integer_test => { :type => Fixnum }
|
637
654
|
|
638
655
|
def call
|
639
656
|
context.integer_test = 1.0
|
640
657
|
end
|
641
658
|
end
|
642
659
|
|
643
|
-
ActionTaskExample.execute # ~> ["Attribute: integer_test with value: 1.0 was expected to be of type
|
660
|
+
ActionTaskExample.execute # ~> ["Attribute: integer_test with value: 1.0 was expected to be of type Fixnum but is Float"] (ActionLogic::AttributeTypeError)
|
644
661
|
```
|
645
662
|
|
646
663
|
In addition to the above default types it is possible to also validate against user defined types.
|
@@ -657,7 +674,7 @@ end
|
|
657
674
|
class ActionTaskExample
|
658
675
|
include ActionLogic::ActionTask
|
659
676
|
|
660
|
-
validates_after :example_attribute => { :type =>
|
677
|
+
validates_after :example_attribute => { :type => ExampleClass }
|
661
678
|
|
662
679
|
def call
|
663
680
|
context.example_attribute = ExampleClass.new
|
@@ -670,8 +687,7 @@ result # => #<ActionLogic::ActionContext status=:success, example_attribute=#<Ex
|
|
670
687
|
```
|
671
688
|
|
672
689
|
In the above example, a custom class `ExampleClass` is defined. In order to type validate against this class, the required format for the name of the class is simply
|
673
|
-
the
|
674
|
-
`ReallyLongClassNameThatBreaks80ColumnsInVimRule` becomes `:reallylongclassnamethatbreaks80columnsinvimrule` and so on.
|
690
|
+
the class constant `ExampleClass`.
|
675
691
|
|
676
692
|
If a custom type validation fails, `ActionLogic` provides the same `ActionLogic::AttributeTypeError` with a detailed explanation about what attribute is in violation
|
677
693
|
of the type validation:
|
@@ -686,14 +702,14 @@ end
|
|
686
702
|
class ActionTaskExample
|
687
703
|
include ActionLogic::ActionTask
|
688
704
|
|
689
|
-
validates_after :example_attribute => { :type =>
|
705
|
+
validates_after :example_attribute => { :type => ExampleClass }
|
690
706
|
|
691
707
|
def call
|
692
708
|
context.example_attribute = OtherClass.new
|
693
709
|
end
|
694
710
|
end
|
695
711
|
|
696
|
-
ActionTaskExample.execute # ~> ["Attribute: example_attribute with value: #<OtherClass:0x007fb5ca04edb8> was expected to be of type
|
712
|
+
ActionTaskExample.execute # ~> ["Attribute: example_attribute with value: #<OtherClass:0x007fb5ca04edb8> was expected to be of type ExampleClass but is OtherClass"] (ActionLogic::AttributeTypeError)
|
697
713
|
```
|
698
714
|
|
699
715
|
Attribute and type validations are very helpful, but in some situations this is not enough. Additionally, `ActionLogic` provides presence validation so you can also verify that
|
@@ -796,7 +812,7 @@ validation on a single attribute:
|
|
796
812
|
class ActionTaskExample
|
797
813
|
include ActionLogic::ActionTask
|
798
814
|
|
799
|
-
validates_before :example_attribute => { :type =>
|
815
|
+
validates_before :example_attribute => { :type => Array, :presence => ->(attribute) { attribute.any? } }
|
800
816
|
|
801
817
|
def call
|
802
818
|
end
|
@@ -813,8 +829,8 @@ The following example illustrates how to specify a before validation for multipl
|
|
813
829
|
class ActionTaskExample
|
814
830
|
include ActionLogic::ActionTask
|
815
831
|
|
816
|
-
validates_before :example_attribute => { :type =>
|
817
|
-
:example_attribute2 => { :type =>
|
832
|
+
validates_before :example_attribute => { :type => Array, :presence => ->(attribute) { attribute.any? } },
|
833
|
+
:example_attribute2 => { :type => Fixnum }
|
818
834
|
|
819
835
|
def call
|
820
836
|
end
|
@@ -838,7 +854,7 @@ validation on a single attribute:
|
|
838
854
|
class ActionTaskExample
|
839
855
|
include ActionLogic::ActionTask
|
840
856
|
|
841
|
-
validates_after :example_attribute => { :type =>
|
857
|
+
validates_after :example_attribute => { :type => Array, :presence => ->(attribute) { attribute.any? } }
|
842
858
|
|
843
859
|
def call
|
844
860
|
context.example_attribute = [1, 2, 3]
|
@@ -855,8 +871,8 @@ The following example illustrates how to specify an after validation for multipl
|
|
855
871
|
class ActionTaskExample
|
856
872
|
include ActionLogic::ActionTask
|
857
873
|
|
858
|
-
validates_after :example_attribute => { :type =>
|
859
|
-
:example_attribute2 => { :type =>
|
874
|
+
validates_after :example_attribute => { :type => Array, :presence => ->(attribute) { attribute.any? } },
|
875
|
+
:example_attribute2 => { :type => Fixnum }
|
860
876
|
|
861
877
|
def call
|
862
878
|
context.example_attribute = [1, 2, 3]
|
@@ -882,7 +898,7 @@ validation on a single attribute:
|
|
882
898
|
class ActionTaskExample
|
883
899
|
include ActionLogic::ActionTask
|
884
900
|
|
885
|
-
validates_around :example_attribute => { :type =>
|
901
|
+
validates_around :example_attribute => { :type => Array, :presence => ->(attribute) { attribute.any? } }
|
886
902
|
|
887
903
|
def call
|
888
904
|
end
|
@@ -898,8 +914,8 @@ The following example illustrates how to specify an around validation for multip
|
|
898
914
|
class ActionTaskExample
|
899
915
|
include ActionLogic::ActionTask
|
900
916
|
|
901
|
-
validates_around :example_attribute => { :type =>
|
902
|
-
:example_attribute2 => { :type =>
|
917
|
+
validates_around :example_attribute => { :type => Array, :presence => ->(attribute) { attribute.any? } },
|
918
|
+
:example_attribute2 => { :type => Fixnum }
|
903
919
|
|
904
920
|
def call
|
905
921
|
end
|
@@ -59,7 +59,7 @@ module ActionLogic
|
|
59
59
|
expected_attributes = validations.keys || []
|
60
60
|
missing_attributes = expected_attributes - existing_attributes
|
61
61
|
|
62
|
-
raise ActionLogic::MissingAttributeError.new(missing_attributes) if missing_attributes.any?
|
62
|
+
raise ActionLogic::MissingAttributeError.new(error_message_format(missing_attributes.join(", ") + " attributes are missing")) if missing_attributes.any?
|
63
63
|
end
|
64
64
|
|
65
65
|
def validate_types!(validations)
|
@@ -74,7 +74,7 @@ module ActionLogic
|
|
74
74
|
collection
|
75
75
|
end
|
76
76
|
|
77
|
-
raise ActionLogic::AttributeTypeError.new(type_errors) if type_errors.any?
|
77
|
+
raise ActionLogic::AttributeTypeError.new(error_message_format(type_errors.join(", "))) if type_errors.any?
|
78
78
|
end
|
79
79
|
|
80
80
|
def validate_presence!(validations)
|
@@ -88,7 +88,7 @@ module ActionLogic
|
|
88
88
|
elsif expected_validation[:presence].class == Proc
|
89
89
|
collection << "Attribute: #{expected_attribute} is missing value in context but custom presence validation was specified" unless expected_validation[:presence].call(context[expected_attribute])
|
90
90
|
else
|
91
|
-
raise ActionLogic::UnrecognizablePresenceValidatorError.new("Presence validator: #{expected_validation[:presence]} is not a supported format")
|
91
|
+
raise ActionLogic::UnrecognizablePresenceValidatorError.new(error_message_format("Presence validator: #{expected_validation[:presence]} is not a supported format"))
|
92
92
|
end
|
93
93
|
|
94
94
|
collection
|
@@ -96,5 +96,9 @@ module ActionLogic
|
|
96
96
|
|
97
97
|
raise ActionLogic::PresenceError.new(presence_errors) if presence_errors.any?
|
98
98
|
end
|
99
|
+
|
100
|
+
def error_message_format(error_string)
|
101
|
+
"context: #{self.class} message: #{error_string}"
|
102
|
+
end
|
99
103
|
end
|
100
104
|
end
|
data/lib/action_logic/version.rb
CHANGED