Skip to content

Commit

Permalink
Merge pull request #256 from dry-rb/merging-schemas
Browse files Browse the repository at this point in the history
Add Processor#merge which allows merging schemas
  • Loading branch information
solnic authored Mar 4, 2020
2 parents 9bd050a + 10b24f5 commit 56a1bdb
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/dry/schema/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,20 @@ def call
processor_type.new(schema_dsl: self, steps: result_steps)
end

# Merge with another dsl
#
# @return [DSL]
#
# @api private
def merge(other)
new(
parent: parents + other.parents,
macros: macros + other.macros,
types: types.merge(other.types),
steps: steps.merge(other.steps)
)
end

# Cast this DSL into a rule object
#
# @return [RuleApplier]
Expand Down
11 changes: 11 additions & 0 deletions lib/dry/schema/processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ def call(input)
end
alias_method :[], :call

# Merge with another schema
#
# @param [Processor] other
#
# @return [Processor, Params, JSON]
#
# @api public
def merge(other)
schema_dsl.merge(other.schema_dsl).()
end

# Return a proc that acts like a schema object
#
# @return [Proc]
Expand Down
82 changes: 82 additions & 0 deletions spec/unit/dry/schema/processor/merge_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
require 'dry/schema/processor'

RSpec.describe Dry::Schema::Processor, '#merge' do
context 'without parents' do
subject(:schema) { left.merge(right) }

let(:left) do
Dry::Schema.define do
after(:rule_applier) do |result|
result.output[:left] = true
end

required(:name).filled(:string)
end
end

let(:right) do
Dry::Schema.define do
after(:rule_applier) do |result|
result.output[:right] = true
end

required(:age).value(Types::Params::Integer)
end
end

it 'maintains rules' do
expect(schema.(name: '', age: 'foo').errors.to_h).to eql(
name: ['must be filled'], age: ['must be an integer']
)
end

it 'maintains types' do
expect(schema.(name: '', age: '36').errors.to_h).to eql(
name: ['must be filled']
)
end

it 'maintains hooks' do
expect(schema.(name: 'Jane', age: 36).to_h).to eql(
name: 'Jane', age: 36, left: true, right: true
)
end
end

context 'with parents' do
subject(:schema) { left.merge(right) }

let(:left_parent) do
Dry::Schema.define do
required(:email).filled(:string)
end
end

let(:left) do
Dry::Schema.define(parent: left_parent) do
required(:name).filled(:string)
end
end

let(:right_parent) do
Dry::Schema.define do
required(:address).filled(:string)
end
end

let(:right) do
Dry::Schema.define(parent: right_parent) do
required(:age).value(:integer)
end
end

it 'maintains all rules' do
expect(schema.(name: '', age: 'foo').errors.to_h).to eql(
name: ['must be filled'],
age: ['must be an integer'],
email: ['is missing'],
address: ['is missing']
)
end
end
end

0 comments on commit 56a1bdb

Please sign in to comment.