Module: Lutaml::Model::Serialize::EnumHandling
- Included in:
- ClassMethods
- Defined in:
- lib/lutaml/model/serialize/enum_handling.rb
Overview
Handles enum-related methods for Serialize::ClassMethods
Extracted from serialize.rb to improve code organization. Provides methods for adding enum getter/setter methods to model classes.
Instance Method Summary collapse
-
#add_enum_getter_if_not_defined(klass, enum_name, collection) ⇒ Object
Add enum getter method to model class.
-
#add_enum_methods_to_model(klass, enum_name, values, collection: false) ⇒ Object
Add enum methods to a model class.
-
#add_enum_setter_if_not_defined(klass, enum_name, _values, collection) ⇒ Object
Add enum setter method to model class.
-
#enums ⇒ Hash
Get all enum attributes for this model.
Instance Method Details
#add_enum_getter_if_not_defined(klass, enum_name, collection) ⇒ Object
Add enum getter method to model class
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/lutaml/model/serialize/enum_handling.rb', line 82 def add_enum_getter_if_not_defined(klass, enum_name, collection) Utils.add_method_if_not_defined(klass, enum_name) do i = instance_variable_get(:"@#{enum_name}") || [] # A singular enum stores its one value as a one-element array. # Several values is a cardinality violation, so hand the array # on instead of collapsing it — #validate reads through here and # would otherwise never see the over-count. Collections fall # through to the liveness path so pushes reach the model. next(i.size > 1 ? i : i.first) if !collection && i.is_a?(Array) current = materialize_lazy_collection(enum_name) # An enum collection reads as an Array even when nothing was # stored — the old `(ivar || []).uniq` never returned nil — so # unlike a regular collection this one materializes nil too, and # stores what it materialized so a push reaches the model. if current.nil? next [] if frozen? next instance_variable_set(:"@#{enum_name}", []) end # Not an Array, which means a model-defined writer stored # something else. Read it the way the old reader did and leave # what it stored alone — replacing it here would discard data. next current.uniq unless current.is_a?(::Array) # A frozen Array cannot be deduped in place, and handing back a # copy would lose the shared sentinel's identity, so only copy # when there is actually something to remove. if current.frozen? deduped = current.uniq next deduped.size == current.size ? current : deduped end # Hand back the stored Array, not a copy. This used to be # `i.uniq`, a fresh Array on every read, so `model.roles << "b"` # pushed onto a throwaway and the value never reached the model — # no error, no warning, the item simply never showed up in the # document. It still has to read unique, which is what that `uniq` # guaranteed, so dedupe in place rather than into a copy. current.uniq! current end end |
#add_enum_methods_to_model(klass, enum_name, values, collection: false) ⇒ Object
Add enum methods to a model class
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/lutaml/model/serialize/enum_handling.rb', line 17 def add_enum_methods_to_model(klass, enum_name, values, collection: false) add_enum_getter_if_not_defined(klass, enum_name, collection) add_enum_setter_if_not_defined(klass, enum_name, values, collection) return unless values.all?(::String) values.each do |value| Utils.add_method_if_not_defined(klass, "#{value}?") do curr_value = public_send(:"#{enum_name}") if collection curr_value.include?(value) else curr_value == value end end # Record value name so regular attribute definitions can # override these shorthand methods when an attribute shares # the same name as an enum value (e.g. attribute :char with # align values including "char"). enum_shorthand_names = klass.instance_variable_get(:@__enum_shorthand_names__) || Set.new enum_shorthand_names << value.to_s klass.instance_variable_set(:@__enum_shorthand_names__, enum_shorthand_names) Utils.add_method_if_not_defined(klass, value.to_s) do public_send(:"#{value}?") end Utils.add_method_if_not_defined(klass, "#{value}=") do |val| value_set_for(enum_name) enum_vals = public_send(:"#{enum_name}") # `+` and `-` rather than `<<` and `delete`. The reader hands # back the stored Array now, so mutating it here would reach an # Array a caller already holds — and would land even when the # store below raises on a frozen model. enum_vals = if !!val if collection enum_vals.include?(value) ? enum_vals : enum_vals + [value] else [value] end elsif collection enum_vals - [value] else instance_variable_get(:"@#{enum_name}") - [value] end instance_variable_set(:"@#{enum_name}", enum_vals) end Utils.add_method_if_not_defined(klass, "#{value}!") do public_send(:"#{value}=", true) end end end |
#add_enum_setter_if_not_defined(klass, enum_name, _values, collection) ⇒ Object
Add enum setter method to model class
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/lutaml/model/serialize/enum_handling.rb', line 135 def add_enum_setter_if_not_defined(klass, enum_name, _values, collection) Utils.add_method_if_not_defined(klass, "#{enum_name}=") do |value| value = [] if value.nil? value = [value] if !value.is_a?(Array) value_set_for(enum_name) if collection curr_value = public_send(:"#{enum_name}") # Build a new Array rather than appending into the stored one. # The reader hands back the real Array now, so `curr_value` may # be this model's own collection — or, when the model defines # its own reader, something shared between instances or not an # Array at all. Duplicates are the reader's job either way. instance_variable_set(:"@#{enum_name}", curr_value + value) else instance_variable_set(:"@#{enum_name}", value) end end end |
#enums ⇒ Hash
Get all enum attributes for this model
161 162 163 |
# File 'lib/lutaml/model/serialize/enum_handling.rb', line 161 def enums attributes.select { |_, attr| attr.enum? } end |