lutaml-model 0.8.16 → 0.8.18
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/.github/workflows/downstream-performance.yml +27 -1
- data/.github/workflows/js-pr-check.yml +102 -0
- data/.github/workflows/js-sync.yml +51 -0
- data/.github/workflows/opal.yml +26 -6
- data/.github/workflows/performance.yml +32 -7
- data/.github/workflows/rake.yml +78 -32
- data/.github/workflows/release.yml +0 -3
- data/.gitmodules +6 -0
- data/.rubocop_todo.yml +76 -12
- data/Gemfile +16 -1
- data/README.adoc +267 -0
- data/Rakefile +166 -4
- data/docs/_guides/schema-import.adoc +42 -0
- data/docs/_guides/xml/namespace-semantics.adoc +2 -0
- data/docs/_guides/xml-mapping.adoc +21 -0
- data/docs/_guides/xml-namespace-qualification.adoc +142 -0
- data/docs/_pages/validation.adoc +65 -0
- data/docs/_tutorials/xml-element-attribute-namespace-guide.adoc +2 -0
- data/docs/_tutorials/xml-schema-primer-style-guide.adoc +2 -0
- data/docs/namespace-management.adoc +2 -0
- data/docs/xml-schema-qualification.md +6 -0
- data/lib/compat/opal/generate_boot.rb +123 -0
- data/lib/compat/opal/js_bundle_entry.rb +42 -0
- data/lib/compat/opal/lutaml_model_boot.rb +497 -0
- data/lib/compat/opal/moxml_boot.rb +68 -0
- data/lib/compat/opal/yaml_compat.rb +32 -0
- data/lib/lutaml/json.rb +1 -1
- data/lib/lutaml/jsonld.rb +1 -4
- data/lib/lutaml/key_value/transform.rb +3 -8
- data/lib/lutaml/key_value/transformation/value_serializer.rb +14 -1
- data/lib/lutaml/key_value/transformation.rb +17 -5
- data/lib/lutaml/model/adapter_resolver.rb +2 -2
- data/lib/lutaml/model/attribute.rb +88 -11
- data/lib/lutaml/model/cached_type_resolver.rb +1 -1
- data/lib/lutaml/model/choice.rb +34 -0
- data/lib/lutaml/model/compiled_rule.rb +7 -0
- data/lib/lutaml/model/error/union_schema_unsupported_error.rb +11 -0
- data/lib/lutaml/model/global_context.rb +11 -8
- data/lib/lutaml/model/instrumentation.rb +2 -2
- data/lib/lutaml/model/mapping/mapping_rule.rb +0 -6
- data/lib/lutaml/model/register.rb +2 -2
- data/lib/lutaml/model/runtime_compatibility.rb +50 -0
- data/lib/lutaml/model/schema/class_loader.rb +58 -0
- data/lib/lutaml/model/schema/compiled_output.rb +83 -0
- data/lib/lutaml/model/schema/definitions/attribute.rb +32 -0
- data/lib/lutaml/model/schema/definitions/choice.rb +20 -0
- data/lib/lutaml/model/schema/definitions/facet.rb +40 -0
- data/lib/lutaml/model/schema/definitions/group_import.rb +22 -0
- data/lib/lutaml/model/schema/definitions/member_walk.rb +33 -0
- data/lib/lutaml/model/schema/definitions/model.rb +40 -0
- data/lib/lutaml/model/schema/definitions/namespace.rb +23 -0
- data/lib/lutaml/model/schema/definitions/restricted_type.rb +30 -0
- data/lib/lutaml/model/schema/definitions/sequence.rb +19 -0
- data/lib/lutaml/model/schema/definitions/simple_content.rb +22 -0
- data/lib/lutaml/model/schema/definitions/transform_facet.rb +21 -0
- data/lib/lutaml/model/schema/definitions/type_ref.rb +20 -0
- data/lib/lutaml/model/schema/definitions/union_type.rb +28 -0
- data/lib/lutaml/model/schema/definitions/xml_root.rb +20 -0
- data/lib/lutaml/model/schema/definitions.rb +24 -0
- data/lib/lutaml/model/schema/file_writer.rb +70 -0
- data/lib/lutaml/model/schema/generator/definitions_collection.rb +16 -2
- data/lib/lutaml/model/schema/generator/property.rb +21 -4
- data/lib/lutaml/model/schema/module_nesting.rb +31 -0
- data/lib/lutaml/model/schema/namespace_naming.rb +46 -0
- data/lib/lutaml/model/schema/registry_generator.rb +115 -0
- data/lib/lutaml/model/schema/renderers/base.rb +40 -0
- data/lib/lutaml/model/schema/renderers/mappings.rb +72 -0
- data/lib/lutaml/model/schema/renderers/member_decls.rb +115 -0
- data/lib/lutaml/model/schema/renderers/model.rb +121 -0
- data/lib/lutaml/model/schema/renderers/namespace.rb +30 -0
- data/lib/lutaml/model/schema/renderers/registration.rb +64 -0
- data/lib/lutaml/model/schema/renderers/required_files_calculator.rb +93 -0
- data/lib/lutaml/model/schema/renderers/restricted_type.rb +88 -0
- data/lib/lutaml/model/schema/renderers/union.rb +83 -0
- data/lib/lutaml/model/schema/renderers.rb +19 -0
- data/lib/lutaml/model/schema/rnc_compiler/source_resolver.rb +47 -0
- data/lib/lutaml/model/schema/rnc_compiler.rb +62 -0
- data/lib/lutaml/model/schema/rng_compiler/define_classifier.rb +91 -0
- data/lib/lutaml/model/schema/rng_compiler/element_visitor.rb +392 -0
- data/lib/lutaml/model/schema/rng_compiler/member_collector.rb +30 -0
- data/lib/lutaml/model/schema/rng_compiler/rng_helpers.rb +152 -0
- data/lib/lutaml/model/schema/rng_compiler/value_type_resolver.rb +125 -0
- data/lib/lutaml/model/schema/rng_compiler.rb +220 -0
- data/lib/lutaml/model/schema/templates.rb +162 -0
- data/lib/lutaml/model/schema/xml_compiler/element_order.rb +41 -0
- data/lib/lutaml/model/schema/xml_compiler/registry_generator.rb +31 -107
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/complex_types.rb +191 -0
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/members.rb +216 -0
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/simple_types.rb +153 -0
- data/lib/lutaml/model/schema/xml_compiler/spec_builder.rb +167 -0
- data/lib/lutaml/model/schema/xml_compiler/supported_data_types.rb +87 -0
- data/lib/lutaml/model/schema/xml_compiler.rb +38 -517
- data/lib/lutaml/model/schema.rb +19 -0
- data/lib/lutaml/model/serialize/attribute_definition.rb +14 -2
- data/lib/lutaml/model/serialize/builder.rb +15 -2
- data/lib/lutaml/model/serialize/value_mapping.rb +9 -57
- data/lib/lutaml/model/serialize.rb +6 -9
- data/lib/lutaml/model/services/rule_value_extractor.rb +2 -3
- data/lib/lutaml/model/services.rb +0 -2
- data/lib/lutaml/model/store.rb +2 -1
- data/lib/lutaml/model/toml.rb +1 -1
- data/lib/lutaml/model/transform.rb +17 -39
- data/lib/lutaml/model/transformation_registry.rb +1 -1
- data/lib/lutaml/model/type.rb +1 -0
- data/lib/lutaml/model/union.rb +320 -0
- data/lib/lutaml/model/utils.rb +6 -0
- data/lib/lutaml/model/validation.rb +1 -4
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +19 -0
- data/lib/lutaml/{jsonld → rdf}/context.rb +1 -1
- data/lib/lutaml/{jsonld/transform.rb → rdf/linked_data_transform.rb} +33 -35
- data/lib/lutaml/{jsonld → rdf}/term_definition.rb +1 -1
- data/lib/lutaml/rdf.rb +3 -0
- data/lib/lutaml/toml.rb +1 -1
- data/lib/lutaml/xml/adapter.rb +1 -1
- data/lib/lutaml/xml/adapter_element.rb +2 -2
- data/lib/lutaml/xml/adapter_loader.rb +1 -1
- data/lib/lutaml/xml/builder/base.rb +1 -1
- data/lib/lutaml/xml/builder.rb +1 -1
- data/lib/lutaml/xml/error/schema_validation_error.rb +25 -0
- data/lib/lutaml/xml/model_transform.rb +5 -1
- data/lib/lutaml/xml/schema/relaxng_schema.rb +5 -0
- data/lib/lutaml/xml/schema/xsd_schema.rb +4 -0
- data/lib/lutaml/xml/serialization/format_conversion.rb +48 -0
- data/lib/lutaml/xml/serialization/instance_methods.rb +13 -0
- data/lib/lutaml/xml/transformation/element_builder.rb +59 -31
- data/lib/lutaml/xml/transformation/ordered_applier.rb +6 -0
- data/lib/lutaml/xml/xsd_validator.rb +66 -0
- data/lib/lutaml/xml.rb +53 -12
- data/lib/lutaml/yamlld/adapter.rb +25 -0
- data/lib/lutaml/yamlld.rb +25 -0
- data/lutaml-model.gemspec +4 -2
- data/spec/fixtures/xml/schema/rnc/address_book.rnc +15 -0
- data/spec/fixtures/xml/schema/rnc/book_features.rnc +18 -0
- data/spec/fixtures/xml/schema/rnc/includes/book.rnc +6 -0
- data/spec/fixtures/xml/schema/rnc/includes/circular_a.rnc +8 -0
- data/spec/fixtures/xml/schema/rnc/includes/circular_b.rnc +8 -0
- data/spec/fixtures/xml/schema/rnc/includes/library.rnc +8 -0
- data/spec/fixtures/xml/schema/rng/address_book.rng +16 -0
- data/spec/fixtures/xml/schema/rng/book.rng +27 -0
- data/spec/fixtures/xml/schema/rng/fixed_value.rng +11 -0
- data/spec/fixtures/xml/schema/rng/fragment_in_choice.rng +30 -0
- data/spec/fixtures/xml/schema/rng/full_name.rng +39 -0
- data/spec/fixtures/xml/schema/rng/integer_range.rng +32 -0
- data/spec/fixtures/xml/schema/rng/list_type.rng +12 -0
- data/spec/fixtures/xml/schema/rng/namespaced.rng +9 -0
- data/spec/fixtures/xml/schema/rng/paragraph.rng +13 -0
- data/spec/fixtures/xml/schema/rng/person.rng +23 -0
- data/spec/fixtures/xml/schema/rng/union.rng +14 -0
- data/spec/fixtures/xml/validate_xml_with_address.xsd +13 -0
- data/spec/fixtures/xml/validate_xml_with_contact.xsd +11 -0
- data/spec/fixtures/xml/validate_xml_with_person.xsd +11 -0
- data/spec/fixtures/xml/validate_xml_with_person_strict.xsd +17 -0
- data/spec/fixtures/xml/validate_xml_with_product.xsd +37 -0
- data/spec/lutaml/integration/multi_format_spec.rb +23 -0
- data/spec/lutaml/model/attribute_apply_value_map_spec.rb +134 -0
- data/spec/lutaml/model/attribute_spec.rb +177 -13
- data/spec/lutaml/model/boot_manifest_spec.rb +30 -0
- data/spec/lutaml/model/choice_restrict_spec.rb +225 -0
- data/spec/lutaml/model/collection_spec.rb +18 -0
- data/spec/lutaml/model/custom_model_spec.rb +4 -4
- data/spec/lutaml/model/mixed_content_spec.rb +173 -2
- data/spec/lutaml/model/multiple_mapping_spec.rb +4 -4
- data/spec/lutaml/model/opal_smoke_spec.rb +67 -2
- data/spec/lutaml/model/ordered_content_spec.rb +33 -3
- data/spec/lutaml/model/raw_element_spec.rb +125 -0
- data/spec/lutaml/model/rule_value_extractor_spec.rb +7 -14
- data/spec/lutaml/model/runtime_compatibility_spec.rb +25 -0
- data/spec/lutaml/model/schema/renderers/model_spec.rb +149 -0
- data/spec/lutaml/model/schema/renderers/namespace_spec.rb +36 -0
- data/spec/lutaml/model/schema/renderers/restricted_type_spec.rb +75 -0
- data/spec/lutaml/model/schema/renderers/union_spec.rb +58 -0
- data/spec/lutaml/model/transform_apply_value_map_spec.rb +64 -0
- data/spec/lutaml/model/uninitialized_class_spec.rb +1 -1
- data/spec/lutaml/model/union_attribute_spec.rb +658 -0
- data/spec/lutaml/model/union_spec.rb +257 -0
- data/spec/lutaml/model/utils_spec.rb +14 -0
- data/spec/lutaml/model/xsd_form_default_patterns_spec.rb +2 -2
- data/spec/lutaml/model/xsd_patterns_spec.rb +4 -4
- data/spec/lutaml/{jsonld → rdf}/context_spec.rb +2 -2
- data/spec/lutaml/{jsonld/transform_spec.rb → rdf/linked_data_transform_spec.rb} +15 -1
- data/spec/lutaml/{jsonld → rdf}/term_definition_spec.rb +2 -2
- data/spec/lutaml/turtle/transform_spec.rb +2 -2
- data/spec/lutaml/xml/enhanced_mapping_spec.rb +230 -1
- data/spec/lutaml/xml/mapping_spec.rb +4 -4
- data/spec/lutaml/xml/namespace_placement_spec.rb +11 -8
- data/spec/lutaml/xml/namespace_three_phase_spec.rb +1 -1
- data/spec/lutaml/xml/opal_xml_spec.rb +22 -20
- data/spec/lutaml/xml/prefix_control_spec.rb +4 -4
- data/spec/lutaml/xml/schema/compiler_spec.rb +21 -4
- data/spec/lutaml/xml/schema/rnc_compiler_spec.rb +404 -0
- data/spec/lutaml/xml/schema/rng_compiler_spec.rb +893 -0
- data/spec/lutaml/xml/serializable_namespace_spec.rb +6 -6
- data/spec/lutaml/xml/type_namespace_examples_spec.rb +1 -1
- data/spec/lutaml/xml/type_namespace_integration_spec.rb +3 -3
- data/spec/lutaml/xml/validate_xml_with_constructs_spec.rb +222 -0
- data/spec/lutaml/xml/validate_xml_with_spec.rb +186 -0
- data/spec/lutaml/yamlld/adapter_spec.rb +56 -0
- data/spec/lutaml/yamlld/registration_spec.rb +33 -0
- data/spec/spec_helper.rb +28 -11
- data/spec/support/opal.rb +5 -2
- metadata +108 -37
- data/lib/lutaml/model/schema/xml_compiler/attribute.rb +0 -106
- data/lib/lutaml/model/schema/xml_compiler/attribute_group.rb +0 -47
- data/lib/lutaml/model/schema/xml_compiler/choice.rb +0 -67
- data/lib/lutaml/model/schema/xml_compiler/complex_content.rb +0 -27
- data/lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb +0 -34
- data/lib/lutaml/model/schema/xml_compiler/complex_type.rb +0 -173
- data/lib/lutaml/model/schema/xml_compiler/element.rb +0 -121
- data/lib/lutaml/model/schema/xml_compiler/group.rb +0 -113
- data/lib/lutaml/model/schema/xml_compiler/restriction.rb +0 -104
- data/lib/lutaml/model/schema/xml_compiler/sequence.rb +0 -52
- data/lib/lutaml/model/schema/xml_compiler/simple_content.rb +0 -40
- data/lib/lutaml/model/schema/xml_compiler/simple_type.rb +0 -265
- data/lib/lutaml/model/schema/xml_compiler/xml_namespace_class.rb +0 -110
- data/lib/lutaml/model/services/default_value_resolver.rb +0 -60
- data/spec/lutaml/model/services/default_value_resolver_spec.rb +0 -162
- data/spec/lutaml/xml/schema/compiler/attribute_group_spec.rb +0 -71
- data/spec/lutaml/xml/schema/compiler/attribute_spec.rb +0 -67
- data/spec/lutaml/xml/schema/compiler/choice_spec.rb +0 -74
- data/spec/lutaml/xml/schema/compiler/complex_content_restriction_spec.rb +0 -60
- data/spec/lutaml/xml/schema/compiler/complex_content_spec.rb +0 -41
- data/spec/lutaml/xml/schema/compiler/complex_type_spec.rb +0 -202
- data/spec/lutaml/xml/schema/compiler/element_spec.rb +0 -68
- data/spec/lutaml/xml/schema/compiler/group_spec.rb +0 -90
- data/spec/lutaml/xml/schema/compiler/restriction_spec.rb +0 -77
- data/spec/lutaml/xml/schema/compiler/sequence_spec.rb +0 -65
- data/spec/lutaml/xml/schema/compiler/simple_content_spec.rb +0 -61
- data/spec/lutaml/xml/schema/compiler/simple_type_spec.rb +0 -184
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Lutaml
|
|
4
|
-
module Model
|
|
5
|
-
module Schema
|
|
6
|
-
module XmlCompiler
|
|
7
|
-
class SimpleType
|
|
8
|
-
attr_accessor :class_name, :base_class, :instance, :unions
|
|
9
|
-
|
|
10
|
-
LUTAML_VALUE_CLASS_NAME = "Lutaml::Model::Type::Value"
|
|
11
|
-
|
|
12
|
-
SUPPORTED_DATA_TYPES = {
|
|
13
|
-
nonNegativeInteger: { skippable: false,
|
|
14
|
-
class_name: "Lutaml::Model::Type::String", validations: { pattern: /\+?[0-9]+/ } },
|
|
15
|
-
normalizedString: { skippable: false,
|
|
16
|
-
class_name: "Lutaml::Model::Type::String", validations: { transform: "value.gsub(/[\\r\\n\\t]/, ' ')" } },
|
|
17
|
-
positiveInteger: { skippable: false,
|
|
18
|
-
class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0 } },
|
|
19
|
-
unsignedShort: { skippable: false,
|
|
20
|
-
class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0, max_inclusive: 65535 } },
|
|
21
|
-
base64Binary: { skippable: false,
|
|
22
|
-
class_name: "Lutaml::Model::Type::String", validations: { pattern: /\A([A-Za-z0-9+\/]+={0,2}|\s)*\z/ } },
|
|
23
|
-
unsignedLong: { skippable: false,
|
|
24
|
-
class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0, max_inclusive: 18446744073709551615 } },
|
|
25
|
-
unsignedByte: { skippable: false,
|
|
26
|
-
class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0, max_inclusive: 255 } },
|
|
27
|
-
unsignedInt: { skippable: false,
|
|
28
|
-
class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0, max_inclusive: 4294967295 } },
|
|
29
|
-
hexBinary: { skippable: false,
|
|
30
|
-
class_name: "Lutaml::Model::Type::String", validations: { pattern: /([0-9a-fA-F]{2})*/ } },
|
|
31
|
-
language: { skippable: false,
|
|
32
|
-
class_name: "Lutaml::Model::Type::String", validations: { pattern: /\A[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*\z/ } },
|
|
33
|
-
dateTime: { skippable: true,
|
|
34
|
-
class_name: "Lutaml::Model::Type::DateTime" },
|
|
35
|
-
boolean: { skippable: true,
|
|
36
|
-
class_name: "Lutaml::Model::Type::Boolean" },
|
|
37
|
-
integer: { skippable: true,
|
|
38
|
-
class_name: "Lutaml::Model::Type::Integer" },
|
|
39
|
-
decimal: { skippable: true,
|
|
40
|
-
class_name: "Lutaml::Model::Type::Decimal" },
|
|
41
|
-
string: { skippable: true,
|
|
42
|
-
class_name: "Lutaml::Model::Type::String" },
|
|
43
|
-
double: { skippable: true,
|
|
44
|
-
class_name: "Lutaml::Model::Type::Float" },
|
|
45
|
-
NCName: { skippable: false,
|
|
46
|
-
class_name: "Lutaml::Model::Type::String", validations: { pattern: /\A[a-zA-Z_][\w.-]*\z/ } },
|
|
47
|
-
anyURI: { skippable: false,
|
|
48
|
-
class_name: "Lutaml::Model::Type::String", validations: { pattern: "\\A\#{URI::DEFAULT_PARSER.make_regexp(%w[http https ftp])}\\z" } },
|
|
49
|
-
token: { skippable: false,
|
|
50
|
-
class_name: "Lutaml::Model::Type::String", validations: { pattern: /\A[^\t\n\f\r ]+(?: [^\t\n\f\r ]+)*\z/ } },
|
|
51
|
-
byte: { skippable: false,
|
|
52
|
-
class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: -128, max_inclusive: 127 } },
|
|
53
|
-
long: { skippable: false,
|
|
54
|
-
class_name: "Lutaml::Model::Type::Decimal" },
|
|
55
|
-
int: { skippable: true,
|
|
56
|
-
class_name: "Lutaml::Model::Type::Integer" },
|
|
57
|
-
id: { skippable: false, class_name: "Lutaml::Model::Type::String",
|
|
58
|
-
validations: { pattern: /\A[a-zA-Z_][\w.-]*\z/ } },
|
|
59
|
-
}.freeze
|
|
60
|
-
|
|
61
|
-
INSTANCE_MODEL_TEMPLATE = ERB.new(<<~TEMPLATE, trim_mode: "-")
|
|
62
|
-
# frozen_string_literal: true
|
|
63
|
-
require "lutaml/model"
|
|
64
|
-
|
|
65
|
-
<%= "\#{required_files}\n" -%>
|
|
66
|
-
<%= module_opening -%>
|
|
67
|
-
class <%= klass_name %><%= " < \#{parent_class}" if parent_class %>
|
|
68
|
-
<%= @indent %>def self.cast(value, options = {})
|
|
69
|
-
<%= extended_indent %>return if value.nil?
|
|
70
|
-
|
|
71
|
-
<%= instance&.to_method_body(extended_indent) %>
|
|
72
|
-
value = super(value, options)
|
|
73
|
-
value
|
|
74
|
-
end
|
|
75
|
-
<%= registration_methods -%>
|
|
76
|
-
end
|
|
77
|
-
<%= module_closing -%>
|
|
78
|
-
<%= registration_execution -%>
|
|
79
|
-
TEMPLATE
|
|
80
|
-
|
|
81
|
-
UNION_MODEL_TEMPLATE = ERB.new(<<~TEMPLATE, trim_mode: "-")
|
|
82
|
-
# frozen_string_literal: true
|
|
83
|
-
require "lutaml/model"
|
|
84
|
-
<%= union_required_files %>
|
|
85
|
-
|
|
86
|
-
<%= module_opening -%>
|
|
87
|
-
class <%= klass_name %> < <%= LUTAML_VALUE_CLASS_NAME %>
|
|
88
|
-
<%= @indent %>def self.cast(value, options = {})
|
|
89
|
-
<%= extended_indent %>return if value.nil?
|
|
90
|
-
|
|
91
|
-
<%= union_class_method_body %>
|
|
92
|
-
end
|
|
93
|
-
<%= registration_methods -%>
|
|
94
|
-
end
|
|
95
|
-
<%= module_closing -%>
|
|
96
|
-
<%= registration_execution -%>
|
|
97
|
-
TEMPLATE
|
|
98
|
-
|
|
99
|
-
def initialize(name, unions = [])
|
|
100
|
-
@class_name = name
|
|
101
|
-
@unions = unions
|
|
102
|
-
@module_namespace = nil
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def to_class(options: {})
|
|
106
|
-
setup_options(options)
|
|
107
|
-
template = unions&.any? ? UNION_MODEL_TEMPLATE : INSTANCE_MODEL_TEMPLATE
|
|
108
|
-
template.result(binding)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def required_files
|
|
112
|
-
files = Array(instance&.required_files)
|
|
113
|
-
# Don't add requires for parent classes if using module namespace
|
|
114
|
-
# They're handled via central autoload registry
|
|
115
|
-
if !@module_namespace && require_parent?
|
|
116
|
-
files << "require_relative \"#{Utils.snake_case(parent_class)}\""
|
|
117
|
-
end
|
|
118
|
-
# Filter out require_relative when using autoload, keep external requires
|
|
119
|
-
if @module_namespace
|
|
120
|
-
files = files.select { |f| f.start_with?("require \"") }
|
|
121
|
-
end
|
|
122
|
-
files.join("\n")
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
private
|
|
126
|
-
|
|
127
|
-
def setup_options(options)
|
|
128
|
-
@indent = " " * options&.fetch(:indent, 2)
|
|
129
|
-
@extended_indent = @indent * 2
|
|
130
|
-
@module_namespace = options[:module_namespace]
|
|
131
|
-
@modules = @module_namespace&.split("::") || []
|
|
132
|
-
@register_id = options[:register_id]
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def module_opening
|
|
136
|
-
return "" if @modules.empty?
|
|
137
|
-
|
|
138
|
-
@modules.map.with_index do |mod, i|
|
|
139
|
-
"#{' ' * i}module #{mod}"
|
|
140
|
-
end.join("\n") + "\n"
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def module_closing
|
|
144
|
-
return "" if @modules.empty?
|
|
145
|
-
|
|
146
|
-
@modules.reverse.map.with_index do |_mod, i|
|
|
147
|
-
"#{' ' * (@modules.size - i - 1)}end"
|
|
148
|
-
end.join("\n")
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def registration_methods
|
|
152
|
-
if @module_namespace
|
|
153
|
-
# Still need register method for union types that call register.get_class
|
|
154
|
-
<<~REGISTRATION
|
|
155
|
-
|
|
156
|
-
#{@indent}def self.register
|
|
157
|
-
#{extended_indent}Lutaml::Model::Config.default_register
|
|
158
|
-
#{@indent}end
|
|
159
|
-
REGISTRATION
|
|
160
|
-
else
|
|
161
|
-
<<~REGISTRATION
|
|
162
|
-
|
|
163
|
-
#{@indent}def self.register
|
|
164
|
-
#{extended_indent}@register ||= Lutaml::Model::Config.default_register
|
|
165
|
-
#{@indent}end
|
|
166
|
-
|
|
167
|
-
#{@indent}def self.register_class_with_id
|
|
168
|
-
#{extended_indent}context = Lutaml::Model::GlobalContext.context(Lutaml::Model::Config.default_register)
|
|
169
|
-
#{extended_indent}context.registry.register(:#{Utils.snake_case(class_name)}, self)
|
|
170
|
-
#{@indent}end
|
|
171
|
-
REGISTRATION
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def registration_execution
|
|
176
|
-
return "" if @module_namespace
|
|
177
|
-
|
|
178
|
-
"\n#{klass_name}.register_class_with_id"
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def klass_name
|
|
182
|
-
@klass_name ||= Utils.camel_case(class_name)
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
def require_parent?
|
|
186
|
-
return false if Utils.blank?(base_class)
|
|
187
|
-
|
|
188
|
-
!!!SUPPORTED_DATA_TYPES[base_class&.to_sym]&.dig(:skippable)
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
def parent_class
|
|
192
|
-
type_info = SUPPORTED_DATA_TYPES[base_class&.to_sym]
|
|
193
|
-
return type_info[:class_name] if type_info&.dig(:skippable)
|
|
194
|
-
return Utils.camel_case(base_class.to_s) if !!!type_info&.dig(:skippable) && Utils.present?(base_class)
|
|
195
|
-
|
|
196
|
-
LUTAML_VALUE_CLASS_NAME
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
def union_class_method_body
|
|
200
|
-
unions.map do |union|
|
|
201
|
-
"#{extended_indent}Lutaml::Model::GlobalContext.resolve_type(:#{down_union_class_name(union)}, @register).cast(value, options)"
|
|
202
|
-
end.join(" ||\n ")
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
def union_required_files
|
|
206
|
-
# Don't add requires for union classes if using module namespace
|
|
207
|
-
# They're handled via central autoload registry
|
|
208
|
-
return "" if @module_namespace
|
|
209
|
-
|
|
210
|
-
unions.filter_map do |union|
|
|
211
|
-
next if SUPPORTED_DATA_TYPES.dig(last_of_split(union).to_sym,
|
|
212
|
-
:skippable)
|
|
213
|
-
|
|
214
|
-
"require_relative \"#{down_union_class_name(union)}\""
|
|
215
|
-
end.join("\n")
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
def down_union_class_name(union)
|
|
219
|
-
Utils.snake_case(last_of_split(union))
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def last_of_split(field)
|
|
223
|
-
field&.split(":")&.last
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
def extended_indent
|
|
227
|
-
@extended_indent || " "
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
class << self
|
|
231
|
-
def setup_supported_types
|
|
232
|
-
SUPPORTED_DATA_TYPES.reject do |_, simple_type|
|
|
233
|
-
simple_type[:skippable]
|
|
234
|
-
end.each_with_object({}) do |(name, simple_type), hash|
|
|
235
|
-
str_name = name.to_s
|
|
236
|
-
new(str_name).tap do |instance|
|
|
237
|
-
instance.base_class = Utils.base_class_snake_case(simple_type[:class_name])
|
|
238
|
-
instance.instance = setup_restriction(instance.base_class,
|
|
239
|
-
simple_type[:validations])
|
|
240
|
-
hash[str_name] = instance
|
|
241
|
-
end
|
|
242
|
-
end
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def setup_restriction(base_class, validations)
|
|
246
|
-
return unless validations
|
|
247
|
-
|
|
248
|
-
Restriction.new.tap do |restriction|
|
|
249
|
-
restriction.base_class = base_class
|
|
250
|
-
restriction.min_inclusive = validations[:min_inclusive]
|
|
251
|
-
restriction.max_inclusive = validations[:max_inclusive]
|
|
252
|
-
restriction.pattern = validations[:pattern]
|
|
253
|
-
restriction.transform = validations[:transform]
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
def skippable?(type)
|
|
258
|
-
SUPPORTED_DATA_TYPES.dig(type&.to_sym, :skippable)
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
end
|
|
265
|
-
end
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Lutaml
|
|
4
|
-
module Model
|
|
5
|
-
module Schema
|
|
6
|
-
module XmlCompiler
|
|
7
|
-
# Generates XmlNamespace class definitions from XSD namespace URIs
|
|
8
|
-
class XmlNamespaceClass
|
|
9
|
-
attr_accessor :uri, :prefix_default, :class_name
|
|
10
|
-
|
|
11
|
-
TEMPLATE = ERB.new(<<~TEMPLATE, trim_mode: "-")
|
|
12
|
-
# frozen_string_literal: true
|
|
13
|
-
|
|
14
|
-
require "lutaml/model"
|
|
15
|
-
|
|
16
|
-
<%= module_opening -%>
|
|
17
|
-
# Namespace: <%= uri %>
|
|
18
|
-
class <%= class_name %> < Lutaml::Xml::W3c::XmlNamespace
|
|
19
|
-
uri <%= uri.inspect %>
|
|
20
|
-
prefix_default <%= prefix_default.inspect %>
|
|
21
|
-
end
|
|
22
|
-
<%= module_closing -%>
|
|
23
|
-
TEMPLATE
|
|
24
|
-
|
|
25
|
-
def initialize(uri:, prefix: nil, class_name: nil)
|
|
26
|
-
@uri = uri
|
|
27
|
-
@prefix_default = prefix || derive_prefix_from_uri(uri)
|
|
28
|
-
@class_name = class_name || derive_class_name_from_uri(uri)
|
|
29
|
-
@module_namespace = nil
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def to_class(options: {})
|
|
33
|
-
@module_namespace = options[:module_namespace]
|
|
34
|
-
@modules = @module_namespace&.split("::") || []
|
|
35
|
-
TEMPLATE.result(binding)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def required_file
|
|
39
|
-
"require_relative \"#{Utils.snake_case(class_name)}\""
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def class_reference
|
|
43
|
-
class_name
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
def module_opening
|
|
49
|
-
return "" if @modules.empty?
|
|
50
|
-
|
|
51
|
-
@modules.map.with_index do |mod, i|
|
|
52
|
-
"#{' ' * i}module #{mod}"
|
|
53
|
-
end.join("\n") + "\n"
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def module_closing
|
|
57
|
-
return "" if @modules.empty?
|
|
58
|
-
|
|
59
|
-
@modules.reverse.map.with_index do |_mod, i|
|
|
60
|
-
"#{' ' * (@modules.size - i - 1)}end"
|
|
61
|
-
end.join("\n")
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def derive_prefix_from_uri(uri)
|
|
65
|
-
# Extract meaningful part from URI
|
|
66
|
-
# http://schemas.openxmlformats.org/officeDocument/2006/math -> "m"
|
|
67
|
-
# http://www.w3.org/2001/XMLSchema -> "xs"
|
|
68
|
-
case uri
|
|
69
|
-
when %r{/math$}
|
|
70
|
-
"m"
|
|
71
|
-
when %r{XMLSchema}
|
|
72
|
-
"xs"
|
|
73
|
-
when %r{/(\w+)$}
|
|
74
|
-
$1[0..2] # First 3 chars
|
|
75
|
-
else
|
|
76
|
-
"ns" # Generic prefix
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def derive_class_name_from_uri(uri)
|
|
81
|
-
# Extract domain and path components
|
|
82
|
-
# http://schemas.openxmlformats.org/officeDocument/2006/math
|
|
83
|
-
# -> OoxmlMathNamespace
|
|
84
|
-
return "XmlSchemaNamespace" if uri.include?("XMLSchema")
|
|
85
|
-
|
|
86
|
-
parsed_uri = URI.parse(uri)
|
|
87
|
-
parts = parsed_uri.host&.split(".")&.reject(&:empty?) || []
|
|
88
|
-
path_parts = parsed_uri.path&.split("/")&.reject(&:empty?) || []
|
|
89
|
-
|
|
90
|
-
# Use reverse domain notation + meaningful path parts
|
|
91
|
-
# Filter out version numbers and empty parts
|
|
92
|
-
name_parts = parts.reverse.take(2) + path_parts.last(2)
|
|
93
|
-
name_parts = name_parts.map do |p|
|
|
94
|
-
Utils.camel_case(p.gsub(/\d+/, "").gsub(/[^a-zA-Z]/, ""))
|
|
95
|
-
end
|
|
96
|
-
.reject(&:empty?)
|
|
97
|
-
|
|
98
|
-
# Fallback if no valid parts
|
|
99
|
-
return "DefaultNamespace" if name_parts.empty?
|
|
100
|
-
|
|
101
|
-
"#{name_parts.join}Namespace"
|
|
102
|
-
rescue URI::InvalidURIError, StandardError
|
|
103
|
-
# Fallback for invalid URIs or any other errors
|
|
104
|
-
"DefaultNamespace"
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
require_relative "base"
|
|
2
|
-
|
|
3
|
-
module Lutaml
|
|
4
|
-
module Model
|
|
5
|
-
module Services
|
|
6
|
-
class DefaultValueResolver < Base
|
|
7
|
-
def initialize(attribute, register, instance_object)
|
|
8
|
-
super()
|
|
9
|
-
|
|
10
|
-
@attribute = attribute
|
|
11
|
-
@register = register
|
|
12
|
-
@instance_object = instance_object
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# Get the default value with proper instance context and casting
|
|
16
|
-
# Returns the evaluated and casted default value
|
|
17
|
-
def default
|
|
18
|
-
attribute.cast_value(default_value, register)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Get the default value with proper instance context
|
|
22
|
-
# Returns the evaluated default value (procs are executed)
|
|
23
|
-
def default_value
|
|
24
|
-
raw_value = raw_default_value
|
|
25
|
-
return raw_value unless raw_value.is_a?(Proc)
|
|
26
|
-
|
|
27
|
-
# Execute proc in instance context if available, otherwise call it directly
|
|
28
|
-
if instance_object
|
|
29
|
-
instance_object.instance_exec(&raw_value)
|
|
30
|
-
else
|
|
31
|
-
raw_value.call
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Get the raw default value without executing procs
|
|
36
|
-
def raw_default_value
|
|
37
|
-
if attribute.delegate
|
|
38
|
-
# For delegated attributes, recursively resolve through the service
|
|
39
|
-
delegated_attr = attribute.type(register).attributes[attribute.to]
|
|
40
|
-
self.class.new(delegated_attr, register,
|
|
41
|
-
instance_object).raw_default_value
|
|
42
|
-
elsif attribute.options.key?(:default)
|
|
43
|
-
attribute.options[:default]
|
|
44
|
-
else
|
|
45
|
-
Lutaml::Model::UninitializedClass.instance
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Check if a default value is set (not uninitialized)
|
|
50
|
-
def default_set?
|
|
51
|
-
!Utils.uninitialized?(raw_default_value)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
private
|
|
55
|
-
|
|
56
|
-
attr_reader :attribute, :register, :instance_object
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
|
|
3
|
-
class TestModel < Lutaml::Model::Serializable
|
|
4
|
-
attribute :_class, :string, default: -> { self.class.name }
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
RSpec.describe Lutaml::Model::Services::DefaultValueResolver do
|
|
8
|
-
let(:register) { Lutaml::Model::Config.default_register }
|
|
9
|
-
let(:instance) { nil }
|
|
10
|
-
|
|
11
|
-
describe "#default_value" do
|
|
12
|
-
context "when default is a static value" do
|
|
13
|
-
let(:attribute) do
|
|
14
|
-
Lutaml::Model::Attribute.new("name", :string, default: "John")
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
it "returns the static value" do
|
|
18
|
-
resolver = described_class.new(attribute, register, instance)
|
|
19
|
-
expect(resolver.default_value).to eq("John")
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
context "when default is a proc without instance context" do
|
|
24
|
-
let(:attribute) do
|
|
25
|
-
Lutaml::Model::Attribute.new("count", :integer, default: -> { 42 })
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it "executes the proc" do
|
|
29
|
-
resolver = described_class.new(attribute, register, instance)
|
|
30
|
-
expect(resolver.default_value).to eq(42)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
context "when default is a proc with instance context" do
|
|
35
|
-
let(:model) { TestModel.new }
|
|
36
|
-
let(:attribute) { TestModel.attributes[:_class] }
|
|
37
|
-
|
|
38
|
-
it "executes the proc in the instance context" do
|
|
39
|
-
resolver = described_class.new(attribute, register, model)
|
|
40
|
-
expect(resolver.default_value).to eq("TestModel")
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
describe "#default" do
|
|
46
|
-
context "when default is a static value" do
|
|
47
|
-
let(:attribute) do
|
|
48
|
-
Lutaml::Model::Attribute.new("count", :integer, default: "42")
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it "returns the casted value" do
|
|
52
|
-
resolver = described_class.new(attribute, register, instance)
|
|
53
|
-
expect(resolver.default).to eq(42)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
context "when default is a proc" do
|
|
58
|
-
let(:attribute) do
|
|
59
|
-
Lutaml::Model::Attribute.new("file", :string, default: -> {
|
|
60
|
-
Pathname.new("avatar.png")
|
|
61
|
-
})
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
it "returns the casted proc result" do
|
|
65
|
-
resolver = described_class.new(attribute, register, instance)
|
|
66
|
-
expect(resolver.default).to eq("avatar.png")
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
context "when default is a proc with instance context" do
|
|
71
|
-
let(:model) { TestModel.new }
|
|
72
|
-
let(:attribute) { TestModel.attributes[:_class] }
|
|
73
|
-
|
|
74
|
-
it "executes and casts the proc in the instance context" do
|
|
75
|
-
resolver = described_class.new(attribute, register, model)
|
|
76
|
-
expect(resolver.default).to eq("TestModel")
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
describe "#raw_default_value" do
|
|
82
|
-
context "when default is not set" do
|
|
83
|
-
let(:attribute) do
|
|
84
|
-
Lutaml::Model::Attribute.new("name", :string)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
it "returns uninitialized" do
|
|
88
|
-
resolver = described_class.new(attribute, register, instance)
|
|
89
|
-
expect(resolver.raw_default_value).to be(Lutaml::Model::UninitializedClass.instance)
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
context "when default is a static value" do
|
|
94
|
-
let(:attribute) do
|
|
95
|
-
Lutaml::Model::Attribute.new("name", :string, default: "John")
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
it "returns the static value without execution" do
|
|
99
|
-
resolver = described_class.new(attribute, register, instance)
|
|
100
|
-
expect(resolver.raw_default_value).to eq("John")
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
context "when default is a proc" do
|
|
105
|
-
let(:proc_default) { -> { "John" } }
|
|
106
|
-
let(:attribute) do
|
|
107
|
-
Lutaml::Model::Attribute.new("name", :string, default: proc_default)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
it "returns the proc without execution" do
|
|
111
|
-
resolver = described_class.new(attribute, register, instance)
|
|
112
|
-
expect(resolver.raw_default_value).to eq(proc_default)
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
context "when default is nil" do
|
|
117
|
-
let(:attribute) do
|
|
118
|
-
Lutaml::Model::Attribute.new("value", :string, default: nil)
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
it "returns nil" do
|
|
122
|
-
resolver = described_class.new(attribute, register, instance)
|
|
123
|
-
expect(resolver.raw_default_value).to be_nil
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
describe "#default_set?" do
|
|
129
|
-
context "when default is not set" do
|
|
130
|
-
let(:attribute) do
|
|
131
|
-
Lutaml::Model::Attribute.new("name", :string)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
it "returns false" do
|
|
135
|
-
resolver = described_class.new(attribute, register, instance)
|
|
136
|
-
expect(resolver.default_set?).to be(false)
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
context "when default is a static value" do
|
|
141
|
-
let(:attribute) do
|
|
142
|
-
Lutaml::Model::Attribute.new("name", :string, default: "John")
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
it "returns true" do
|
|
146
|
-
resolver = described_class.new(attribute, register, instance)
|
|
147
|
-
expect(resolver.default_set?).to be(true)
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
context "when default is a proc" do
|
|
152
|
-
let(:attribute) do
|
|
153
|
-
Lutaml::Model::Attribute.new("name", :string, default: -> { "John" })
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
it "returns true" do
|
|
157
|
-
resolver = described_class.new(attribute, register, instance)
|
|
158
|
-
expect(resolver.default_set?).to be(true)
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
end
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "support/xml/schema_helper"
|
|
3
|
-
|
|
4
|
-
RSpec.describe Lutaml::Model::Schema::XmlCompiler::AttributeGroup do
|
|
5
|
-
let(:attribute_group) { described_class.new(name: "foo", ref: nil) }
|
|
6
|
-
let(:dummy_class) do
|
|
7
|
-
Class.new do
|
|
8
|
-
def to_attributes(indent); end
|
|
9
|
-
def to_xml_mapping(indent); end
|
|
10
|
-
def required_files; end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe "#initialize" do
|
|
15
|
-
it "sets name, ref, and empty instances" do
|
|
16
|
-
ag = described_class.new(name: "bar", ref: "baz")
|
|
17
|
-
expect(ag.name).to eq("bar")
|
|
18
|
-
expect(ag.ref).to eq("baz")
|
|
19
|
-
expect(ag.instances).to eq([])
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
describe "#<<" do
|
|
24
|
-
it "adds instances to the list" do
|
|
25
|
-
instance = instance_double(dummy_class, to_attributes: "attr",
|
|
26
|
-
to_xml_mapping: "xml", required_files: "files")
|
|
27
|
-
expect { attribute_group << instance }.to change {
|
|
28
|
-
attribute_group.instances.size
|
|
29
|
-
}.by(1)
|
|
30
|
-
expect(attribute_group.instances).to include(instance)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it "ignores nil instances" do
|
|
34
|
-
expect { attribute_group << nil }.not_to(change do
|
|
35
|
-
attribute_group.instances.size
|
|
36
|
-
end)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
describe "#to_attributes" do
|
|
41
|
-
it "returns attributes from resolved_instances" do
|
|
42
|
-
instance = instance_double(dummy_class, to_attributes: "attr")
|
|
43
|
-
attribute_group.instances = [instance]
|
|
44
|
-
expect(attribute_group.to_attributes(" ").join).to include("attr")
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
describe "#to_xml_mapping" do
|
|
49
|
-
it "returns xml mappings from resolved_instances" do
|
|
50
|
-
instance = instance_double(dummy_class, to_xml_mapping: "xml")
|
|
51
|
-
attribute_group.instances = [instance]
|
|
52
|
-
expect(attribute_group.to_xml_mapping(" ").join).to include("xml")
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
describe "#required_files" do
|
|
57
|
-
it "collects required_files from resolved_instances" do
|
|
58
|
-
instance = instance_double(dummy_class, required_files: "files")
|
|
59
|
-
attribute_group.instances = [instance]
|
|
60
|
-
expect(attribute_group.required_files.join).to include("files")
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
describe "private methods" do
|
|
65
|
-
it "resolved_instances returns @instances if ref is not present" do
|
|
66
|
-
attribute_group.instances = [1, 2]
|
|
67
|
-
attribute_group.ref = nil
|
|
68
|
-
expect(attribute_group.send(:resolved_instances)).to eq([1, 2])
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|