Class: SmartParams::Field

Inherits:
Object
  • Object
show all
Defined in:
lib/smart_params/field.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(keychain:, type:, key: nil, subschema: false, nullable: false, &nesting) ⇒ Field

Returns a new instance of Field.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/smart_params/field.rb', line 20

def initialize(keychain:, type:, key: nil, subschema: false, nullable: false, &nesting)
  @key = key
  @keychain = Array(keychain)
  @subfields = Set.new
  @type = type
  @nullable = nullable
  @subschema = subschema
  @specified = false
  @dirty = false

  instance_eval(&nesting) if nesting

  if subschema
    @type = @type.schema(subfields.reduce({}) do |mapping, field|
      mapping.merge("#{field.key}#{'?' if field.nullable}": field.type)
    end).with_key_transform(&:to_sym)
  end
  @type = @type.optional if nullable
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



9
10
11
# File 'lib/smart_params/field.rb', line 9

def key
  @key
end

#keychainObject (readonly)

Returns the value of attribute keychain.



5
6
7
# File 'lib/smart_params/field.rb', line 5

def keychain
  @keychain
end

#nullableObject (readonly)

Returns the value of attribute nullable.



8
9
10
# File 'lib/smart_params/field.rb', line 8

def nullable
  @nullable
end

#subfieldsObject (readonly)

Returns the value of attribute subfields.



6
7
8
# File 'lib/smart_params/field.rb', line 6

def subfields
  @subfields
end

#typeObject (readonly)

Returns the value of attribute type.



7
8
9
# File 'lib/smart_params/field.rb', line 7

def type
  @type
end

Instance Method Details

#allow_empty?Boolean

Check if we should consider this value even when empty.

Returns:

  • (Boolean)


83
84
85
86
87
# File 'lib/smart_params/field.rb', line 83

def allow_empty?
  return true if specified? && nullable?

  subfields.any?(&:allow_empty?)
end

#claim(raw) ⇒ Object



89
90
91
92
93
94
95
96
97
# File 'lib/smart_params/field.rb', line 89

def claim(raw)
  return type[dug(raw)] if deep?

  @value = type[dug(raw)]
rescue Dry::Types::ConstraintError => _constraint_exception
  raise SmartParams::Error::InvalidPropertyType.new(keychain:, wanted: type, raw: keychain.empty? ? raw : raw.dig(*keychain))
rescue Dry::Types::MissingKeyError => missing_key_exception
  raise SmartParams::Error::InvalidPropertyType.new(keychain:, wanted: type, raw: keychain.empty? ? raw : raw.dig(*keychain), missing_key: missing_key_exception.key)
end

#clean?Boolean

Returns:

  • (Boolean)


75
76
77
78
79
80
# File 'lib/smart_params/field.rb', line 75

def clean?
  return false if dirty?
  return true if empty? || subfields.reject(&:empty?).any?

  false
end

#deep?Boolean

Returns:

  • (Boolean)


40
41
42
43
44
45
46
# File 'lib/smart_params/field.rb', line 40

def deep?
  # We check @specified directly because we want to know if ANY
  # subfields have been passed, not just ones that match the schema.
  return false if nullable? && @specified

  subfields.present?
end

#dirty?Boolean

For nullable hashes: Any keys not in the schema make the hash dirty. If a key is found that matches the schema, we can consider the hash clean.

Returns:

  • (Boolean)


71
72
73
# File 'lib/smart_params/field.rb', line 71

def dirty?
  !!@dirty
end

#empty?Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/smart_params/field.rb', line 105

def empty?
  value.nil?
end

#inspectObject



11
12
13
14
15
16
17
18
# File 'lib/smart_params/field.rb', line 11

def inspect
  "#<#{self.class.name}:#{__id__} #{[
    ('subschema' if @subschema),
    ("#/#{@keychain.join('/')}" if @keychain),
    ("-> #{type.name}" if @type),
    ("= #{@value.inspect}" if @value)
  ].compact.join(' ')}>"
end

#nullable?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/smart_params/field.rb', line 56

def nullable?
  !!@nullable
end

#removable?Boolean

Should this field be removed from resulting hash?

Returns:

  • (Boolean)


110
111
112
# File 'lib/smart_params/field.rb', line 110

def removable?
  empty? && !allow_empty?
end

#root?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/smart_params/field.rb', line 48

def root?
  keychain.empty?
end

#specified?Boolean

Returns:

  • (Boolean)


60
61
62
63
64
65
66
# File 'lib/smart_params/field.rb', line 60

def specified?
  if nullable?
    !!@specified && clean?
  else
    !!@specified
  end
end

#to_hashObject



99
100
101
102
103
# File 'lib/smart_params/field.rb', line 99

def to_hash
  keychain.reverse.reduce(value) do |accumulation, key|
    { key => accumulation }
  end
end

#valueObject



52
53
54
# File 'lib/smart_params/field.rb', line 52

def value
  @value || ({} if root?)
end

#weightObject



114
115
116
# File 'lib/smart_params/field.rb', line 114

def weight
  keychain.map(&:to_s)
end