lutaml-model 0.3.24 → 0.3.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +35 -16
  3. data/README.adoc +274 -28
  4. data/lib/lutaml/model/attribute.rb +18 -8
  5. data/lib/lutaml/model/error/type_error.rb +9 -0
  6. data/lib/lutaml/model/error/unknown_type_error.rb +9 -0
  7. data/lib/lutaml/model/error/validation_error.rb +0 -1
  8. data/lib/lutaml/model/error.rb +2 -0
  9. data/lib/lutaml/model/serialize.rb +6 -1
  10. data/lib/lutaml/model/type/boolean.rb +38 -0
  11. data/lib/lutaml/model/type/date.rb +35 -0
  12. data/lib/lutaml/model/type/date_time.rb +32 -4
  13. data/lib/lutaml/model/type/decimal.rb +42 -0
  14. data/lib/lutaml/model/type/float.rb +37 -0
  15. data/lib/lutaml/model/type/hash.rb +62 -0
  16. data/lib/lutaml/model/type/integer.rb +41 -0
  17. data/lib/lutaml/model/type/string.rb +49 -0
  18. data/lib/lutaml/model/type/time.rb +49 -0
  19. data/lib/lutaml/model/type/time_without_date.rb +37 -5
  20. data/lib/lutaml/model/type/value.rb +52 -0
  21. data/lib/lutaml/model/type.rb +50 -114
  22. data/lib/lutaml/model/version.rb +1 -1
  23. data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +5 -2
  24. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +2 -1
  25. data/lib/lutaml/model/xml_adapter/xml_document.rb +0 -2
  26. data/lutaml-model.gemspec +1 -1
  27. data/spec/address_spec.rb +170 -0
  28. data/spec/fixtures/address.rb +33 -0
  29. data/spec/fixtures/person.rb +73 -0
  30. data/spec/fixtures/sample_model.rb +40 -0
  31. data/spec/fixtures/vase.rb +38 -0
  32. data/spec/fixtures/xml/special_char.xml +13 -0
  33. data/spec/lutaml/model/attribute_spec.rb +112 -0
  34. data/spec/lutaml/model/collection_spec.rb +299 -0
  35. data/spec/lutaml/model/comparable_model_spec.rb +106 -0
  36. data/spec/lutaml/model/custom_model_spec.rb +410 -0
  37. data/spec/lutaml/model/custom_serialization_spec.rb +170 -0
  38. data/spec/lutaml/model/defaults_spec.rb +221 -0
  39. data/spec/lutaml/model/delegation_spec.rb +340 -0
  40. data/spec/lutaml/model/inheritance_spec.rb +92 -0
  41. data/spec/lutaml/model/json_adapter_spec.rb +37 -0
  42. data/spec/lutaml/model/key_value_mapping_spec.rb +86 -0
  43. data/spec/lutaml/model/map_content_spec.rb +118 -0
  44. data/spec/lutaml/model/mixed_content_spec.rb +625 -0
  45. data/spec/lutaml/model/namespace_spec.rb +57 -0
  46. data/spec/lutaml/model/ordered_content_spec.rb +83 -0
  47. data/spec/lutaml/model/render_nil_spec.rb +138 -0
  48. data/spec/lutaml/model/schema/json_schema_spec.rb +79 -0
  49. data/spec/lutaml/model/schema/relaxng_schema_spec.rb +60 -0
  50. data/spec/lutaml/model/schema/xsd_schema_spec.rb +55 -0
  51. data/spec/lutaml/model/schema/yaml_schema_spec.rb +47 -0
  52. data/spec/lutaml/model/serializable_spec.rb +297 -0
  53. data/spec/lutaml/model/serializable_validation_spec.rb +85 -0
  54. data/spec/lutaml/model/simple_model_spec.rb +314 -0
  55. data/spec/lutaml/model/toml_adapter_spec.rb +39 -0
  56. data/spec/lutaml/model/type/boolean_spec.rb +54 -0
  57. data/spec/lutaml/model/type/date_spec.rb +118 -0
  58. data/spec/lutaml/model/type/date_time_spec.rb +127 -0
  59. data/spec/lutaml/model/type/decimal_spec.rb +125 -0
  60. data/spec/lutaml/model/type/float_spec.rb +191 -0
  61. data/spec/lutaml/model/type/hash_spec.rb +63 -0
  62. data/spec/lutaml/model/type/integer_spec.rb +145 -0
  63. data/spec/lutaml/model/type/string_spec.rb +150 -0
  64. data/spec/lutaml/model/type/time_spec.rb +142 -0
  65. data/spec/lutaml/model/type/time_without_date_spec.rb +125 -0
  66. data/spec/lutaml/model/type_spec.rb +276 -0
  67. data/spec/lutaml/model/utils_spec.rb +79 -0
  68. data/spec/lutaml/model/validation_spec.rb +83 -0
  69. data/spec/lutaml/model/with_child_mapping_spec.rb +174 -0
  70. data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +56 -0
  71. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +56 -0
  72. data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +61 -0
  73. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +251 -0
  74. data/spec/lutaml/model/xml_adapter_spec.rb +178 -0
  75. data/spec/lutaml/model/xml_mapping_spec.rb +863 -0
  76. data/spec/lutaml/model/yaml_adapter_spec.rb +30 -0
  77. data/spec/lutaml/model_spec.rb +1 -0
  78. data/spec/person_spec.rb +161 -0
  79. data/spec/spec_helper.rb +33 -0
  80. metadata +66 -2
