Class: Lutaml::Model::Choice
- Inherits:
-
Object
- Object
- Lutaml::Model::Choice
- Defined in:
- lib/lutaml/model/choice.rb
Constant Summary collapse
- INTERNAL_ATTRIBUTES =
%i[@flat_attributes].freeze
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
Returns the value of attribute attributes.
-
#format ⇒ Object
Returns the value of attribute format.
-
#max ⇒ Object
readonly
Returns the value of attribute max.
-
#min ⇒ Object
readonly
Returns the value of attribute min.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
Instance Method Summary collapse
- #==(other) ⇒ Object
- #attribute(name, type, options = {}) ⇒ Object
- #can_render_empty?(_object) ⇒ Boolean
- #choice(min: 1, max: 1, &block) ⇒ Object
- #deep_duplicate(new_model, register = nil) ⇒ Object
- #flat_attributes ⇒ Object
- #import_model_attributes(model, register_id = nil) ⇒ Object
-
#initialize(model, min, max, format: nil) ⇒ Choice
constructor
A new instance of Choice.
- #optional_empty_choice?(count) ⇒ Boolean
- #pretty_print_instance_variables ⇒ Object
-
#remove_attribute(name) ⇒ Boolean
Remove an attribute from this choice block.
-
#restrict(name, options = {}) ⇒ Symbol
Restrict options on a predefined or imported attribute within this choice.
- #validate_content!(object, register = nil) ⇒ Object
- #validate_count_errors!(count, attributes) ⇒ Object
- #validate_sequence_content!(elements, appearance_count = 0, register = nil) ⇒ Object
Constructor Details
#initialize(model, min, max, format: nil) ⇒ Choice
Returns a new instance of Choice.
14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/lutaml/model/choice.rb', line 14 def initialize(model, min, max, format: nil) @attributes = [] @model = model @min = min @max = max @format = format if @min.negative? || @max.negative? raise Lutaml::Model::InvalidChoiceRangeError.new(@min, @max) end end |
Instance Attribute Details
#attributes ⇒ Object (readonly)
Returns the value of attribute attributes.
6 7 8 |
# File 'lib/lutaml/model/choice.rb', line 6 def attributes @attributes end |
#format ⇒ Object
Returns the value of attribute format.
10 11 12 |
# File 'lib/lutaml/model/choice.rb', line 10 def format @format end |
#max ⇒ Object (readonly)
Returns the value of attribute max.
6 7 8 |
# File 'lib/lutaml/model/choice.rb', line 6 def max @max end |
#min ⇒ Object (readonly)
Returns the value of attribute min.
6 7 8 |
# File 'lib/lutaml/model/choice.rb', line 6 def min @min end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
6 7 8 |
# File 'lib/lutaml/model/choice.rb', line 6 def model @model end |
Instance Method Details
#==(other) ⇒ Object
27 28 29 30 31 32 |
# File 'lib/lutaml/model/choice.rb', line 27 def ==(other) @attributes == other.attributes && @min == other.min && @max == other.max && @model == other.model end |
#attribute(name, type, options = {}) ⇒ Object
34 35 36 37 |
# File 'lib/lutaml/model/choice.rb', line 34 def attribute(name, type, = {}) [:choice] = self @attributes << @model.attribute(name, type, ) end |
#can_render_empty?(_object) ⇒ Boolean
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/lutaml/model/choice.rb', line 102 def can_render_empty?(_object) # Check if ALL attributes in the choice have render_empty: true # This allows empty instances of required elements to pass validation return false unless @format mapping = @model.mappings_for(@format) return false unless mapping&.elements @attributes.all? do |attribute| next true if attribute.is_a?(Choice) # Nested choices handled separately rule = mapping.elements.find { |r| r.to == attribute.name } rule&.render_empty? end rescue StandardError false end |
#choice(min: 1, max: 1, &block) ⇒ Object
69 70 71 72 73 |
# File 'lib/lutaml/model/choice.rb', line 69 def choice(min: 1, max: 1, &block) @attributes << Choice.new(@model, min, max, format: @format).tap do |c| c.instance_eval(&block) end end |
#deep_duplicate(new_model, register = nil) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/lutaml/model/choice.rb', line 152 def deep_duplicate(new_model, register = nil) choice = self.class.new(new_model, @min, @max, format: @format) attrs = @attributes.map do |attr| next attr.deep_duplicate(new_model, register) if attr.is_a?(Choice) choice_attr = new_model.attributes(register)[attr.name] next if choice_attr.nil? choice_attr.[:choice] = choice choice_attr end choice.attributes.concat(attrs.compact) choice end |
#flat_attributes ⇒ Object
75 76 77 78 79 |
# File 'lib/lutaml/model/choice.rb', line 75 def flat_attributes @flat_attributes ||= @attributes.flat_map do |attribute| attribute.is_a?(Choice) ? attribute.flat_attributes : attribute end end |
#import_model_attributes(model, register_id = nil) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/lutaml/model/choice.rb', line 120 def import_model_attributes(model, register_id = nil) if later_importable?(model) return import_model_later(model, :import_model_attributes) end root_model_error(model) register_id ||= Lutaml::Model::Config.default_register if register_id != :default # Non-default register: store in register-specific storage only current_record = @model.register_records[register_id] ||= { attributes: {}, choice_attributes: [] } imported_attributes = Utils.deep_dup(model.attributes(register_id)) imported_attributes.each_value do |attr| attr.[:choice] = self end current_record[:attributes].merge!(imported_attributes) return end # Default register: store in class-level storage imported_attributes = Utils.deep_dup(model.attributes.values) imported_attributes.each do |attr| attr.[:choice] = self @model.define_attribute_methods(attr) end @attributes.concat(imported_attributes) attrs_hash = imported_attributes.to_h { |attr| [attr.name, attr] } @model.attributes.merge!(attrs_hash) end |
#optional_empty_choice?(count) ⇒ Boolean
182 183 184 185 186 187 188 |
# File 'lib/lutaml/model/choice.rb', line 182 def optional_empty_choice?(count) count.zero? && @attributes.any? do |attr| next attr.optional_empty_choice?(count) if attr.is_a?(self.class) optional_attribute?(attr) end end |
#pretty_print_instance_variables ⇒ Object
190 191 192 |
# File 'lib/lutaml/model/choice.rb', line 190 def pretty_print_instance_variables (instance_variables - INTERNAL_ATTRIBUTES).sort end |
#remove_attribute(name) ⇒ Boolean
Remove an attribute from this choice block
59 60 61 62 63 64 65 66 67 |
# File 'lib/lutaml/model/choice.rb', line 59 def remove_attribute(name) attr = @attributes.find { |a| !a.is_a?(Choice) && a.name == name } return nil unless attr @attributes.delete(attr) attr..delete(:choice) invalidate_cache! attr end |
#restrict(name, options = {}) ⇒ Symbol
Restrict options on a predefined or imported attribute within this choice
44 45 46 47 48 49 50 51 52 53 |
# File 'lib/lutaml/model/choice.rb', line 44 def restrict(name, = {}) @model.restrict(name, ) attr = @model.attributes[name] unless @attributes.include?(attr) attr.[:choice] = self @attributes << attr end invalidate_cache! name end |
#validate_content!(object, register = nil) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/lutaml/model/choice.rb', line 90 def validate_content!(object, register = nil) validated_attributes = [] valid = valid_attributes(object, validated_attributes, register) # Allow empty choice if it can render empty elements if valid.none? && can_render_empty?(object) return end validate_count_errors!(valid.count, validated_attributes) end |
#validate_count_errors!(count, attributes) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/lutaml/model/choice.rb', line 168 def validate_count_errors!(count, attributes) return if count.between?(@min, @max) return if optional_empty_choice?(count) if count < @min raise Lutaml::Model::ChoiceLowerBoundError.new(attributes, @min) end if count > @max raise Lutaml::Model::ChoiceUpperBoundError.new(attributes, @max) end end |
#validate_sequence_content!(elements, appearance_count = 0, register = nil) ⇒ Object
81 82 83 84 85 86 87 88 |
# File 'lib/lutaml/model/choice.rb', line 81 def validate_sequence_content!(elements, appearance_count = 0, register = nil) choices_hash = ::Hash.new { |h, k| h[k] = 0 } choices_hash[self] = appearance_count current_index = validate_choices(elements, choices_hash, register) raise_errors(choices_hash) current_index end |