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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46629f7e8b78b79da65d73f694f03ffd3598a836
4
- data.tar.gz: e7cd5893f3661781d40ed6050a10067e31d4df3e
3
+ metadata.gz: ec1c25ca6b1d98aead3c8da72aaa11ae58c1b9fe
4
+ data.tar.gz: c27b50ad7c730bcf5b370b3016b8dc8fabca1cc9
5
5
  SHA512:
6
- metadata.gz: a81e6790403bb1611887adc70072541414c8df853cbfae06474eeb6bcb4d481ba17fb29c8b79be8352e155dd554b455f164ad472cfdabdd84b7431ccac35f9a2
7
- data.tar.gz: 561ca45352089282b7a036013799664efc7787fd80f1b38adb7df8d522ee1ae8a72b6ed7c22d49ffa3a6a24490f3575adb422bd15c72a85478c92b17ed249586
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 => :string },
166
- :expected_attribute2 => { :type => :integer, :presence => true }
167
- validates_after :example_attribute1 => { :type => :string, :presence => ->(example_attribute1) { !example_attribute1.empty? } }
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`. 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` instance via a `context` object. This shared `context` object allows for getting and setting attributes as needed. When the `call` method returns, the `context` is validated against any defined after validations, and the `context` is then returned to the caller.
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` is designed to organize multiple `ActionTasks`, and `ActionCoordinator` is designed to organize many `ActionUseCases`.
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. 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 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.
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. 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`:
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 => :string },
201
- :expected_attribute2 => { :type => :integer, :presence => true }
202
- validates_after :example_task1 => { :type => :boolean, :presence => true },
203
- :example_task2 => { :type => :boolean, :presence => true },
204
- :example_task3 => { :type => :boolean, :presence => true },
205
- :example_usecase1 => { :type => :boolean, :presence => true }
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 => :boolean, :presence => true }
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 => :boolean, :presence => true }
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 => :boolean, :presence => true }
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` 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` are evaluated, and indicates that the `call` method of the `ActionUseCaseExample` is invoked prior to any of the `ActionTasks` defined in the `tasks` method.
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` and the order in which operations are performed:
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. The `ActionCoordinator` abstraction is intended to help coordinate multiple `ActionUseCases` by allowing you to define a plan of which `ActionUseCases` to invoke depending on the outcome of each `ActionUseCase` execution. The `ActionCoordinator` abstraction is the highest level of abstraction in `ActionLogic`.
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 transition map that links together the various `ActionUseCase` classes the `ActionCoordinator` is organizing, as well as allowing you to define error or halt scenarios based on the result of each `ActionUseCase`. The following code example demonstrates a simple `ActionCoordinator`:
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 => :string }
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 => :string }
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 => :boolean, :presence => true }
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 => :boolean, :presence => true }
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`, `ActionUseCase` or `ActionCoordinator`
364
- because it informs the caller that the various execution context(s) were successful. In other words, a `:success` status indicates that none of the execution contexts had a failure
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 => :integer },
593
- :float_test => { :type => :float },
594
- :string_test => { :type => :string },
595
- :bool_test => { :type => :boolean },
596
- :hash_test => { :type => :hash },
597
- :array_test => { :type => :array },
598
- :symbol_test => { :type => :symbol },
599
- :nil_test => { :type => :nil }
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.bool_test = true
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
- # bool_test=true,
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
- To simplify the way these validations work for `true` or `false`, type validations expect the symbol `:boolean` as the `:type`. `nil` is validated simply with the `:nil` `:type`.
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 => :integer }
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 integer but is float"] (ActionLogic::AttributeTypeError)
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 => :exampleclass }
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 lowercase version of the class as a symbol. `ExampleClass` becomes `:exampleclass`, `UserAttributes` becomes `:userattributes`,
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 => :exampleclass }
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 exampleclass but is otherclass"] (ActionLogic::AttributeTypeError)
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 => :array, :presence => ->(attribute) { attribute.any? } }
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 => :array, :presence => ->(attribute) { attribute.any? } },
817
- :example_attribute2 => { :type => :integer }
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 => :array, :presence => ->(attribute) { attribute.any? } }
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 => :array, :presence => ->(attribute) { attribute.any? } },
859
- :example_attribute2 => { :type => :integer }
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 => :array, :presence => ->(attribute) { attribute.any? } }
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 => :array, :presence => ->(attribute) { attribute.any? } },
902
- :example_attribute2 => { :type => :integer }
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
@@ -1,3 +1,3 @@
1
1
  module ActionLogic
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.1'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_logic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Winfrey