@@ -0,0 +1,35 @@
1
+ module Lutaml
2
+ module Model
3
+ module Type
4
+ class Date < Value
5
+ def self.cast(value)
6
+ return nil if value.nil?
7
+
8
+ case value
9
+ when ::DateTime, ::Time
10
+ value.to_date
11
+ when ::Date
12
+ value
13
+ else
14
+ ::Date.parse(value.to_s)
15
+ end
16
+ rescue ArgumentError
17
+ nil
18
+ end
19
+
20
+ # xs:date format
21
+ def self.serialize(value)
22
+ return nil if value.nil?
23
+
24
+ value&.iso8601
25
+ end
26
+
27
+ # This is to handle where Ruby's YAML safe_load does not handle
28
+ # the Date/Time classes
29
+ def to_yaml
30
+ value&.iso8601.to_s
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -4,15 +4,43 @@ module Lutaml
4
4
  module Model
5
5
  module Type
6
6
  # Date and time representation
7
- class DateTime
7
+ class DateTime < Value
8
8
  def self.cast(value)
9
- return if value.nil?
9
+ return nil if value.nil?
10
10
 
11
- ::DateTime.parse(value.to_s).new_offset(0)
11
+ case value
12
+ when ::DateTime then value
13
+ when ::Time then value.to_datetime
14
+ else ::DateTime.parse(value.to_s)
15
+ end
16
+ rescue ArgumentError
17
+ nil
12
18
  end
13
19
 
14
20
  def self.serialize(value)
15
- value.iso8601
21
+ return nil if value.nil?
22
+
23
+ cast(value)&.iso8601
24
+ end
25
+
26
+ # xs:dateTime format (ISO8601 with timezone)
27
+ def to_xml
28
+ value&.iso8601
29
+ end
30
+
31
+ # RFC3339 (ISO8601 with timezone)
32
+ def to_json(*_args)
33
+ value&.iso8601
34
+ end
35
+
36
+ # YAML timestamp format (native)
37
+ def to_yaml
38
+ value&.iso8601
39
+ end
40
+
41
+ # TOML datetime format (RFC3339)
42
+ def to_toml
43
+ value&.iso8601
16
44
  end
17
45
  end
18
46
  end
