rice_bubble 0.1.2 → 0.2.1

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: 5ff1a10fe0388c60a178246ee4c45a005292355ec741b9f175b56c8ba393b060
4
- data.tar.gz: 35c94ec3a32ea7187b031eaf4341c59ad4a55649510bece671a52b480a10c2c5
3
+ metadata.gz: ab58ee2fd09eed3c5031ff9679f326004055f2d328e923386d7ba8590fb9e9dc
4
+ data.tar.gz: bdc33392f0718f127d631c19c18737630a319edcdd25016afd29d3bed1cc459d
5
5
  SHA512:
6
- metadata.gz: 1eb7c799044b2d70f6f13a2066d175b4ff09965b19b11d91c36493509d579e6e9ea6ebbeb4cfe1d897faf5aded93bc74ea5e955db81fc396bda9a292689537c3
7
- data.tar.gz: 9bd2f3aa7f5c6c70ebb5c8afc1d2ca2d4ee95e2978c5491c5a6a1e225ce31c4f3ea5e908a933fa48d74e1cea4d437e131f1718c5e0c496df7c7bf0f99196699b
6
+ metadata.gz: 9ac2ed7ffe7a9ce1e77f8d8456c5ce59acc30d8f60cd8ba7fe8785e58ece18c2d22e98ed7e87b9bd7769326b2a9a9759f35283263b671f3313e0f81d0a7533fa
7
+ data.tar.gz: d55cec7b53844644fd04e76fec038f1abf7ad0cf59170e38e85ce73baabff0c4fe58025fe1e71ec496fa7557e3aa4353d003aa55924b9d3bd837d16374a409e8
data/.rubocop.yml CHANGED
@@ -13,7 +13,7 @@ Layout/FirstHashElementIndentation:
13
13
  Layout/LineLength:
14
14
  Max: 80
15
15
  AllowedPatterns:
