rom-relation 0.1.0

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.
Files changed (70) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +3 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +21 -0
  6. data/.yardopts +4 -0
  7. data/Gemfile +24 -0
  8. data/Gemfile.devtools +55 -0
  9. data/Guardfile +25 -0
  10. data/LICENSE +20 -0
  11. data/README.md +21 -0
  12. data/Rakefile +4 -0
  13. data/TODO.md +4 -0
  14. data/config/devtools.yml +2 -0
  15. data/config/flay.yml +3 -0
  16. data/config/flog.yml +2 -0
  17. data/config/mutant.yml +8 -0
  18. data/config/reek.yml +97 -0
  19. data/config/rubocop.yml +41 -0
  20. data/lib/rom/environment.rb +133 -0
  21. data/lib/rom/mapping/definition.rb +127 -0
  22. data/lib/rom/mapping.rb +81 -0
  23. data/lib/rom/relation.rb +339 -0
  24. data/lib/rom/repository.rb +62 -0
  25. data/lib/rom/schema/definition/relation/base.rb +25 -0
  26. data/lib/rom/schema/definition/relation.rb +44 -0
  27. data/lib/rom/schema/definition.rb +82 -0
  28. data/lib/rom/schema.rb +49 -0
  29. data/lib/rom/support/axiom/adapter/data_objects.rb +39 -0
  30. data/lib/rom/support/axiom/adapter/memory.rb +25 -0
  31. data/lib/rom/support/axiom/adapter/postgres.rb +19 -0
  32. data/lib/rom/support/axiom/adapter/sqlite3.rb +19 -0
  33. data/lib/rom/support/axiom/adapter.rb +100 -0
  34. data/lib/rom/version.rb +7 -0
  35. data/lib/rom-relation.rb +45 -0
  36. data/rom-relation.gemspec +26 -0
  37. data/spec/integration/environment_setup_spec.rb +22 -0
  38. data/spec/integration/mapping_relations_spec.rb +64 -0
  39. data/spec/integration/schema_definition_spec.rb +94 -0
  40. data/spec/shared/unit/environment_context.rb +6 -0
  41. data/spec/shared/unit/relation_context.rb +25 -0
  42. data/spec/spec_helper.rb +41 -0
  43. data/spec/support/helper.rb +17 -0
  44. data/spec/support/test_mapper.rb +23 -0
  45. data/spec/unit/rom/environment/class_methods/setup_spec.rb +25 -0
  46. data/spec/unit/rom/environment/element_reader_spec.rb +23 -0
  47. data/spec/unit/rom/environment/mapping_spec.rb +26 -0
  48. data/spec/unit/rom/environment/repository_spec.rb +21 -0
  49. data/spec/unit/rom/environment/schema_spec.rb +33 -0
  50. data/spec/unit/rom/mapping/class_methods/build_spec.rb +77 -0
  51. data/spec/unit/rom/relation/class_methods/build_spec.rb +19 -0
  52. data/spec/unit/rom/relation/delete_spec.rb +15 -0
  53. data/spec/unit/rom/relation/drop_spec.rb +11 -0
  54. data/spec/unit/rom/relation/each_spec.rb +23 -0
  55. data/spec/unit/rom/relation/first_spec.rb +19 -0
  56. data/spec/unit/rom/relation/inject_mapper_spec.rb +17 -0
  57. data/spec/unit/rom/relation/insert_spec.rb +13 -0
  58. data/spec/unit/rom/relation/last_spec.rb +19 -0
  59. data/spec/unit/rom/relation/one_spec.rb +49 -0
  60. data/spec/unit/rom/relation/replace_spec.rb +13 -0
  61. data/spec/unit/rom/relation/restrict_spec.rb +25 -0
  62. data/spec/unit/rom/relation/sort_by_spec.rb +25 -0
  63. data/spec/unit/rom/relation/take_spec.rb +11 -0
  64. data/spec/unit/rom/relation/to_a_spec.rb +20 -0
  65. data/spec/unit/rom/relation/update_spec.rb +25 -0
  66. data/spec/unit/rom/repository/class_methods/build_spec.rb +27 -0
  67. data/spec/unit/rom/repository/element_reader_spec.rb +21 -0
  68. data/spec/unit/rom/repository/element_writer_spec.rb +18 -0
  69. data/spec/unit/rom/schema/class_methods/build_spec.rb +103 -0
  70. metadata +249 -0
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'axiom-memory-adapter'
4
+ require 'rom/support/axiom/adapter'
5
+
6
+ module Axiom
7
+ module Adapter
8
+
9
+ # A axiom in memory adapter
10
+ #
11
+ # This is basically a "null adapter"
12
+ # as it doesn't make use of it's uri
13
+ # and only passes through the given
14
+ # +relation+ in {#gateway}
15
+ #
16
+ class Memory
17
+ extend Adapter
18
+
19
+ include Equalizer.new(:schema)
20
+
21
+ uri_scheme :memory
22
+
23
+ end # class Memory
24
+ end # module Adapter
25
+ end # module Axiom
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'do_postgres'
4
+
5
+ require 'rom/support/axiom/adapter'
6
+ require 'rom/support/axiom/adapter/data_objects'
7
+
8
+ module Axiom
9
+ module Adapter
10
+
11
+ # A Axiom adapter for postgres
12
+ #
13
+ class Postgres < DataObjects
14
+
15
+ uri_scheme :postgres
16
+
17
+ end # class Postgres
18
+ end # module Adapter
19
+ end # module Axiom
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'do_sqlite3'
4
+
5
+ require 'rom/support/axiom/adapter'
6
+ require 'rom/support/axiom/adapter/data_objects'
7
+
8
+ module Axiom
9
+ module Adapter
10
+
11
+ # A axiom adapter for sqlite3
12
+ #
13
+ class Sqlite3 < DataObjects
14
+
15
+ uri_scheme :sqlite3
16
+
17
+ end # class Sqlite3
18
+ end # module Adapter
19
+ end # module Axiom
@@ -0,0 +1,100 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+
5
+ # Raised when passing an +uri+ with an unregistered scheme to {Adapter.new}
6
+ UnknownAdapterError = Class.new(StandardError)
7
+
8
+ # Provides base functionality for every axiom adapter
9
+ #
10
+ # @todo think about making this a (base) class
11
+ #
12
+ # @example
13
+ #
14
+ # class MyAdapter
15
+ # extend Axiom::Adapter
16
+ # uri_scheme :foo
17
+ # end
18
+ #
19
+ module Adapter
20
+
21
+ # The registry of adapters
22
+ #
23
+ # @return [Hash<String, Object>]
24
+ # a hash of adapters, keyed by uri scheme
25
+ #
26
+ # @api private
27
+ REGISTRY = {}
28
+
29
+ # Return the adapter to use for the given +uri+
30
+ #
31
+ # @param [Addressable::URI] uri
32
+ # the uri to initialize the adapter with
33
+ #
34
+ # @return [Object]
35
+ # a axiom adapter
36
+ #
37
+ # @raise [UnknownAdapterError]
38
+ # when the given +uri+'s scheme is not registered
39
+ #
40
+ # @api private
41
+ def self.build(uri)
42
+ klass = get(uri)
43
+
44
+ if klass.name == 'Axiom::Adapter::Memory'
45
+ klass.new
46
+ else
47
+ klass.new(uri)
48
+ end
49
+ end
50
+
51
+ # Return the adapter class registered for +uri+
52
+ #
53
+ # @param [Addressable::URI] uri
54
+ # the uri that identifies the adapter class
55
+ #
56
+ # @return [Class]
57
+ # a axiom adapter class
58
+ #
59
+ # @raise [UnknownAdapterError]
60
+ # when the given +uri+'s scheme is not registered
61
+ #
62
+ # @api private
63
+ def self.get(uri)
64
+ uri_scheme = uri.scheme
65
+
66
+ REGISTRY.fetch(uri_scheme) {
67
+ raise(
68
+ UnknownAdapterError,
69
+ "#{uri_scheme.inspect} is no registered uri scheme"
70
+ )
71
+ }
72
+ end
73
+
74
+ # Set the uri scheme for an adapter class
75
+ #
76
+ # @example for a DataObjects adapter
77
+ #
78
+ # class Postgres < Axiom::Adapter::DataObjects
79
+ # uri_scheme :postgres
80
+ # end
81
+ #
82
+ # @example for an arbitrary adapter
83
+ #
84
+ # class InMemory
85
+ # extend Axiom::Adapter
86
+ # uri_scheme :in_memory
87
+ # end
88
+ #
89
+ # @param [#to_s] name
90
+ # the name of the uri scheme
91
+ #
92
+ # @return [self]
93
+ #
94
+ # @api public
95
+ def uri_scheme(name)
96
+ REGISTRY[name.to_s] = self
97
+ end
98
+
99
+ end # module Adapter
100
+ end # module Axiom
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ module ROM
4
+ class Relation
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'addressable/uri'
4
+
5
+ require 'set'
6
+ require 'concord'
7
+ require 'abstract_type'
8
+ require 'descendants_tracker'
9
+ require 'equalizer'
10
+ require 'axiom'
11
+
12
+ # Main ROM module with methods to setup and manage the environment
13
+ module ROM
14
+
15
+ # Raised when the returned tuples are unexpectedly empty
16
+ NoTuplesError = Class.new(RuntimeError)
17
+
18
+ # Raised when the returned tuples are unexpectedly too many
19
+ ManyTuplesError = Class.new(RuntimeError)
20
+
21
+ # Represent an undefined argument
22
+ Undefined = Object.new.freeze
23
+
24
+ # An empty frozen Hash useful for parameter default values
25
+ EMPTY_HASH = {}.freeze
26
+
27
+ # An empty frozen Array useful for parameter default values
28
+ EMPTY_ARRAY = [].freeze
29
+
30
+ # Represent a positive, infinitely large Float number
31
+ Infinity = 1.0 / 0
32
+
33
+ end # module ROM
34
+
35
+ require 'rom/repository'
36
+ require 'rom/environment'
37
+ require 'rom/relation'
38
+
39
+ require 'rom/schema'
40
+ require 'rom/schema/definition'
41
+ require 'rom/schema/definition/relation'
42
+ require 'rom/schema/definition/relation/base'
43
+
44
+ require 'rom/mapping'
45
+ require 'rom/mapping/definition'
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../lib/rom/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'rom-relation'
7
+ gem.summary = 'Relation schema with mapping for ROM'
8
+ gem.description = gem.summary
9
+ gem.authors = 'Piotr Solnica'
10
+ gem.email = 'piotr.solnica@gmail.com'
11
+ gem.homepage = 'http://rom-rb.org'
12
+ gem.require_paths = ['lib']
13
+ gem.version = ROM::Relation::VERSION
14
+ gem.files = `git ls-files`.split("\n")
15
+ gem.test_files = `git ls-files -- {spec}/*`.split("\n")
16
+ gem.license = 'MIT'
17
+
18
+ gem.add_dependency 'addressable', '~> 2.3', '>= 2.3.3'
19
+ gem.add_dependency 'concord', '~> 0.1.4'
20
+ gem.add_dependency 'equalizer', '~> 0.0.7'
21
+ gem.add_dependency 'descendants_tracker', '~> 0.0.1'
22
+ gem.add_dependency 'abstract_type', '~> 0.0.6'
23
+ gem.add_dependency 'adamantium', '~> 0.1'
24
+ gem.add_dependency 'axiom', '~> 0.1.1'
25
+ gem.add_dependency 'axiom-optimizer', '~> 0.1.0'
26
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Setting up environment' do
6
+ it 'registers relations within repositories' do
7
+ env = ROM::Environment.setup(memory: 'memory://test')
8
+
9
+ schema = env.schema do
10
+ base_relation :users do
11
+ repository :memory
12
+
13
+ attribute :id, Integer
14
+ attribute :name, String
15
+
16
+ key :id
17
+ end
18
+ end
19
+
20
+ expect(schema[:users]).to be_instance_of(Axiom::Relation::Variable)
21
+ end
22
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Defining relation mappings' do
6
+ let!(:schema) {
7
+ env.schema {
8
+ base_relation :users do
9
+ repository :test
10
+
11
+ attribute :id, Integer
12
+ attribute :user_name, String
13
+
14
+ key :id
15
+ end
16
+ }
17
+ }
18
+
19
+ let!(:env) {
20
+ Environment.setup(test: 'memory://test')
21
+ }
22
+
23
+ before do
24
+ User = mock_model(:id, :name)
25
+ end
26
+
27
+ after do
28
+ Object.send(:remove_const, :User)
29
+ end
30
+
31
+ specify 'building registry of automatically mapped relations' do
32
+ env.mapping do
33
+ users do
34
+ model User
35
+
36
+ map :id
37
+ map :user_name, to: :name
38
+ end
39
+ end
40
+
41
+ users = env[:users]
42
+
43
+ jane = User.new(id: 1, name: 'Jane')
44
+
45
+ users.insert(jane)
46
+
47
+ expect(users.to_a).to eql([jane])
48
+ end
49
+
50
+ specify 'providing custom mapper' do
51
+ custom_model = mock_model(:id, :user_name)
52
+ custom_mapper = TestMapper.new(schema[:users].header, custom_model)
53
+
54
+ env.mapping { users { mapper(custom_mapper) } }
55
+
56
+ users = env[:users]
57
+
58
+ jane = custom_model.new(id: 1, user_name: 'Jane')
59
+
60
+ users.insert(jane)
61
+
62
+ expect(users.to_a).to eql([jane])
63
+ end
64
+ end
@@ -0,0 +1,94 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Defining a ROM schema' do
6
+ let(:people) {
7
+ Axiom::Relation::Base.new(:people, people_header)
8
+ }
9
+
10
+ let(:people_header) {
11
+ Axiom::Relation::Header.coerce(people_attributes, keys: people_keys)
12
+ }
13
+
14
+ let(:people_attributes) {
15
+ [[:id, Integer], [:name, String]]
16
+ }
17
+
18
+ let(:people_keys) {
19
+ [:id]
20
+ }
21
+
22
+ let(:profiles) {
23
+ Axiom::Relation::Base.new(:profiles, profiles_header)
24
+ }
25
+
26
+ let(:profiles_header) {
27
+ Axiom::Relation::Header.coerce(profiles_attributes, keys: profiles_keys)
28
+ }
29
+
30
+ let(:profiles_attributes) {
31
+ [[:id, Integer], [:person_id, Integer], [:text, String]]
32
+ }
33
+
34
+ let(:profiles_keys) {
35
+ [:id, :person_id]
36
+ }
37
+
38
+ let(:people_with_profile) {
39
+ people.join(profiles.rename(id: :profile_id, person_id: :id))
40
+ }
41
+
42
+ let(:env) { Environment.setup(test: 'memory://test') }
43
+ let(:repository) { env.repository(:test) }
44
+
45
+ let(:schema) do
46
+ env.schema do
47
+ base_relation :people do
48
+ repository :test
49
+
50
+ attribute :id, Integer
51
+ attribute :name, String
52
+
53
+ key :id
54
+ end
55
+
56
+ base_relation :profiles do
57
+ repository :test
58
+
59
+ attribute :id, Integer
60
+ attribute :person_id, Integer
61
+ attribute :text, String
62
+
63
+ key :id
64
+ key :person_id
65
+ end
66
+ end
67
+
68
+ env.schema do
69
+ relation :people_with_profile do
70
+ people.join(profiles.rename(id: :profile_id, person_id: :id))
71
+ end
72
+ end
73
+ end
74
+
75
+ it 'registers the people relation' do
76
+ expect(schema[:people]).to eq(people)
77
+ end
78
+
79
+ it 'establishes key attributes for people relation' do
80
+ expect(schema[:people].header.keys).to include(*people_keys)
81
+ end
82
+
83
+ it 'establishes key attributes for profiles relation' do
84
+ expect(schema[:profiles].header.keys).to include(*profiles_keys)
85
+ end
86
+
87
+ it 'registers the profiles relation' do
88
+ expect(schema[:profiles]).to eq(profiles)
89
+ end
90
+
91
+ it 'registers the people_with_profile relation' do
92
+ expect(schema[:people_with_profile]).to eq(people_with_profile)
93
+ end
94
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ shared_context 'Environment' do
4
+ let(:object) { Environment.setup(test: 'memory://test') }
5
+ let(:uri) { 'memory://test' }
6
+ end
@@ -0,0 +1,25 @@
1
+ # # encoding: utf-8
2
+
3
+ # encoding: utf-8
4
+
5
+ shared_context 'Relation' do
6
+ subject(:relation) { described_class.new(users, mapper) }
7
+
8
+ let(:header) {
9
+ Axiom::Relation::Header.coerce([[:id, Integer], [:name, String]], keys: [:id])
10
+ }
11
+
12
+ let(:users) {
13
+ Axiom::Relation.new(header, [
14
+ [1, 'John'], [2, 'Jane'], [3, 'Jack'], [4, 'Jade']
15
+ ])
16
+ }
17
+
18
+ let(:model) { mock_model(:id, :name) }
19
+ let(:mapper) { TestMapper.new(users.header, model) }
20
+
21
+ let(:john) { model.new(id: 1, name: 'John') }
22
+ let(:jane) { model.new(id: 2, name: 'Jane') }
23
+ let(:jack) { model.new(id: 3, name: 'Jack') }
24
+ let(:jade) { model.new(id: 4, name: 'Jade') }
25
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+
3
+ # SimpleCov MUST be started before require 'rom-relation'
4
+ #
5
+ if ENV['COVERAGE'] == 'true'
6
+ require 'simplecov'
7
+ require 'coveralls'
8
+
9
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
10
+ SimpleCov::Formatter::HTMLFormatter,
11
+ Coveralls::SimpleCov::Formatter
12
+ ]
13
+
14
+ SimpleCov.start do
15
+ command_name 'spec:unit'
16
+
17
+ add_filter 'config'
18
+ add_filter 'lib/rom/support'
19
+ add_filter 'spec'
20
+ end
21
+ end
22
+
23
+ require 'rom-relation'
24
+ require 'rom-mapper'
25
+ require 'rom/support/axiom/adapter/memory'
26
+
27
+ require 'devtools/spec_helper'
28
+ require 'bogus/rspec'
29
+
30
+ include ROM
31
+
32
+ ROM_ENV = Environment.setup(test: 'memory://test')
33
+ ROM_ADAPTER = ENV.fetch('ROM_ADAPTER', :in_memory).to_sym
34
+
35
+ Bogus.configure do |config|
36
+ config.search_modules << ROM
37
+ end
38
+
39
+ RSpec.configure do |config|
40
+ config.include(SpecHelper)
41
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ module SpecHelper
4
+
5
+ def mock_model(*attributes)
6
+ Class.new {
7
+ include Equalizer.new(*attributes)
8
+
9
+ attributes.each { |attribute| attr_accessor attribute }
10
+
11
+ def initialize(attrs)
12
+ attrs.each { |name, value| send("#{name}=", value) }
13
+ end
14
+ }
15
+ end
16
+
17
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ class TestMapper < Struct.new(:header, :model)
4
+
5
+ def call(relation)
6
+ relation
7
+ end
8
+
9
+ def load(tuple)
10
+ model.new(
11
+ Hash[
12
+ header.map { |attribute| [attribute.name, tuple[attribute.name]] }
13
+ ]
14
+ )
15
+ end
16
+
17
+ def dump(object)
18
+ header.each_with_object([]) { |attribute, tuple|
19
+ tuple << object.send(attribute.name)
20
+ }
21
+ end
22
+
23
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Environment, '.setup' do
6
+ subject { described_class.setup(config) }
7
+
8
+ context 'when an environment is passed' do
9
+ let(:config) { environment }
10
+ let(:environment) { described_class.setup(test: 'memory://test') }
11
+
12
+ it { should be(environment) }
13
+ end
14
+
15
+ context 'when a repository config hash is passed' do
16
+ let(:config) { { name => uri } }
17
+ let(:name) { :test }
18
+ let(:uri) { 'memory://test' }
19
+
20
+ let(:coerced_config) { Hash[test: Repository.build(name, coerced_uri)] }
21
+ let(:coerced_uri) { Addressable::URI.parse(uri) }
22
+
23
+ it { should eq(described_class.new(coerced_config, {})) }
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Environment, '#[]' do
6
+ include_context 'Environment'
7
+
8
+ subject { object[:users] }
9
+
10
+ context 'when relation exists' do
11
+ fake(:relation, name: :users) { Axiom::Relation::Base }
12
+
13
+ before do
14
+ object[:users] = relation
15
+ end
16
+
17
+ it { should be(relation) }
18
+ end
19
+
20
+ context 'when relation does not exist' do
21
+ it { should be(nil) }
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Environment, '#mapping' do
6
+ include_context 'Environment'
7
+
8
+ let!(:schema) do
9
+ object.schema do
10
+ base_relation(:users) do
11
+ repository :test
12
+ attribute :name, String
13
+ end
14
+ end
15
+ end
16
+
17
+ before do
18
+ object.mapping do
19
+ users { map :name }
20
+ end
21
+ end
22
+
23
+ it 'sets up rom relations' do
24
+ expect(object[:users]).to be_instance_of(Relation)
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Environment, '#repository' do
6
+ include_context 'Environment'
7
+
8
+ subject { object.repository(name) }
9
+
10
+ context 'when repository exists' do
11
+ let(:name) { :test }
12
+
13
+ it { should be_instance_of(Repository) }
14
+ end
15
+
16
+ context 'when is not known' do
17
+ let(:name) { :not_here }
18
+
19
+ it { should be(nil) }
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Environment, '#schema' do
6
+ let(:repositories) { Hash.new }
7
+ let(:object) { Environment.build(repositories) }
8
+ let(:block) { -> { } }
9
+
10
+ fake(:schema)
11
+
12
+ before do
13
+ fake_class(Schema, build: -> { schema })
14
+ end
15
+
16
+ describe 'with a block' do
17
+ subject { object.schema(&block) }
18
+
19
+ it 'calls the schema' do
20
+ expect(subject).to be(schema)
21
+ expect(schema).to have_received.call
22
+ end
23
+ end
24
+
25
+ describe 'without a block' do
26
+ subject { object.schema }
27
+
28
+ it 'calls the schema' do
29
+ expect(subject).to be(schema)
30
+ expect(schema).not_to have_received.call
31
+ end
32
+ end
33
+ end