@@ -0,0 +1,42 @@
1
+ module Lutaml
2
+ module Model
3
+ module Type
4
+ class Decimal < Value
5
+ def self.cast(value)
6
+ return nil if value.nil?
7
+
8
+ check_dependencies!(value)
9
+ case value
10
+ when BigDecimal
11
+ # If already a BigDecimal, return as-is
12
+ value
13
+ else
14
+ # Convert to string first to handle various input types
15
+ BigDecimal(value.to_s)
16
+ end
17
+ rescue ArgumentError
18
+ nil
19
+ end
20
+
21
+ # # xs:decimal format
22
+ def self.serialize(value)
23
+ return nil if value.nil?
24
+
25
+ check_dependencies!(value)
26
+ value = cast(value)
27
+ value.to_s("F") # Use fixed-point notation to match test expectations
28
+ end
29
+
30
+ def self.from_xml(value)
31
+ cast(value.text)
32
+ end
33
+
34
+ def self.check_dependencies!(value)
35
+ unless defined?(BigDecimal)
36
+ raise TypeNotEnabledError.new("Decimal", value)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ module Lutaml
2
+ module Model
3
+ module Type
4
+ class Float < Value
5
+ def self.cast(value)
6
+ return nil if value.nil?
7
+
8
+ value.to_f
9
+ end
10
+
11
+ def self.serialize(value)
12
+ return nil if value.nil?
13
+
14
+ cast(value)
15
+ end
16
+
17
+ # Instance methods for specific formats
18
+ # xs:float format
19
+ def to_xml
20
+ value.to_s
21
+ end
22
+
23
+ def to_yaml
24
+ value
25
+ end
26
+
27
+ def to_json(*_args)
28
+ value
29
+ end
30
+
31
+ def to_yaml
32
+ value
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,62 @@
1
+ module Lutaml
2
+ module Model
3
+ module Type
4
+ class Hash < Value
5
+ def self.cast(value)
6
+ return nil if value.nil?
7
+
8
+ hash = if value.respond_to?(:to_h)
9
+ value.to_h
10
+ else
11
+ Hash(value)
12
+ end
13
+
14
+ normalize_hash(hash)
15
+ end
16
+
17
+ def self.normalize_hash(hash)
18
+ return hash["text"] if hash.keys == ["text"]
19
+
20
+ hash = hash.to_h if hash.is_a?(Lutaml::Model::MappingHash)
21
+
22
+ hash = hash.except("text")
23
+
24
+ hash.transform_values do |value|
25
+ if value.is_a?(::Hash)
26
+ # Only process if value is a Hash
27
+ nested = normalize_hash(value)
28
+ # Only include non-text nodes in nested hashes if it's a hash
29
+ nested.is_a?(::Hash) ? nested.except("text") : nested
30
+ else
31
+ value
32
+ end
33
+ end
34
+ end
35
+
36
+ def self.serialize(value)
37
+ return nil if value.nil?
38
+ return value if value.is_a?(Hash)
39
+
40
+ value.respond_to?(:to_h) ? value.to_h : Hash(value)
41
+ end
42
+
43
+ # Format-specific serialization methods
44
+ def to_xml
45
+ value
46
+ end
47
+
48
+ def to_json(*_args)
49
+ value
50
+ end
51
+
52
+ def to_yaml
53
+ value
54
+ end
55
+
56
+ def to_toml
57
+ value
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,41 @@
1
+ module Lutaml
2
+ module Model
3
+ module Type
4
+ class Integer < Value
5
+ def self.cast(value)
6
+ return nil if value.nil?
7
+ return 1 if value === true
8
+ return 0 if value === false
9
+
10
+ case value
11
+ when ::String
12
+ if value.match?(/^0[0-7]+$/) # Octal
13
+ value.to_i(8)
14
+ elsif value.match?(/^-?\d+(\.\d+)?(e-?\d+)?$/i) # Float/exponential
15
+ Float(value).to_i
16
+ else
17
+ begin
18
+ Integer(value, 10)
19
+ rescue StandardError
20
+ nil
21
+ end
22
+ end
23
+ else
24
+ begin
25
+ Integer(value)
26
+ rescue StandardError
27
+ nil
28
+ end
29
+ end
30
+ end
31
+
32
+ # Override serialize to return Integer instead of String
33
+ def self.serialize(value)
34
+ return nil if value.nil?
35
+
36
+ cast(value)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,49 @@
1
+ module Lutaml
2
+ module Model
3
+ module Type
4
+ class String < Value
5
+ def self.cast(value)
6
+ return nil if value.nil?
7
+
8
+ value.to_s
9
+ end
10
+
11
+ # xs:string format
12
+ def to_xml
13
+ value&.to_s
14
+ end
15
+
16
+ # JSON string
17
+ def to_json(*_args)
18
+ value
19
+ end
20
+
21
+ # YAML string
22
+ def to_yaml
23
+ value
24
+ end
25
+
26
+ # TOML string
27
+ def to_toml
28
+ value&.to_s
29
+ end
30
+
31
+ def self.from_xml(value)
32
+ cast(value)
33
+ end
34
+
35
+ def self.from_json(value)
36
+ cast(value)
37
+ end
38
+
39
+ def self.from_yaml(value)
40
+ cast(value)
41
+ end
42
+
43
+ def self.from_toml(value)
44
+ cast(value)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ require "time"
2
+
3
+ module Lutaml
4
+ module Model
5
+ module Type
6
+ class Time < Value
7
+ def self.cast(value)
8
+ return nil if value.nil?
9
+
10
+ case value
11
+ when ::Time then value
12
+ when ::DateTime then value.to_time
13
+ else ::Time.parse(value.to_s)
14
+ end
15
+ rescue ArgumentError
16
+ nil
17
+ end
18
+
19
+ def self.serialize(value)
20
+ return nil if value.nil?
21
+
22
+ value = cast(value)
23
+ # value&.strftime("%Y-%m-%dT%H:%M:%S%:z")
24
+ value&.iso8601
25
+ end
26
+
27
+ # # xs:time format (HH:MM:SS.mmm±HH:MM)
28
+ # def to_xml
29
+ # value&.strftime("%H:%M:%S%:z")
30
+ # end
31
+
32
+ # # ISO8601 time format
33
+ # def to_json
34
+ # value&.iso8601
35
+ # end
36
+
37
+ # # YAML timestamp format (native)
38
+ # def to_yaml
39
+ # value
40
+ # end
41
+
42
+ # # TOML time format (HH:MM:SS.mmm)
43
+ # def to_toml
44
+ # value&.strftime("%H:%M:%S.%L")
45
+ # end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,16 +1,48 @@
1
+ require "time"
2
+
1
3
  module Lutaml