16
- - '^\s*#'
16
+ - ^\s*[#']
17
17
 
18
18
  Layout/MultilineMethodCallIndentation:
19
19
  EnforcedStyle: indented
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rice_bubble (0.1.1)
4
+ rice_bubble (0.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -12,22 +12,17 @@ module RiceBubble
12
12
  !which(value).nil?
13
13
  end
14
14
 
15
- def validate!(value, path:, **)
16
- member = which(value)
17
- return unless member.nil?
18
-
19
- expected = "one of [#{members.map(&:description).join(", ")}]"
20
- raise ValidationError,
21
- "#{path} expected #{expected} but received #{value.inspect}"
22
- end
23
-
24
- def coerce(value)
25
- which(value)&.coerce(value) || value
15
+ def call(value, path: '')
16
+ super(which(value)&.call(value, path:) || value, path:)
26
17
  end
27
18
 
28
19
  def which(value)
29
20
  members.find { |member| member.valid?(value) }
30
21
  end
22
+
23
+ def description
24
+ "one of [#{members.map(&:description).join(", ")}]"
25
+ end
31
26
  end
32
27
  end
33
28
  end
@@ -16,19 +16,11 @@ module RiceBubble
16
16
  end
17
17
  end
18
18
 
19
- def validate!(_value, coerced:, path:)
20
- coerced.each.with_index do |child, index|
21
- members.validate!(
22
- child,
23
- coerced: members.coerce(child),
24
- path: "#{path}[#{index}]"
25
- )
19
+ def call(value, path: '')
20
+ (value || []).map.with_index do |child, index|
21
+ members.call(child, path: "#{path}[#{index}]")
26
22
  end
27
23
  end
28
-
29
- def coerce(value)
30
- value.respond_to?(:to_a) ? value.to_a : value
31
- end
32
24
  end
33
25
  end
34
26
  end
@@ -11,29 +11,24 @@ module RiceBubble
11
11
  elsif object.respond_to?(name)
12
12
  object.public_send(name)
13
13
  else
14
- object[name]
14
+ object[name] || object[name.to_s]
15
15
  end
16
16
  end
17
17
 
18
- def valid?(_value)
19
- true
18
+ def valid?(value)
19
+ valid_types.any? { |t| value.is_a?(t) }
20
20
  end
21
21
 
22
- def coerce(value)
23
- value
24
- end
25
-
26
- def validate!(value, coerced:, path:)
27
- return if valid?(coerced)
28
-
29
- raise ValidationError,
30
- "#{path} expected #{description} but received #{value.inspect}"
22
+ def valid_types
23
+ [::Object]
31
24
  end
32
25
 
33
26
  def call(value, path: '')
34
- coerced = coerce(value)
35
- validate!(value, coerced:, path:)
36
- coerced
27
+ if valid?(value)
28
+ value
29
+ else
30
+ validation_error(value:, path:)
31
+ end
37
32
  end
38
33
 
39
34
  def optional
@@ -57,6 +52,10 @@ module RiceBubble
57
52
  class_or_instance
58
53
  end
59
54
  end
55
+
56
+ def validation_error(value:, path: '')
57
+ raise ValidationError.new(value:, path:, attribute: self)
58
+ end
60
59
  end
61
60
  end
62
61
  end
@@ -1,10 +1,6 @@
1
1
  module RiceBubble
2
2
  class Attributes
3
3
  class Boolean < Base
4
- def validate!(value, path:, **)
5
- super(value, coerced: value, path:)
6
- end
7
-
8
4
  def valid?(value)
9
5
  [true, false].include?(value)
10
6
  end
@@ -1,14 +1,12 @@
1
- require 'date'
2
-
3
1
  module RiceBubble
4
2
  class Attributes
5
3
  class Date < Base
6
- def valid?(value)
7
- value.respond_to?(:to_date)
4
+ def call(value, path: '')
5
+ super(value.to_date, path:)
8
6
  end
9
7
 
10
- def coerce(value)
11
- value.respond_to?(:to_date) ? value.to_date : value
8
+ def valid_types
9
+ [::Date, ::Time, ::DateTime]
12
10
  end
13
11
  end
14
12
  end
@@ -1,27 +1,12 @@
1
1
  module RiceBubble
2
2
  class Attributes
3
3
  class Datetime < Base
4
- def valid?(value)
5
- return false unless valid_datetime?(value)
6
-
7
- value.respond_to?(:to_datetime)
4
+ def call(value, path: '')
5
+ super(value, path:)
8
6
  end
9
7
 
10
- def coerce(value)
11
- return nil unless valid_datetime?(value)
12
-
13
- value.respond_to?(:to_datetime) ? value.to_datetime : value
14
- end
15
-
16
- private
17
-
18
- def valid_datetime?(value)
19
- case value
20
- when ::Time then true
21
- when ::DateTime then true
22
- when ::Date then false
23
- else value.respond_to?(:to_datetime)
24
- end
8
+ def valid_types
9
+ [::Time, ::DateTime]
25
10
  end
26
11
  end
27
12
  end
@@ -3,16 +3,20 @@ module RiceBubble
3
3
  class Integer < Number
4
4
  attr_reader :min, :max
5
5
 
6
- def valid?(value)
7
- value.is_a?(::Integer) && super
6
+ def initialize(min: nil, max: nil, **options, &)
7
+ super(**options, &)
8
+ @min = min
9
+ @max = max
10
+ end
11
+
12
+ def valid_types
13
+ [::Integer]
8
14
  end
9
15
 
10
- def coerce(value)
11
- case value
12
- when nil then nil
13
- when ::String then value.match?(/\A-?\d+\z/) ? value.to_i : value
14
- else value.respond_to?(:to_i) ? value.to_i : value
15
- end
16
+ def valid?(value)
17
+ super &&
18
+ (!min || value >= min) &&
19
+ (!max || value <= max)
16
20
  end
17
21
  end
18
22
  end
@@ -9,8 +9,12 @@ module RiceBubble
9
9
  @max = max
10
10
  end
11
11
 
12
+ def valid_types
13
+ [::Numeric]
14
+ end
15
+
12
16
  def valid?(value)
13
- value.is_a?(::Numeric) &&
17
+ super &&
14
18
  !min&.send(:>, value) &&
15
19
  !max&.send(:<, value)
16
20
  end
@@ -16,17 +16,12 @@ module RiceBubble
16
16
  end
17
17
  end
18
18
 
19
- def validate!(value, path:, **)
20
- children.each do |name, attr|
21
- child = attr.fetch(value, name)
22
- coerced = attr.coerce(child)
23
- attr.validate!(child, coerced:, path: "#{path}.#{name}")
19
+ def call(value, path: '')
20
+ children.to_h do |name, attr|
21
+ [name,
22
+ attr.call(value[name] || value[name.to_s], path: "#{path}.#{name}")]
24
23
  end
25
24
  end
26
-
27
- def coerce(value)
28
- children.map { |name, attr| attr.coerce(attr.fetch(value, name)) }
29
- end
30
25
  end
31
26
  end
32
27
  end
@@ -9,17 +9,13 @@ module RiceBubble
9
9
  end
10
10
 
11
11
  def valid?(value)
12
- value.nil? || child.valid?(child.coerce(value))
12
+ value.nil? || child.valid?(value)
13
13
  end
14
14
 
15
15
  def call(value, path: '')
16
16
  value && child.call(value, path:)
17
17
  end
18
18
 
19
- def coerce(value)
20
- value && child.coerce(value)
21
- end
22
-
23
19
  def description
24
20
  "#{child.description} (optional)"
25
21
  end
@@ -5,15 +5,15 @@ module RiceBubble
5
5
 
6
6
  def initialize(serializer, &)
7
7
  super(&)
8
- @serializer = serializer.new
8
+ @serializer = serializer
9
9
  end
10
10
 
11
11
  def valid?(value)
12
12
  serializer.valid?(value)
13
13
  end
14
14
 
15
- def validate!(value, path:, **)
16
- serializer.validate!(value, path:)
15
+ def call(value, path: '')
16
+ serializer.call(value, path:)
17
17
  end
18
18
  end
19
19
  end
@@ -10,19 +10,19 @@ module RiceBubble
10
10
  @format = format
11
11
  end
12
12
 
13
- def valid?(value)
14
- value.is_a?(::String) &&
15
- !min&.send(:>, value.length) &&
16
- !max&.send(:<, value.length) &&
17
- (!format || format.match?(value))
13
+ def valid_types
14
+ [::String, Symbol]
18
15
  end
19
16
 
20
- def call(value, path: '')
21
- super(value.to_s, path:)
17
+ def valid?(value)
18
+ super &&
19
+ !min&.send(:>, value.to_s.length) &&
20
+ !max&.send(:<, value.to_s.length) &&
21
+ (!format || format.match?(value.to_s))
22
22
  end
23
23
 
24
- def coerce(value)
25
- value.respond_to?(:to_s) ? value.to_s : value
24
+ def call(value, path: '')
25
+ super.to_s
26
26
  end
27
27
 
28
28
  def description
@@ -10,7 +10,7 @@ module RiceBubble
10
10
  def coerce(value)
11
11
  return nil unless valid_time?(value)
12
12
 
13
- value.respond_to?(:to_time) ? value.to_time : value
13
+ value
14
14
  end
15
15
 
16
16
  private
@@ -11,7 +11,7 @@ module RiceBubble
11
11
  self.class.new(object_to_serialize).call(path:)
12
12
  elsif object
13
13
  self.class.attributes.map do |name, attr|
14
- attr.call(fetch(name), path: path || self.class.name)
14
+ attr.call(fetch(name), path: "#{path || self.class.name}.#{name}")
15
15
  end
16
16
  else
17
17
  raise ArgumentError, 'no object to serialize'
@@ -32,23 +32,6 @@ module RiceBubble
32
32
  end
33
33
  end
34
34
 
35
- def validate!(object, path: '', **)
36
- path = self.class.name if path.empty?
37
-
38
- self.class.attributes.each do |name, attr|
39
- value = attr.fetch(object, name)
40
- attr.validate!(
41
- value,
42
- coerced: attr.coerce(value),
43
- path: "#{path}.#{name}"
44
- )
45
- end
46
- end
47
-
48
- def coerce(object)
49
- object
50
- end
51
-
52
35
  class << self
53
36
  def call(object = nil, ...)
54
37
  new(object).call(...)
@@ -1,3 +1,3 @@
1
1
  module RiceBubble
2
- VERSION = '0.1.2'.freeze
2
+ VERSION = '0.2.1'.freeze
3
3
  end
data/lib/rice_bubble.rb CHANGED
@@ -18,6 +18,11 @@ require_relative 'rice_bubble/attributes/time'
18
18
  require_relative 'rice_bubble/serializer'
19
19
 
20
20
  module RiceBubble
21
- class ValidationError < StandardError; end
22
- # Your code goes here...
21
+ class ValidationError < StandardError
22
+ attr_reader :value, :path, :attribute
23
+
24
+ def initialize(value:, path:, attribute:)
25
+ super("#{path} expected #{attribute.description} but received #{value.inspect}")
26
+ end
27
+ end
23
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rice_bubble
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Powell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-22 00:00:00.000000000 Z
11
+ date: 2023-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake