datacaster 3.1.0 → 3.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c42f42112214378de25b126640a7bb578532c1db0ac9fbb73914ef3c08db76e2
4
- data.tar.gz: 0abba877a155d717b0aa2cb605c9214789c839b381492984cb277a1523c5a7a1
3
+ metadata.gz: 22f1741420c172f91fba9bf20a341a785f609a7e0132e74bcd3a07e6069eaca4
4
+ data.tar.gz: 641fb863b7a40931f481d066e09062cddff1a4e3ff642d5981dacf9bfaa036eb
5
5
  SHA512:
6
- metadata.gz: 4b07733981e971af666cf9a7688cd35f4a32b80eb2e4a53505620425027f5fdd963c7c63717f6888fe700df4ef6c5eb175a07aac7183cb0df29dd1e8b97fe446
7
- data.tar.gz: a596b40d1ebff4e8abc455bdde09c01b0f1499a35cee44daca329885277448cbe6f66268d568a091fa78e83e0da7adf9d9cb09df0c5711d4bc3243d3b909a886
6
+ metadata.gz: 2a3573aac6a44ef0a5849da04325c9089119ad529cc6f6384d18bb6dda97f66358081c27d1fc260d95f7adaec5937bda7769cd9207ea9be6b01f2547f4425659
7
+ data.tar.gz: '04765854fbe156b3418728d4d2392b78ce0837ead8e1e72b76a51d55e6227bb68eebf8a98e672c924205bbe731610f21c72a1be355c51c2f014886ab160efdb7'
data/README.md CHANGED
@@ -32,12 +32,12 @@ It is currently used in production in several projects (mainly as request parame
32
32
  - [`integer32(error_key = nil)`](#integer32error_key--nil)
33
33
  - [`non_empty_string(error_key = nil)`](#non_empty_stringerror_key--nil)
34
34
  - [Special types](#special-types)
35
- - [`absent(error_key = nil)`](#absenterror_key--nil)
35
+ - [`absent(error_key = nil, on: nil)`](#absenterror_key--nil-on-nil)
36
36
  - [`any(error_key = nil)`](#anyerror_key--nil)
37
37
  - [`default(default_value, on: nil)`](#defaultdefault_value-on-nil)
38
38
  - [`merge_message_keys(*keys)`](#merge_message_keyskeys)
39
39
  - [`must_be(klass, error_key = nil)`](#must_beklass-error_key--nil)
40
- - [`optional(base)`](#optionalbase)
40
+ - [`optional(base, on: nil)`](#optionalbase-on-nil)
41
41
  - [`pass`](#pass)
42
42
  - [`pass_if(base)`](#pass_ifbase)
43
43
  - [`pick(key)`](#pickkey)
@@ -56,6 +56,8 @@ It is currently used in production in several projects (mainly as request parame
56
56
  - [`try(error_key = nil, catched_exception:) { |value| ... }`](#tryerror_key--nil-catched_exception--value--)
57
57
  - [`validate(active_model_validations, name = 'Anonymous')`](#validateactive_model_validations-name--anonymous)
58
58
  - [`compare(reference_value, error_key = nil)`](#comparereference_value-error_key--nil)
59
+ - [`included_in(*reference_values, error_key: nil)`](#included_inreference_values-error_key-nil)
60
+ - [`relate(left, op, right, error_key: nil)`](#relateleft-op-right-error_key-nil)
59
61
  - [`transform { |value| ... }`](#transform--value--)
60
62
  - [`transform_if_present { |value| ... }`](#transform_if_present--value--)
61
63
  - [Array schemas](#array-schemas)
@@ -175,10 +177,10 @@ array = Datacaster.schema { array }
175
177
  array.(nil)
176
178
 
177
179
  # In this README
178
- #=> Datacaster::ErrorResult(['should be an array'])
180
+ # => Datacaster::ErrorResult(['should be an array'])
179
181
 
180
182
  # In reality
181
- #=> <Datacaster::ErrorResult([#<Datacaster::I18nValues::Key(.array, datacaster.errors.array) {:value=>nil}>])>
183
+ # => <Datacaster::ErrorResult([#<Datacaster::I18nValues::Key(.array, datacaster.errors.array) {:value=>nil}>])>
182
184
  ```
183
185
 
184
186
  See [section on i18n](#internationalization-i18n) for details.
@@ -502,9 +504,16 @@ Returns ValidResult if and only if provided value is a string and is not empty.
502
504
 
503
505
  ### Special types
504
506
 
505
- #### `absent(error_key = nil)`
507
+ #### `absent(error_key = nil, on: nil)`
506
508
 
507
- Returns ValidResult if and only if provided value is `Datacaster.absent` (this is singleton instance). Relevant only for hash schemas (see below). Doesn't transform the value.
509
+ Returns ValidResult if and only if provided value is absent. Relevant only for hash schemas (see below). Transforms the value to `Datacaster.absent`.
510
+
511
+ The value is considered absent:
512
+
513
+ * if the value is `Datacaster.absent` (`on` is disregarded in such case)
514
+ * if `on` is set to a method name to which the value responds and yields truthy
515
+
516
+ Set `on` to `:nil?`, `:empty?` or similar method names.
508
517
 
509
518
  I18n keys: `error_key`, `'.absent'`, `'datacaster.errors.absent'`.
510
519
 
@@ -636,18 +645,25 @@ Returns ValidResult if and only if the value `#is_a?(klass)`. Doesn't transform
636
645
 
637
646
  I18n keys: `error_key`, `'.must_be'`, `'datacaster.errors.must_be'`. Adds `reference` i18n variable, setting it to `klass.name`.
638
647
 
639
- #### `optional(base)`
648
+ #### `optional(base, on: nil)`
640
649
 
641
- Returns ValidResult if and only if the value is either `Datacaster.absent` or passes `base` validation. See below documentation on hash schemas for details on `Datacaster.absent`.
650
+ Returns ValidResult if and only if the value is either absent or passes `base` validation. In the value is absent, transforms it to the `Datacaster.absent`. Otherwise, returns `base` result.
651
+
652
+ Value is considered absent:
653
+
654
+ * if the value is `Datacaster.absent` (`on` is disregarded in such case)
655
+ * if `on` is set to a method name to which the value responds and yields truthy
656
+
657
+ Set `on` to `:nil?`, `:empty?` or similar method names.
642
658
 
643
659
  ```ruby
644
660
  item_with_optional_price =
645
- Datacaster.schema do
646
- hash_schema(
647
- name: string,
648
- price: optional(float)
649
- )
650
- end
661
+ Datacaster.schema do
662
+ hash_schema(
663
+ name: string,
664
+ price: optional(float)
665
+ )
666
+ end
651
667
 
652
668
  item_with_optional_price.(name: "Book", price: 1.23)
653
669
  # => Datacaster::ValidResult({:name=>"Book", :price=>1.23})
@@ -868,8 +884,6 @@ I18n is performed by ActiveModel gem.
868
884
 
869
885
  #### `compare(reference_value, error_key = nil)`
870
886
 
871
- This type is the way to ensure some value in your schema is some predefined "constant".
872
-
873
887
  Returns ValidResult if and only if `reference_value` equals value.
874
888
 
875
889
  ```ruby
@@ -883,6 +897,50 @@ agreed_with_tos =
883
897
 
884
898
  I18n keys: `error_key`, `'.compare'`, `'datacaster.errors.compare'`. Adds `reference` i18n variable, setting it to `reference_value.to_s`.
885
899
 
900
+ #### `included_in(*reference_values, error_key: nil)`
901
+
902
+ Returns ValidResult if and only if `reference_values.include?` the value.
903
+
904
+ I18n keys: `error_key`, `'.included_in'`, `'datacaster.errors.included_in'`. Adds `reference` i18n variable, setting it to `reference_values.map(&:to_s).join(', ')`.
905
+
906
+ #### `relate(left, op, right, error_key: nil)`
907
+
908
+ Returns ValidResult if and only if `left`, `right` and `op` returns valid result. Doesn't transform the value.
909
+
910
+ Use `relate` to check relations between object keys:
911
+
912
+ ```ruby
913
+ ordered =
914
+ # Check that hash[:a] < hash[:b]
915
+ Datacaster.schema do
916
+ transform_to_hash(
917
+ a: relate(:a, :<, :b) & pick(:a),
918
+ b: pick(:b)
919
+ )
920
+ end
921
+
922
+ ordered.(a: 1, b: 2)
923
+ # => Datacaster::ValidResult({:a=>1, :b=>2})
924
+
925
+ ordered.(a: 2, b: 1)
926
+ # => Datacaster::ErrorResult({:a=>["a should be < b"]})
927
+
928
+ ordered.({})
929
+ # => Datacaster::ErrorResult({:a=>["a should be < b"]})
930
+ ```
931
+
932
+ Notice that shortcut definitions are available (illustrated in the example above) for the `relate` caster:
933
+
934
+ * `:key` provided as 'left' or 'right' argument is exactly the same as `pick(:key)` (works for a string, a symbol or an integer)
935
+ * `:method` provided as 'op' argument is exactly the same as `check { |(l, r)| l.respond_to?(method) && l.public_send(method, r) }` (works for a string or a symbol)
936
+
937
+ Formally, `relate(left, op, right, error_key: error_key)` will:
938
+
939
+ * call the `left` caster with the original value, return the result unless it's valid
940
+ * call the `right` caster with the original value, return the result unless it's valid
941
+ * call the `op` caster with the `[left_result, right_result]`, return the result unless it's valid
942
+ * return the original value as valid result
943
+
886
944
  #### `transform { |value| ... }`
887
945
 
888
946
  Always returns ValidResult. Transforms the value: returns whatever the block has returned.
@@ -1025,7 +1083,7 @@ restricted_params.(username: "test", is_admin: nil)
1025
1083
 
1026
1084
  More practical case is to include `absent` validator in logical expressions, e.g. `something: absent | string`. If `something` is set to `nil`, this validation will fail, which could be the desired (and hardly achieved by any other validation framework) behavior.
1027
1085
 
1028
- Also, see documentation for [`optional(base)`](#optionalbase) and [`optional_param(base)`](#optional_parambase). If some value becomes `Datacaster.absent` in its chain of validations-transformations, it is removed from the resultant hash (on the same stage where the lack of extra/unchecked keys in the hash is validated):
1086
+ Also, see documentation for [`optional(base)`](#optionalbase-on-nil) and [`optional_param(base)`](#optional_parambase). If some value becomes `Datacaster.absent` in its chain of validations-transformations, it is removed from the resultant hash (on the same stage where the lack of extra/unchecked keys in the hash is validated):
1029
1087
 
1030
1088
  ```ruby
1031
1089
  person =
@@ -11,10 +11,12 @@ en:
11
11
  empty: should not be empty
12
12
  float: is not a float
13
13
  hash_value: is not a hash
14
+ included_in: is not one of %{reference}
14
15
  integer: is not an integer
15
16
  integer32: is not a 32-bit integer
16
17
  iso8601: is not a string with ISO-8601 date and time
17
18
  must_be: "is not %{reference}"
19
+ relate: "%{left} should be %{op} %{right}"
18
20
  responds_to: "does not respond to %{reference}"
19
21
  string: is not a string
20
22
  to_boolean: does not look like a boolean
@@ -17,7 +17,7 @@ module Datacaster
17
17
  if right_result.valid?
18
18
  left_result
19
19
  else
20
- Datacaster.ErrorResult(self.class.merge_errors(left_result.raw_errors, right_result.raw_errors))
20
+ Datacaster.ErrorResult(Utils.merge_errors(left_result.raw_errors, right_result.raw_errors))
21
21
  end
22
22
  end
23
23
  end
@@ -1,97 +1,5 @@
1
1
  module Datacaster
2
2
  class Base
3
- def self.merge_errors(left, right)
4
- add_error_to_base = ->(hash, error) {
5
- hash[:base] ||= []
6
- hash[:base] = merge_errors(hash[:base], error)
7
- hash
8
- }
9
-
10
- return [] if left.nil? && right.nil?
11
- return right if left.nil?
12
- return left if right.nil?
13
-
14
- result = case [left.class, right.class]
15
- when [Array, Array]
16
- left | right
17
- when [Array, Hash]
18
- add_error_to_base.(right, left)
19
- when [Hash, Hash]
20
- (left.keys | right.keys).map do |k|
21
- [k, merge_errors(left[k], right[k])]
22
- end.to_h
23
- when [Hash, Array]
24
- add_error_to_base.(left, right)
25
- else
26
- raise ArgumentError.new("Expected failures to be Arrays or Hashes, left: #{left.inspect}, right: #{right.inspect}")
27
- end
28
-
29
- result
30
- end
31
-
32
- def &(other)
33
- AndNode.new(self, other)
34
- end
35
-
36
- def |(other)
37
- OrNode.new(self, other)
38
- end
39
-
40
- def *(other)
41
- AndWithErrorAggregationNode.new(self, other)
42
- end
43
-
44
- def cast_errors(error_caster)
45
- ContextNodes::ErrorsCaster.new(self, error_caster)
46
- end
47
-
48
- def then(other)
49
- ThenNode.new(self, DefinitionDSL.expand(other))
50
- end
51
-
52
- def with_context(context)
53
- unless context.is_a?(Hash)
54
- raise "with_context expected Hash as argument, got #{context.inspect} instead"
55
- end
56
- ContextNodes::UserContext.new(self, context)
57
- end
58
-
59
- def call(object)
60
- call_with_runtime(object, Runtimes::Base.new)
61
- end
62
-
63
- def call_with_runtime(object, runtime)
64
- result = cast(object, runtime: runtime)
65
- unless result.is_a?(Result)
66
- raise RuntimeError.new("Caster should've returned Datacaster::Result, but returned #{result.inspect} instead")
67
- end
68
- result
69
- end
70
-
71
- def with_runtime(runtime)
72
- ->(object) do
73
- call_with_runtime(object, runtime)
74
- end
75
- end
76
-
77
- def i18n_key(*keys, **args)
78
- ContextNodes::I18n.new(self, I18nValues::Key.new(keys, args))
79
- end
80
-
81
- def i18n_map_keys(mapping)
82
- ContextNodes::I18nKeysMapper.new(self, mapping)
83
- end
84
-
85
- def i18n_scope(scope, **args)
86
- ContextNodes::I18n.new(self, I18nValues::Scope.new(scope, args))
87
- end
88
-
89
- def i18n_vars(vars)
90
- ContextNodes::I18n.new(self, I18nValues::Scope.new(nil, vars))
91
- end
92
-
93
- def inspect
94
- "#<Datacaster::Base>"
95
- end
3
+ include Mixin
96
4
  end
97
5
  end
@@ -9,13 +9,13 @@ module Datacaster
9
9
  def cast(object, runtime:)
10
10
  result = Runtimes::Base.(runtime, @cast, object)
11
11
 
12
- raise TypeError.new("Either Datacaster::Result or Dry::Monads::Result " \
13
- "should be returned from cast block") unless [Datacaster::Result, Dry::Monads::Result].any? { |k| result.is_a?(k) }
14
-
15
- if result.is_a?(Dry::Monads::Result)
12
+ if defined?(Dry::Monads::Result) && result.is_a?(Dry::Monads::Result)
16
13
  result = result.success? ? Datacaster.ValidResult(result.value!) : Datacaster.ErrorResult(result.failure)
17
14
  end
18
15
 
16
+ raise TypeError.new("Either Datacaster::Result or Dry::Monads::Result " \
17
+ "should be returned from cast block") unless result.is_a?(Datacaster::Result)
18
+
19
19
  result
20
20
  end
21
21
 
@@ -45,9 +45,9 @@ module Datacaster
45
45
  end
46
46
  else
47
47
  if key.is_a?(Array)
48
- errors = self.class.merge_errors(errors, key.zip(new_value.raw_errors).to_h)
48
+ errors = Utils.merge_errors(errors, key.zip(new_value.raw_errors).to_h)
49
49
  else
50
- errors = self.class.merge_errors(errors, {key => new_value.raw_errors})
50
+ errors = Utils.merge_errors(errors, {key => new_value.raw_errors})
51
51
  end
52
52
  end
53
53
  end
@@ -0,0 +1,68 @@
1
+ module Datacaster
2
+ module Mixin
3
+ def &(other)
4
+ AndNode.new(self, other)
5
+ end
6
+
7
+ def |(other)
8
+ OrNode.new(self, other)
9
+ end
10
+
11
+ def *(other)
12
+ AndWithErrorAggregationNode.new(self, other)
13
+ end
14
+
15
+ def cast_errors(error_caster)
16
+ ContextNodes::ErrorsCaster.new(self, error_caster)
17
+ end
18
+
19
+ def then(other)
20
+ ThenNode.new(self, DefinitionDSL.expand(other))
21
+ end
22
+
23
+ def with_context(context)
24
+ unless context.is_a?(Hash)
25
+ raise "with_context expected Hash as argument, got #{context.inspect} instead"
26
+ end
27
+ ContextNodes::UserContext.new(self, context)
28
+ end
29
+
30
+ def call(object)
31
+ call_with_runtime(object, Runtimes::Base.new)
32
+ end
33
+
34
+ def call_with_runtime(object, runtime)
35
+ result = cast(object, runtime: runtime)
36
+ unless result.is_a?(Result)
37
+ raise RuntimeError.new("Caster should've returned Datacaster::Result, but returned #{result.inspect} instead")
38
+ end
39
+ result
40
+ end
41
+
42
+ def with_runtime(runtime)
43
+ ->(object) do
44
+ call_with_runtime(object, runtime)
45
+ end
46
+ end
47
+
48
+ def i18n_key(*keys, **args)
49
+ ContextNodes::I18n.new(self, I18nValues::Key.new(keys, args))
50
+ end
51
+
52
+ def i18n_map_keys(mapping)
53
+ ContextNodes::I18nKeysMapper.new(self, mapping)
54
+ end
55
+
56
+ def i18n_scope(scope, **args)
57
+ ContextNodes::I18n.new(self, I18nValues::Scope.new(scope, args))
58
+ end
59
+
60
+ def i18n_vars(vars)
61
+ ContextNodes::I18n.new(self, I18nValues::Scope.new(nil, vars))
62
+ end
63
+
64
+ def inspect
65
+ "#<Datacaster::Base>"
66
+ end
67
+ end
68
+ end
@@ -67,10 +67,20 @@ module Datacaster
67
67
 
68
68
  # 'Meta' types
69
69
 
70
- def absent(error_key = nil)
70
+ def absent(error_key = nil, on: nil)
71
71
  error_keys = ['.absent', 'datacaster.errors.absent']
72
72
  error_keys.unshift(error_key) if error_key
73
- check { |x| x == Datacaster.absent }.i18n_key(*error_keys)
73
+
74
+ cast do |x|
75
+ if x == Datacaster.absent ||
76
+ (!on.nil? && x.respond_to?(on) && x.public_send(on))
77
+ Datacaster.ValidResult(Datacaster.absent)
78
+ else
79
+ Datacaster.ErrorResult(
80
+ I18nValues::Key.new(error_keys, value: x)
81
+ )
82
+ end
83
+ end
74
84
  end
75
85
 
76
86
  def any(error_key = nil)
@@ -82,7 +92,7 @@ module Datacaster
82
92
  def default(value, on: nil)
83
93
  transform do |x|
84
94
  if x == Datacaster.absent ||
85
- (on && x.respond_to?(on) && x.public_send(on))
95
+ (!on.nil? && x.respond_to?(on) && x.public_send(on))
86
96
  value
87
97
  else
88
98
  x
@@ -94,6 +104,52 @@ module Datacaster
94
104
  transform { value }
95
105
  end
96
106
 
107
+ # min_amount: has_relation(:min_amount, :>, :max_amount)
108
+
109
+ def relate(left, op, right, error_key: nil)
110
+ error_keys = ['.relate', 'datacaster.errors.relate']
111
+ additional_vars = {}
112
+
113
+ {left: left, op: op, right: right}.each do |k, v|
114
+ if [String, Symbol, Integer].any? { |c| v.is_a?(c) }
115
+ additional_vars[k] = v
116
+ elsif !Datacaster.instance?(v)
117
+ raise RuntimeError, "expected #{k} to be String, Symbol, Integer or Datacaster::Base, but got #{v.inspect}", caller
118
+ end
119
+ end
120
+
121
+ if op.is_a?(Integer)
122
+ raise RuntimeError, "expected op to be String, Symbol or Datacaster::Base, but got #{op.inspect}", caller
123
+ end
124
+
125
+ if [left, op, right].none? { |x| Datacaster.instance?(x) }
126
+ error_keys.unshift(".#{left}.#{op}.#{right}")
127
+ end
128
+ error_keys.unshift(error_key) if error_key
129
+
130
+ left = pick(left) unless Datacaster.instance?(left)
131
+ right = pick(right) unless Datacaster.instance?(right)
132
+ op_caster = op
133
+ unless Datacaster.instance?(op_caster)
134
+ op_caster = check { |(l, r)| l.respond_to?(op) && l.public_send(op, r) }
135
+ end
136
+
137
+ cast do |value|
138
+ left_result = left.(value)
139
+ next left_result unless left_result.valid?
140
+ i18n_var!(:left, left_result.value) unless additional_vars.key?(:left)
141
+
142
+ right_result = right.(value)
143
+ next right_result unless right_result.valid?
144
+ i18n_var!(:right, right_result.value) unless additional_vars.key?(:right)
145
+
146
+ result = op_caster.([left_result.value, right_result.value])
147
+ next Datacaster.ErrorResult([I18nValues::Key.new(error_keys)]) unless result.valid?
148
+
149
+ Datacaster.ValidResult(value)
150
+ end.i18n_vars(additional_vars)
151
+ end
152
+
97
153
  def remove
98
154
  transform { Datacaster.absent }
99
155
  end
@@ -153,8 +209,16 @@ module Datacaster
153
209
  check { |x| x.is_a?(klass) }.i18n_key(*error_keys, reference: klass.name)
154
210
  end
155
211
 
156
- def optional(base)
157
- absent | base
212
+ def optional(base, on: nil)
213
+ return absent | base if on == nil
214
+ cast do |x|
215
+ if x == Datacaster.absent ||
216
+ (!on.nil? && x.respond_to?(on) && x.public_send(on))
217
+ Datacaster.ValidResult(Datacaster.absent)
218
+ else
219
+ base.(x)
220
+ end
221
+ end
158
222
  end
159
223
 
160
224
  # Strict types
@@ -187,13 +251,19 @@ module Datacaster
187
251
  def hash_value(error_key = nil)
188
252
  error_keys = ['.hash_value', 'datacaster.errors.hash_value']
189
253
  error_keys.unshift(error_key) if error_key
190
- check(error_key) { |x| x.is_a?(Hash) }
254
+ check { |x| x.is_a?(Hash) }.i18n_key(*error_keys)
191
255
  end
192
256
 
193
257
  def hash_with_symbolized_keys(error_key = nil)
194
258
  hash_value(error_key) & transform { |x| x.symbolize_keys }
195
259
  end
196
260
 
261
+ def included_in(*values, error_key: nil)
262
+ error_keys = ['.included_in', 'datacaster.errors.included_in']
263
+ error_keys.unshift(error_key) if error_key
264
+ check { |x| values.include?(x) }.i18n_key(*error_keys, reference: values.map(&:to_s).join(', '))
265
+ end
266
+
197
267
  def integer(error_key = nil)
198
268
  error_keys = ['.integer', 'datacaster.errors.integer']
199
269
  error_keys.unshift(error_key) if error_key
@@ -0,0 +1,34 @@
1
+ module Datacaster
2
+ module Utils
3
+ extend self
4
+
5
+ def merge_errors(left, right)
6
+ add_error_to_base = ->(hash, error) {
7
+ hash[:base] ||= []
8
+ hash[:base] = merge_errors(hash[:base], error)
9
+ hash
10
+ }
11
+
12
+ return [] if left.nil? && right.nil?
13
+ return right if left.nil?
14
+ return left if right.nil?
15
+
16
+ result = case [left.class, right.class]
17
+ when [Array, Array]
18
+ left | right
19
+ when [Array, Hash]
20
+ add_error_to_base.(right, left)
21
+ when [Hash, Hash]
22
+ (left.keys | right.keys).map do |k|
23
+ [k, merge_errors(left[k], right[k])]
24
+ end.to_h
25
+ when [Hash, Array]
26
+ add_error_to_base.(left, right)
27
+ else
28
+ raise ArgumentError.new("Expected failures to be Arrays or Hashes, left: #{left.inspect}, right: #{right.inspect}")
29
+ end
30
+
31
+ result
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module Datacaster
2
- VERSION = "3.1.0"
2
+ VERSION = "3.1.2"
3
3
  end
data/lib/datacaster.rb CHANGED
@@ -24,6 +24,10 @@ module Datacaster
24
24
  Datacaster::Absent.instance
25
25
  end
26
26
 
27
+ def instance?(object)
28
+ object.is_a?(Mixin)
29
+ end
30
+
27
31
  private
28
32
 
29
33
  def build_schema(i18n_scope: nil, &block)
@@ -31,7 +35,7 @@ module Datacaster
31
35
 
32
36
  datacaster = DefinitionDSL.eval(&block)
33
37
 
34
- unless datacaster.is_a?(Base)
38
+ unless Datacaster.instance?(datacaster)
35
39
  raise "Datacaster instance should be returned from a block (e.g. result of 'hash_schema(...)' call)"
36
40
  end
37
41
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datacaster
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eugene Zolotarev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-02 00:00:00.000000000 Z
11
+ date: 2023-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -150,6 +150,7 @@ files:
150
150
  - lib/datacaster/i18n_values/key.rb
151
151
  - lib/datacaster/i18n_values/scope.rb
152
152
  - lib/datacaster/message_keys_merger.rb
153
+ - lib/datacaster/mixin.rb
153
154
  - lib/datacaster/or_node.rb
154
155
  - lib/datacaster/predefined.rb
155
156
  - lib/datacaster/result.rb
@@ -162,6 +163,7 @@ files:
162
163
  - lib/datacaster/then_node.rb
163
164
  - lib/datacaster/transformer.rb
164
165
  - lib/datacaster/trier.rb
166
+ - lib/datacaster/utils.rb
165
167
  - lib/datacaster/validator.rb
166
168
  - lib/datacaster/version.rb
167
169
  homepage: https://github.com/EugZol/datacaster