2
4
  module Model
3
5
  module Type
4
- # Time representation without date
5
- class TimeWithoutDate
6
+ class TimeWithoutDate < Value
7
+ # TODO: we probably want to do something like this because using
8
+ # Time.parse will set the date to today.
9
+ #
10
+ # time = ::Time.parse(value.to_s)
11
+ # ::Time.new(1, 1, 1, time.hour, time.min, time.sec)
12
+
6
13
  def self.cast(value)
7
- return if value.nil?
14
+ return nil if value.nil?
8
15
 
9
- ::Time.parse(value.to_s)
16
+ case value
17
+ when ::Time then value
18
+ else ::Time.parse(value.to_s)
19
+ end
20
+ rescue ArgumentError
21
+ nil
10
22
  end
11
23
 
12
24
  def self.serialize(value)
13
- value.strftime("%H:%M:%S")
25
+ return nil if value.nil?
26
+
27
+ value = cast(value)
28
+ value.strftime("%H:%M:%S") # Format as HH:MM:SS
29
+ end
30
+
31
+ # Instance methods for format-specific serialization
32
+ def to_xml
33
+ self.class.serialize(value)
34
+ end
35
+
36
+ def to_json(*_args)
37
+ self.class.serialize(value)
38
+ end
39
+
40
+ def to_yaml
41
+ self.class.serialize(value)
42
+ end
43
+
44
+ def to_toml
45
+ value.strftime("%H:%M:%S.%L") # Include milliseconds for TOML
14
46
  end
15
47
  end
16
48
  end
