Class: Parametric::TaggedOneOf

Inherits:
Object
  • Object
show all
Defined in:
lib/parametric/tagged_one_of.rb

Overview

A policy that allows you to select a sub-schema based on a value in the payload. Instances can also be created separately and used as a policy:

Examples:


user_schema = Parametric::Schema.new do |sc, _|
  field(:name).type(:string).present
  field(:age).type(:integer).present
end

company_schema = Parametric::Schema.new do
  field(:name).type(:string).present
  field(:company_code).type(:string).present
end

schema = Parametric::Schema.new do |sc, _|
   # Use :type field to locate the sub-schema to use for :sub
   sc.field(:type).type(:string)

   # Use the :one_of policy to select the sub-schema based on the :type field above
   sc.field(:sub).type(:object).tagged_one_of do |sub|
     sub.index_by(:type)
     sub.on('user', user_schema)
     sub.on('company', company_schema)
   end
 end

 # The schema will now select the correct sub-schema based on the value of :type
 result = schema.resolve(type: 'user', sub: { name: 'Joe', age: 30 })

UserOrCompany = Parametric::TaggedOneOf.new do |sc, _|
  sc.on('user', user_schema)
  sc.on('company', company_schema)
end

schema = Parametric::Schema.new do |sc, _|
  sc.field(:type).type(:string)
  sc.field(:sub).type(:object).policy(UserOrCompany.index_by(:type))
end

Defined Under Namespace

Classes: Runner

Constant Summary collapse

NOOP_INDEX =
->(payload) { payload }.freeze

Instance Method Summary collapse

Constructor Details

#initialize(index: NOOP_INDEX, matchers: {}, &block) ⇒ TaggedOneOf

Returns a new instance of TaggedOneOf.



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/parametric/tagged_one_of.rb', line 46

def initialize(index: NOOP_INDEX, matchers: {}, &block)
  @index = index
  @matchers = matchers
  @configuring = false
  if block_given?
    @configuring = true
    block.call(self)
    @configuring = false
  end
  freeze
end

Instance Method Details

#build(key, value, payload:, context:) ⇒ Object

The [PolicyFactory] interface



76
77
78
# File 'lib/parametric/tagged_one_of.rb', line 76

def build(key, value, payload:, context:)
  Runner.new(@index, @matchers, key, value, payload, context)
end

#index_by(callable = nil, &block) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/parametric/tagged_one_of.rb', line 58

def index_by(callable = nil, &block)
  if callable.is_a?(Symbol)
    key = callable
    callable = ->(payload) { payload[key] }
  end
  index = callable || block
  if configuring?
    @index = index
  else
    self.class.new(index:, matchers: @matchers)
  end
end

#meta_dataObject



80
81
82
# File 'lib/parametric/tagged_one_of.rb', line 80

def 
  { type: :object, one_of: @matchers }
end

#on(key, schema) ⇒ Object



71
72
73
# File 'lib/parametric/tagged_one_of.rb', line 71

def on(key, schema)
  @matchers[key] = schema
end