Module: Axn::Core::ContractForSubfields::ClassMethods

Defined in:
lib/axn/core/contract_for_subfields.rb

Instance Method Summary collapse

Instance Method Details

#_expects_subfields(*fields, on:, readers: true, allow_blank: false, allow_nil: false, optional: false, default: nil, preprocess: nil, sensitive: false, metadata: {}, **validations) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/axn/core/contract_for_subfields.rb', line 33

def _expects_subfields(
  *fields,
  on:,
  readers: true,
  allow_blank: false,
  allow_nil: false,
  optional: false,
  default: nil,
  preprocess: nil,
  sensitive: false,
  metadata: {},
  **validations
)
  # `on:` may be a dotted path (e.g. "address.billing"); the *root* segment must be declared.
  root = on.to_s.split(".").first.to_sym
  unless internal_field_configs.map(&:field).include?(root) || subfield_configs.map(&:field).include?(root)
    raise ArgumentError,
          "expects called with `on: #{on}`, but no such method exists (are you sure you've declared `expects :#{root}`?)"
  end

  # default:/preprocess: write into the parent, and sensitive: relies on the log filter
  # matching config.on to a top-level field — none of which support an arbitrary nested
  # path yet. Reject the combination explicitly rather than silently ignoring it (use
  # .nil? for default/preprocess so an explicit `default: false`/`nil` is still caught).
  if on.to_s.include?(".") && (!default.nil? || !preprocess.nil? || sensitive)
    raise ArgumentError,
          "`default:`/`preprocess:`/`sensitive:` are not supported with a nested (dotted) `on:` (got on: #{on.inspect})"
  end

  _parse_subfield_configs(*fields, on:, readers:, allow_blank:, allow_nil:, optional:, preprocess:, sensitive:, default:,
                                   metadata:, **validations).tap do |configs|
    duplicated = subfield_configs.map(&:field) & configs.map(&:field)
    raise Axn::DuplicateFieldError, "Duplicate field(s) declared: #{duplicated.join(', ')}" if duplicated.any?

    # NOTE: avoid <<, which would update value for parents and children
    self.subfield_configs += configs
  end
end