@@ -0,0 +1,52 @@
1
+ require_relative "../config"
2
+
3
+ module Lutaml
4
+ module Model
5
+ module Type
6
+ # Base class for all value types
7
+ class Value
8
+ attr_reader :value
9
+
10
+ def initialize(value)
11
+ @value = self.class.cast(value)
12
+ end
13
+
14
+ def self.cast(value)
15
+ return nil if value.nil?
16
+
17
+ value
18
+ end
19
+
20
+ def self.serialize(value)
21
+ return nil if value.nil?
22
+
23
+ new(value).to_s
24
+ end
25
+
26
+ # Instance methods for serialization
27
+ def to_s
28
+ value.to_s
29
+ end
30
+
31
+ # Format-specific instance methods
32
+ ::Lutaml::Model::Config::AVAILABLE_FORMATS.each do |format|
33
+ define_method(:"to_#{format}") do
34
+ value
35
+ end
36
+ end
37
+
38
+ # Class-level format conversion
39
+ def self.from_format(value, format)
40
+ new(send(:"from_#{format}", value))
41
+ end
42
+
43
+ # Default format-specific class methods that can be overridden
44
+ ::Lutaml::Model::Config::AVAILABLE_FORMATS.each do |format|
45
+ define_singleton_method(:"from_#{format}") do |value|
46
+ cast(value)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,136 +1,72 @@
1
- require "date"
2
- require "bigdecimal"
3
-
4
1
  module Lutaml
5
2
  module Model
6
3
  module Type
