Class: SoberSwag::Serializer::Conditional
- Defined in:
- lib/sober_swag/serializer/conditional.rb
Overview
Conditionally serialize one thing or the other thing via deciding on a condition.
This works by taking three elements: a "decision" proc, a "left" serializer, and a "right" serializer.
The decision proc takes in both the object to be serialized and the options hash, and returns a
[:left, val]
object, or a [:right, val]
object, which
then get passed on to the appropriate serializer.
This is a very weird, not-very-Ruby-like abstraction, upon which we can build abstractions that are actually use for users. It lets you build abstractions like "Use this serializer if a type has this class, otherwise use this other one." When composed together, you can make arbitrary decision trees.
This class is heavily inspired by the Decideable typeclass from Haskell.
Defined Under Namespace
Classes: BadChoiceError
Instance Attribute Summary collapse
-
#chooser ⇒ Proc, Lambda
readonly
The "chooser" proc.
-
#left ⇒ SoberSwag::Serializer::Base
readonly
The serializer to use if the "chooser" proc chooses
:right
. -
#right ⇒ SoberSwag::Serializer::Base
readonly
The serializer to use if the "chooser" proc chooses
:right
.
Instance Method Summary collapse
- #finalize_lazy_type! ⇒ Object
-
#initialize(chooser, left, right) ⇒ Conditional
constructor
Create a new conditional serializer, from a "chooser" proc, a "left" serializer, and a "right" serializer.
- #lazy_type ⇒ Object
- #lazy_type? ⇒ Boolean
-
#serialize(object, options = {}) ⇒ Hash
First, call #chooser with
object
andoptions
to see what serializer to use, and what to serialize. -
#type ⇒ Object
Since this could potentially serialize one of two alternatives, the "type" we serialize two is either one alternative or the other.
Methods inherited from Base
#array, #identifier, #meta, #optional, #serializer, #via_map
Constructor Details
#initialize(chooser, left, right) ⇒ Conditional
Create a new conditional serializer, from a "chooser" proc, a "left" serializer, and a "right" serializer.
28 29 30 31 32 |
# File 'lib/sober_swag/serializer/conditional.rb', line 28 def initialize(chooser, left, right) @chooser = chooser @left = left @right = right end |
Instance Attribute Details
#chooser ⇒ Proc, Lambda (readonly)
Returns the "chooser" proc.
36 37 38 |
# File 'lib/sober_swag/serializer/conditional.rb', line 36 def chooser @chooser end |
#left ⇒ SoberSwag::Serializer::Base (readonly)
Returns the serializer to use if the "chooser" proc chooses :right
.
Also called the "left-side serializer.".
41 42 43 |
# File 'lib/sober_swag/serializer/conditional.rb', line 41 def left @left end |
#right ⇒ SoberSwag::Serializer::Base (readonly)
Returns the serializer to use if the "chooser" proc chooses :right
.
Also called the "right-side serializer.".
46 47 48 |
# File 'lib/sober_swag/serializer/conditional.rb', line 46 def right @right end |
Instance Method Details
#finalize_lazy_type! ⇒ Object
93 94 95 |
# File 'lib/sober_swag/serializer/conditional.rb', line 93 def finalize_lazy_type! [left, right].each(&:finalize_lazy_type!) end |
#lazy_type ⇒ Object
79 80 81 82 83 84 85 |
# File 'lib/sober_swag/serializer/conditional.rb', line 79 def lazy_type if left.lazy_type == right.lazy_type left.lazy_type else left.lazy_type | right.lazy_type end end |
#lazy_type? ⇒ Boolean
87 88 89 |
# File 'lib/sober_swag/serializer/conditional.rb', line 87 def lazy_type? left.lazy_type? || right.lazy_type? end |
#serialize(object, options = {}) ⇒ Hash
First, call #chooser with object
and options
to see what serializer to use, and what to serialize.
Then, if it returns [:left, val]
, use #left to serialize val
.
Otherwise, if it returns [:right, val]
, use #right to serialize val
.
If it returns neither, throw BadChoiceError.
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/sober_swag/serializer/conditional.rb', line 56 def serialize(object, = {}) tag, val = chooser.call(object, ) case tag when :left left.serialize(val, ) when :right right.serialize(val, ) else raise BadChoiceError, "result of chooser proc was not a left or right, but a #{val.class}" end end |
#type ⇒ Object
Since this could potentially serialize one of two alternatives, the "type" we serialize two is either one alternative or the other.
71 72 73 74 75 76 77 |
# File 'lib/sober_swag/serializer/conditional.rb', line 71 def type if left.type == right.type left.type else left.type | right.type end end |