7
- # This module provides a set of methods to cast and serialize values
8
-
9
- # TODO: Make Boolean a separate class
10
-
11
- %w(
12
- String
13
- Integer
14
- Float
15
- Date
16
- Time
17
- Boolean
18
- Decimal
19
- Hash
20
- ).each do |t|
21
- class_eval <<~HEREDOC, __FILE__, __LINE__ + 1
22
- class #{t} # class Integer
23
- def self.cast(value) # def self.cast(value)
24
- return if value.nil? # return if value.nil?
25
- #
26
- Type.cast(value, #{t}) # Type.cast(value, Integer)
27
- end # end
28
-
29
- def self.serialize(value) # def self.serialize(value)
30
- return if value.nil? # return if value.nil?
31
- #
32
- Type.serialize(value, #{t}) # Type.serialize(value, Integer)
33
- end # end
34
- end # end
35
- HEREDOC
36
- end
37
-
38
- UUID_REGEX = /\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\z/
39
-
40
- def self.cast(value, type)
41
- return if value.nil?
42
-
43
- case type.to_s.split("::").last
44
- when "String"
45
- value.to_s
46
- when "Integer"
47
- value.to_i
48
- when "Float"
49
- value.to_f
50
- when "Date"
51
- begin
52
- ::Date.parse(value.to_s)
53
- rescue ArgumentError
54
- nil
55
- end
56
- when "DateTime"
57
- DateTime.cast(value)
58
- when "Time"
59
- ::Time.parse(value.to_s)
60
- when "TimeWithoutDate"
61
- TimeWithoutDate.cast(value)
62
- when "Boolean"
63
- to_boolean(value)
64
- when "Decimal"
65
- unless defined?(BigDecimal)
66
- raise Lutaml::Model::TypeNotEnabledError.new("Decimal", value)
4
+ TYPE_CODES = {
5
+ string: "Lutaml::Model::Type::String",
6
+ integer: "Lutaml::Model::Type::Integer",
7
+ float: "Lutaml::Model::Type::Float",
8
+ decimal: "Lutaml::Model::Type::Decimal",
9
+ date: "Lutaml::Model::Type::Date",
10
+ time: "Lutaml::Model::Type::Time",
11
+ date_time: "Lutaml::Model::Type::DateTime",
12
+ time_without_date: "Lutaml::Model::Type::TimeWithoutDate",
13
+ boolean: "Lutaml::Model::Type::Boolean",
14
+ hash: "Lutaml::Model::Type::Hash",
15
+ }.freeze
16
+
17
+ class << self
18
+ def register_builtin_types
19
+ TYPE_CODES.each do |type_name, type_class|
20
+ register(type_name, const_get(type_class))
67
21
  end
68
-
69
- BigDecimal(value.to_s)
70
- when "Hash"
71
- normalize_hash(Hash(value))
72
- else
73
- value
74
22
  end
75
- end
76
-
77
- def self.serialize(value, type)
78
- return if value.nil?
79
23
 
80
- case type.to_s.split("::").last
81
- when "Date"
82
- value.iso8601
83
- when "DateTime"
84
- DateTime.serialize(value)
85
- when "Integer"
86
- value.to_i
87
- when "Float"
88
- value.to_f
89
- when "Boolean"
90
- to_boolean(value)
91
- when "Decimal"
92
- unless defined?(BigDecimal)
93
- raise Lutaml::Model::TypeNotEnabledError.new("Decimal", value)
24
+ def register(type_name, type_class)
25
+ unless type_class < Value
26
+ raise TypeError,
27
+ "class '#{type_class}' is not a valid Lutaml::Model::Type::Value"
94
28
  end
95
29
 
96
- value.to_s("F")
97
- when "Hash"
98
- Hash(value)
99
- else
100
- value.to_s
30
+ @registry ||= {}
31
+ @registry[type_name.to_sym] = type_class
101
32
  end
102
- end
103
33
 
104
- def self.to_boolean(value)
105
- if value == true || value.to_s =~ (/^(true|t|yes|y|1)$/i)
106
- return true
107
- end
34
+ def lookup(type_name)
35
+ @registry ||= {}
36
+ klass = @registry[type_name.to_sym]
108
37
 
109
- if value == false || value.nil? || value.to_s =~ (/^(false|f|no|n|0)$/i)
110
- return false
111
- end
38
+ raise UnknownTypeError.new(type_name) unless klass
112
39
 
113
- raise ArgumentError.new("invalid value for Boolean: \"#{value}\"")
114
- end
40
+ klass
41
+ end
115
42
 
116
- def self.normalize_hash(hash)
117
- return hash["text"] if hash.keys == ["text"]
43
+ def cast(value, type)
44
+ return nil if value.nil?
118
45
 
119
- hash = hash.to_h if hash.is_a?(Lutaml::Model::MappingHash)
46
+ type.cast(value)
47
+ end
120
48
 
121
- hash.filter_map do |key, value|
122
- next if key == "text"
49
+ def serialize(value, type)
50
+ return nil if value.nil?
123
51
 
124
- if value.is_a?(::Hash)
125
- [key, normalize_hash(value)]
126
- else
127
- [key, value]
128
- end
129
- end.to_h
52
+ type.serialize(value)
53
+ end
130
54
  end
131
55
  end
132
56
  end
133
57
  end
134
58
 
135
- require_relative "type/time_without_date"
59
+ # Register built-in types
60
+ require_relative "type/value"
61
+ require_relative "type/string"
62
+ require_relative "type/integer"
63
+ require_relative "type/float"
64
+ require_relative "type/date"
65
+ require_relative "type/time"
136
66
  require_relative "type/date_time"
67
+ require_relative "type/time_without_date"
68
+ require_relative "type/boolean"
69
+ require_relative "type/decimal"
70
+ require_relative "type/hash"
71
+
72
+ Lutaml::Model::Type.register_builtin_types
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- VERSION = "0.3.24"
5
+ VERSION = "0.3.25"
6
6
  end
7
7
  end
@@ -39,6 +39,8 @@ module Lutaml
39
39
  )
40
40
  add_namespace_prefix(prefix)
41
41
 
42
+ element_name = "#{element_name}_" if respond_to?(element_name)
43
+
42
44
  if block_given?
43
45
  public_send(element_name, attributes) do
44
46
  xml.parent.namespace = nil if prefix.nil? && !prefix_unset
@@ -54,7 +56,8 @@ module Lutaml
54
56
  element = element.xml.parent
55
57
  end
56
58
 
57
- element << text.to_s
59
+ text_node = ::Nokogiri::XML::Text.new(text.to_s, element)
60
+ element.add_child(text_node)
58
61
  end
59
62
 
60
63
  def add_namespace_prefix(prefix)
@@ -64,7 +67,7 @@ module Lutaml
64
67
  end
65
68
 
66
69
  def method_missing(method_name, *args, &block)
67
- if block
70
+ if block_given?
68
71
  xml.public_send(method_name, *args, &block)
69
72
  else
70
73
  xml.public_send(method_name, *args)