rom 2.0.2 → 3.0.0.beta1
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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/CHANGELOG.md +34 -1
- data/Gemfile +16 -2
- data/Rakefile +7 -2
- data/lib/rom/array_dataset.rb +44 -0
- data/lib/rom/association_set.rb +11 -5
- data/lib/rom/auto_curry.rb +55 -0
- data/lib/rom/command.rb +70 -41
- data/lib/rom/command_registry.rb +7 -18
- data/lib/rom/commands/class_interface.rb +7 -6
- data/lib/rom/commands/composite.rb +0 -1
- data/lib/rom/commands/graph.rb +7 -15
- data/lib/rom/commands/lazy/update.rb +1 -1
- data/lib/rom/configuration_dsl/command.rb +6 -8
- data/lib/rom/configuration_dsl/mapper.rb +2 -3
- data/lib/rom/configuration_dsl/mapper_dsl.rb +0 -1
- data/lib/rom/configuration_dsl/relation.rb +4 -4
- data/lib/rom/configuration_dsl.rb +0 -4
- data/lib/rom/constants.rb +1 -1
- data/lib/rom/container.rb +0 -2
- data/lib/rom/create_container.rb +0 -2
- data/lib/rom/data_proxy.rb +94 -0
- data/lib/rom/enumerable_dataset.rb +68 -0
- data/lib/rom/gateway.rb +23 -6
- data/lib/rom/global/plugin_dsl.rb +0 -2
- data/lib/rom/global.rb +0 -2
- data/lib/rom/initializer.rb +26 -0
- data/lib/rom/lint/gateway.rb +17 -0
- data/lib/rom/mapper_registry.rb +1 -1
- data/lib/rom/memory/commands.rb +0 -2
- data/lib/rom/memory/dataset.rb +1 -2
- data/lib/rom/memory/relation.rb +14 -1
- data/lib/rom/memory/schema.rb +13 -0
- data/lib/rom/plugin_registry.rb +1 -1
- data/lib/rom/plugins/configuration/configuration_dsl.rb +6 -2
- data/lib/rom/plugins/relation/key_inference.rb +4 -2
- data/lib/rom/plugins/relation/registry_reader.rb +5 -1
- data/lib/rom/registry.rb +50 -0
- data/lib/rom/relation/class_interface.rb +94 -26
- data/lib/rom/relation/curried.rb +15 -15
- data/lib/rom/relation/view_dsl.rb +31 -0
- data/lib/rom/relation.rb +49 -34
- data/lib/rom/schema/dsl.rb +7 -9
- data/lib/rom/schema/type.rb +115 -0
- data/lib/rom/schema.rb +218 -18
- data/lib/rom/setup/auto_registration.rb +20 -17
- data/lib/rom/setup/auto_registration_strategies/base.rb +8 -3
- data/lib/rom/setup/auto_registration_strategies/custom_namespace.rb +4 -3
- data/lib/rom/setup/auto_registration_strategies/no_namespace.rb +5 -4
- data/lib/rom/setup/auto_registration_strategies/with_namespace.rb +3 -3
- data/lib/rom/setup/finalize/finalize_commands.rb +1 -1
- data/lib/rom/setup/finalize/finalize_mappers.rb +1 -1
- data/lib/rom/setup/finalize/finalize_relations.rb +3 -1
- data/lib/rom/setup/finalize.rb +1 -1
- data/lib/rom/transaction.rb +24 -0
- data/lib/rom/types.rb +9 -1
- data/lib/rom/version.rb +1 -1
- data/lib/rom.rb +4 -8
- data/rom.gemspec +4 -3
- data/spec/integration/command_registry_spec.rb +1 -14
- data/spec/integration/commands/create_spec.rb +5 -25
- data/spec/integration/commands/delete_spec.rb +1 -1
- data/spec/integration/commands/error_handling_spec.rb +1 -1
- data/spec/integration/commands/graph_spec.rb +20 -14
- data/spec/integration/commands/update_spec.rb +4 -27
- data/spec/integration/commands_spec.rb +1 -1
- data/spec/integration/{repositories → gateways}/extending_relations_spec.rb +1 -1
- data/spec/integration/{repositories → gateways}/setting_logger_spec.rb +2 -2
- data/spec/integration/mappers/combine_spec.rb +1 -1
- data/spec/integration/mappers/deep_embedded_spec.rb +1 -1
- data/spec/integration/mappers/definition_dsl_spec.rb +1 -1
- data/spec/integration/mappers/embedded_spec.rb +1 -1
- data/spec/integration/mappers/exclude_spec.rb +1 -1
- data/spec/integration/mappers/fold_spec.rb +1 -1
- data/spec/integration/mappers/group_spec.rb +1 -1
- data/spec/integration/mappers/overwrite_attributes_value_spec.rb +1 -1
- data/spec/integration/mappers/prefix_separator_spec.rb +1 -1
- data/spec/integration/mappers/prefix_spec.rb +1 -1
- data/spec/integration/mappers/prefixing_attributes_spec.rb +1 -1
- data/spec/integration/mappers/registering_custom_mappers_spec.rb +1 -1
- data/spec/integration/mappers/renaming_attributes_spec.rb +1 -1
- data/spec/integration/mappers/reusing_mappers_spec.rb +1 -1
- data/spec/integration/mappers/step_spec.rb +1 -1
- data/spec/integration/mappers/symbolizing_attributes_spec.rb +1 -1
- data/spec/integration/mappers/unfold_spec.rb +1 -1
- data/spec/integration/mappers/ungroup_spec.rb +1 -1
- data/spec/integration/mappers/unwrap_spec.rb +2 -2
- data/spec/integration/mappers/wrap_spec.rb +1 -1
- data/spec/integration/memory/commands/create_spec.rb +1 -1
- data/spec/integration/memory/commands/delete_spec.rb +1 -1
- data/spec/integration/memory/commands/update_spec.rb +1 -1
- data/spec/integration/multi_env_spec.rb +1 -1
- data/spec/integration/multi_repo_spec.rb +1 -1
- data/spec/integration/relations/default_dataset_spec.rb +1 -1
- data/spec/integration/relations/reading_spec.rb +1 -1
- data/spec/integration/relations/registry_dsl_spec.rb +1 -1
- data/spec/integration/setup_spec.rb +10 -4
- data/spec/shared/command_graph.rb +8 -4
- data/spec/shared/enumerable_dataset.rb +1 -1
- data/spec/spec_helper.rb +7 -9
- data/spec/support/schema.rb +14 -0
- data/spec/unit/rom/array_dataset_spec.rb +59 -0
- data/spec/unit/rom/association_set_spec.rb +4 -0
- data/spec/unit/rom/auto_curry_spec.rb +63 -0
- data/spec/unit/rom/commands/graph_spec.rb +12 -11
- data/spec/unit/rom/commands/lazy_spec.rb +8 -5
- data/spec/unit/rom/commands/pre_and_post_processors_spec.rb +269 -0
- data/spec/unit/rom/commands/result_spec.rb +1 -1
- data/spec/unit/rom/commands_spec.rb +9 -3
- data/spec/unit/rom/configuration_spec.rb +1 -1
- data/spec/unit/rom/container_spec.rb +11 -5
- data/spec/unit/rom/create_container_spec.rb +1 -1
- data/spec/unit/rom/enumerable_dataset_spec.rb +15 -0
- data/spec/unit/rom/gateway_spec.rb +1 -1
- data/spec/unit/rom/mapper_registry_spec.rb +1 -1
- data/spec/unit/rom/memory/commands_spec.rb +1 -1
- data/spec/unit/rom/memory/dataset_spec.rb +1 -1
- data/spec/unit/rom/memory/{repository_spec.rb → gateway_spec.rb} +1 -1
- data/spec/unit/rom/memory/inheritance_spec.rb +32 -0
- data/spec/unit/rom/memory/relation_spec.rb +15 -3
- data/spec/unit/rom/memory/storage_spec.rb +1 -1
- data/spec/unit/rom/plugin_spec.rb +1 -1
- data/spec/unit/rom/plugins/relation/key_inference_spec.rb +1 -1
- data/spec/unit/rom/registry_spec.rb +86 -0
- data/spec/unit/rom/relation/attribute_reader_spec.rb +17 -0
- data/spec/unit/rom/relation/composite_spec.rb +1 -1
- data/spec/unit/rom/relation/graph_spec.rb +1 -1
- data/spec/unit/rom/relation/lazy/combine_spec.rb +1 -1
- data/spec/unit/rom/relation/lazy_spec.rb +1 -1
- data/spec/unit/rom/relation/loaded_spec.rb +1 -1
- data/spec/unit/rom/relation/schema_spec.rb +10 -6
- data/spec/unit/rom/relation/view_spec.rb +112 -0
- data/spec/unit/rom/relation_spec.rb +16 -2
- data/spec/unit/rom/schema/accessing_attributes_spec.rb +52 -0
- data/spec/unit/rom/schema/exclude_spec.rb +15 -0
- data/spec/unit/rom/schema/finalize_spec.rb +59 -0
- data/spec/unit/rom/schema/key_predicate_spec.rb +15 -0
- data/spec/unit/rom/schema/merge_spec.rb +17 -0
- data/spec/unit/rom/schema/prefix_spec.rb +16 -0
- data/spec/unit/rom/schema/project_spec.rb +15 -0
- data/spec/unit/rom/schema/rename_spec.rb +22 -0
- data/spec/unit/rom/schema/type_spec.rb +49 -0
- data/spec/unit/rom/schema/wrap_spec.rb +17 -0
- data/spec/unit/rom/schema_spec.rb +2 -2
- metadata +69 -17
- data/lib/rom/plugins/relation/view/dsl.rb +0 -32
- data/lib/rom/plugins/relation/view.rb +0 -95
- data/spec/unit/rom/plugins/relation/view_spec.rb +0 -51
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'rom/registry'
|
2
|
+
|
3
|
+
RSpec.shared_examples_for 'registry fetch' do
|
4
|
+
it 'raises an ArgumentError when nil is used as a key' do
|
5
|
+
expect {
|
6
|
+
registry.public_send(fetch_method, nil)
|
7
|
+
}.to raise_error(ArgumentError, "key cannot be nil")
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'returns registered element identified by name' do
|
11
|
+
expect(registry.public_send(fetch_method, :mars)).to be(mars)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'raises error when element is not found' do
|
15
|
+
expect { registry.public_send(fetch_method, :twix) }.to raise_error(
|
16
|
+
ROM::Registry::ElementNotFoundError,
|
17
|
+
":twix doesn't exist in Candy registry"
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns the value from an optional block when key is not found' do
|
22
|
+
value = registry.public_send(fetch_method, :candy) { :twix }
|
23
|
+
|
24
|
+
expect(value).to eq(:twix)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'calls #to_sym on a key before fetching' do
|
28
|
+
expect(registry.public_send(fetch_method, double(to_sym: :mars))).to be(mars)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
RSpec.describe ROM::Registry do
|
33
|
+
subject(:registry) { registry_class.new(mars: mars) }
|
34
|
+
|
35
|
+
let(:mars) { double('mars') }
|
36
|
+
|
37
|
+
let(:registry_class) do
|
38
|
+
Class.new(ROM::Registry) do
|
39
|
+
def self.name
|
40
|
+
'Candy'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#fetch' do
|
46
|
+
let(:fetch_method) { :fetch }
|
47
|
+
|
48
|
+
it_behaves_like 'registry fetch'
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#[]' do
|
52
|
+
let(:fetch_method) { :[] }
|
53
|
+
|
54
|
+
it_behaves_like 'registry fetch'
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#method_missing' do
|
58
|
+
it 'returns registered element identified by name' do
|
59
|
+
expect(registry.mars).to be(mars)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'raises no-method error when element is not there' do
|
63
|
+
expect { registry.twix }.to raise_error(NoMethodError)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#key?' do
|
68
|
+
let(:mars) { double(to_sym: :mars) }
|
69
|
+
|
70
|
+
it 'calls #to_sym on a key before checking if it exists' do
|
71
|
+
registry.key?(:mars)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'returns true for an existing key' do
|
75
|
+
expect(registry.key?(:mars)).to be(true)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'returns false for a non-existing key' do
|
79
|
+
expect(registry.key?(:twix)).to be(false)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'returns false for a nil key' do
|
83
|
+
expect(registry.key?(nil)).to be(false)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rom/memory'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Relation, '#[]' do
|
4
|
+
it 'defines a canonical schema for a relation' do
|
5
|
+
class Test::Users < ROM::Relation[:memory]
|
6
|
+
schema do
|
7
|
+
attribute :id, Types::Int
|
8
|
+
attribute :name, Types::String
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
relation = Test::Users.new([])
|
13
|
+
|
14
|
+
expect(relation[:id]).to be(Test::Users.schema[:id])
|
15
|
+
expect(relation[:name]).to be(Test::Users.schema[:name])
|
16
|
+
end
|
17
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rom/memory'
|
3
3
|
|
4
|
-
describe ROM::Relation, '.schema' do
|
4
|
+
RSpec.describe ROM::Relation, '.schema' do
|
5
5
|
it 'defines a canonical schema for a relation' do
|
6
6
|
class Test::Users < ROM::Relation[:memory]
|
7
7
|
schema do
|
@@ -13,11 +13,15 @@ describe ROM::Relation, '.schema' do
|
|
13
13
|
|
14
14
|
Test::Users.schema.finalize!
|
15
15
|
|
16
|
-
|
16
|
+
relation_name = ROM::Relation::Name[:test_users]
|
17
|
+
|
18
|
+
schema = ROM::Memory::Schema.define(
|
17
19
|
ROM::Relation::Name.new(:test_users),
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
attributes: [
|
21
|
+
ROM::Memory::Types::Int.meta(primary_key: true, name: :id, source: relation_name),
|
22
|
+
ROM::Memory::Types::String.meta(name: :name, source: relation_name),
|
23
|
+
ROM::Memory::Types::Bool.meta(name: :admin, source: relation_name)
|
24
|
+
]
|
21
25
|
).finalize!
|
22
26
|
|
23
27
|
expect(Test::Users.schema.primary_key).to eql([Test::Users.schema[:id]])
|
@@ -111,7 +115,7 @@ describe ROM::Relation, '.schema' do
|
|
111
115
|
end
|
112
116
|
end
|
113
117
|
|
114
|
-
expect(Test::Users.schema[:admin]).to eql(ROM::Types::Bool.meta(name: :admin))
|
118
|
+
expect(Test::Users.schema[:admin]).to eql(ROM::Types::Bool.meta(name: :admin, source: ROM::Relation::Name[:test_users]))
|
115
119
|
end
|
116
120
|
end
|
117
121
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'rom'
|
2
|
+
require 'rom/memory'
|
3
|
+
|
4
|
+
RSpec.describe ROM::Relation do
|
5
|
+
subject(:relation) { relation_class.new(ROM::Memory::Dataset.new([])) }
|
6
|
+
|
7
|
+
shared_context 'relation with views' do
|
8
|
+
before do
|
9
|
+
relation << { id: 1, name: 'Joe' }
|
10
|
+
relation << { id: 2, name: 'Jane' }
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'uses projected schema for view schema' do
|
14
|
+
expect(relation.schemas[:names].map(&:name)).to eql(%i[name])
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'auto-projects the relation via schema' do
|
18
|
+
new_rel = relation_class.new([{ name: 'Jane' }, { name: 'Joe' }])
|
19
|
+
names_schema = relation_class.schemas[:names]
|
20
|
+
|
21
|
+
expect(names_schema).to receive(:call).with(relation).and_return(new_rel)
|
22
|
+
expect(relation.names).to eql(new_rel)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'auto-projects a restricted relation via schema' do
|
26
|
+
new_rel = relation_class.new([{ id: 2 }])
|
27
|
+
ids_schema = relation_class.schemas[:ids_for_names]
|
28
|
+
|
29
|
+
expect(ids_schema).to receive(:call).with(relation.restrict(name: ['Jane'])).and_return(new_rel)
|
30
|
+
expect(relation.ids_for_names(['Jane'])).to eql(new_rel)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with an explicit schema' do
|
35
|
+
before do
|
36
|
+
# this is normally called automatically during setup
|
37
|
+
relation_class.finalize({}, relation)
|
38
|
+
end
|
39
|
+
|
40
|
+
include_context 'relation with views' do
|
41
|
+
let(:relation_class) do
|
42
|
+
Class.new(ROM::Memory::Relation) do
|
43
|
+
schema(:users) do
|
44
|
+
attribute :id, ROM::Types::Int
|
45
|
+
attribute :name, ROM::Types::String
|
46
|
+
end
|
47
|
+
|
48
|
+
view(:names) do
|
49
|
+
schema do
|
50
|
+
project(:name)
|
51
|
+
end
|
52
|
+
|
53
|
+
relation do
|
54
|
+
self
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
view(:ids_for_names) do
|
59
|
+
schema do
|
60
|
+
project(:id)
|
61
|
+
end
|
62
|
+
|
63
|
+
relation do |names|
|
64
|
+
restrict(name: names)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'with an inferred schema' do
|
73
|
+
before do
|
74
|
+
# this is normally called automatically during setup
|
75
|
+
relation_class.schema.finalize!
|
76
|
+
relation_class.finalize({}, relation)
|
77
|
+
end
|
78
|
+
|
79
|
+
include_context 'relation with views' do
|
80
|
+
let(:relation_class) do
|
81
|
+
Class.new(ROM::Memory::Relation) do
|
82
|
+
schema_inferrer -> dataset, gateway {
|
83
|
+
[[ROM::Types::Int.meta(name: :id, source: :users),
|
84
|
+
ROM::Types::String.meta(name: :name, source: :users)], []]
|
85
|
+
}
|
86
|
+
|
87
|
+
schema(:users, infer: true)
|
88
|
+
|
89
|
+
view(:names) do
|
90
|
+
schema do
|
91
|
+
project(:name)
|
92
|
+
end
|
93
|
+
|
94
|
+
relation do
|
95
|
+
self
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
view(:ids_for_names) do
|
100
|
+
schema do
|
101
|
+
project(:id)
|
102
|
+
end
|
103
|
+
|
104
|
+
relation do |names|
|
105
|
+
restrict(name: names)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rom/memory'
|
2
2
|
|
3
|
-
describe ROM::Relation do
|
3
|
+
RSpec.describe ROM::Relation do
|
4
4
|
subject(:relation) { Class.new(ROM::Relation).new(dataset) }
|
5
5
|
|
6
6
|
let(:dataset) { ROM::Memory::Dataset.new([jane, joe]) }
|
@@ -196,7 +196,7 @@ describe ROM::Relation do
|
|
196
196
|
|
197
197
|
describe "#with" do
|
198
198
|
it "returns a new instance with the original dataset and given custom options" do
|
199
|
-
relation = Class.new(ROM::Relation) { option :custom }.new([])
|
199
|
+
relation = Class.new(ROM::Relation) { option :custom }.new([], custom: true)
|
200
200
|
|
201
201
|
custom_opts = { mappers: "Custom Mapper Registry" }
|
202
202
|
new_relation = relation.with(custom_opts).with(custom: true)
|
@@ -217,6 +217,20 @@ describe ROM::Relation do
|
|
217
217
|
end
|
218
218
|
end
|
219
219
|
|
220
|
+
describe '#schema' do
|
221
|
+
it 'returns an empty schema by default' do
|
222
|
+
relation = Class.new(ROM::Relation[:memory]) {
|
223
|
+
def self.name
|
224
|
+
'SomeRelation'
|
225
|
+
end
|
226
|
+
}.new([])
|
227
|
+
|
228
|
+
expect(relation.schema).to be_empty
|
229
|
+
expect(relation.schema.name).to be(:some_relation)
|
230
|
+
expect(relation.schema?).to be(false)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
220
234
|
describe '#schema_hash' do
|
221
235
|
it 'returns a schema hash type' do
|
222
236
|
relation = Class.new(ROM::Relation[:memory]) do
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#[]' do
|
4
|
+
context 'with a schema' do
|
5
|
+
subject(:schema) do
|
6
|
+
define_schema(:users, id: :Int, name: :String, email: :String)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'returns an attribute identified by its canonical name' do
|
10
|
+
expect(schema[:email]).to eql(define_type(:email, :String, source: :users))
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns an aliased attribute identified by its canonical name' do
|
14
|
+
expect(schema.rename(id: :user_id)[:id]).to eql(define_type(:id, :Int, source: :users, alias: :user_id))
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'raises KeyError when attribute is not found' do
|
18
|
+
expect { schema[:not_here] }.to raise_error(KeyError, /not_here/)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with a merged schema' do
|
23
|
+
subject(:schema) do
|
24
|
+
left.merge(right.__send__(:new, right.map { |attr| attr.meta(source: :tasks) }))
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:left) do
|
28
|
+
define_schema(:users, id: :Int, name: :String)
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:right) do
|
32
|
+
define_schema(:tasks, id: :Int, title: :String)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns an attribute identified by its canonical name' do
|
36
|
+
expect(schema[:id]).to eql(define_type(:id, :Int, source: :users))
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns an attribute identified by its canonical name when its unique' do
|
40
|
+
expect(schema[:title]).to eql(define_type(:title, :String, source: :tasks))
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns an attribute identified by its canonical name and its source' do
|
44
|
+
expect(schema[:id, :tasks]).to eql(define_type(:id, :Int, source: :tasks))
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'raises KeyError when attribute is not found' do
|
48
|
+
expect { schema[:not_here] }.to raise_error(KeyError, /not_here/)
|
49
|
+
expect { schema[:not_here, :tasks] }.to raise_error(KeyError, /not_here/)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#exclude' do
|
4
|
+
subject(:schema) do
|
5
|
+
define_schema(:users, id: :Int, name: :String, email: :String)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:excluded) do
|
9
|
+
schema.exclude(:id, :name)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns projected schema with renamed attributes using provided prefix' do
|
13
|
+
expect(excluded.map(&:name)).to eql(%i[email])
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#finalize!' do
|
4
|
+
context 'without inferrer' do
|
5
|
+
subject(:schema) do
|
6
|
+
define_schema(:users, id: :Int, name: :String)
|
7
|
+
end
|
8
|
+
|
9
|
+
before { schema.finalize! }
|
10
|
+
|
11
|
+
it 'returns a frozen canonical schema' do
|
12
|
+
expect(schema).to be_frozen
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'with inferrer' do
|
17
|
+
subject(:schema) do
|
18
|
+
ROM::Schema.define(:users, attributes: attributes, inferrer: inferrer)
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:inferrer) do
|
22
|
+
proc { [[define_type(:name, :String)], [:id, :age]]}
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when all required attributes are present' do
|
26
|
+
let(:attributes) do
|
27
|
+
[define_type(:id, :Int), define_type(:age, :Int)]
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'concats defined attributes with inferred attributes' do
|
31
|
+
expect(schema.finalize!.map(&:name)).to eql(%i[id age name])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when inferred attributes are overridden' do
|
36
|
+
let(:attributes) do
|
37
|
+
[define_type(:id, :Int),
|
38
|
+
define_type(:age, :Int),
|
39
|
+
define_type(:name, :String).meta(custom: true)]
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'respects overridden attributes' do
|
43
|
+
expect(schema.finalize!.map(&:name)).to eql(%i[id age name])
|
44
|
+
expect(schema[:name].meta[:custom]).to be(true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when some attributes are missing' do
|
49
|
+
let(:attributes) do
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'raises error' do
|
54
|
+
expect { schema.finalize! }.
|
55
|
+
to raise_error(ROM::Schema::MissingAttributesError, /missing attributes in :users schema: :id, :age/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#key?' do
|
4
|
+
subject(:schema) do
|
5
|
+
define_schema(:users, name: :String)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'returns true when an attribute exists' do
|
9
|
+
expect(schema.key?(:name)).to be(true)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns false when an attribute does not exist' do
|
13
|
+
expect(schema.key?(:foo)).to be(false)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#merge' do
|
4
|
+
subject(:schema) { left.merge(right) }
|
5
|
+
|
6
|
+
let(:left) do
|
7
|
+
define_schema(:users, id: :Int, name: :String)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:right) do
|
11
|
+
define_schema(:tasks, user_id: :Int)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns a new schema with attributes from two schemas' do
|
15
|
+
expect(schema.map(&:name)).to eql(%i[id name user_id])
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#prefix' do
|
4
|
+
subject(:schema) do
|
5
|
+
define_schema(:users, id: :Int, name: :String)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:prefixed) do
|
9
|
+
schema.prefix(:user)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns projected schema with renamed attributes using provided prefix' do
|
13
|
+
expect(prefixed.map(&:alias)).to eql(%i[user_id user_name])
|
14
|
+
expect(prefixed.map { |attr| attr.meta[:name] }).to eql(%i[id name])
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#project' do
|
4
|
+
subject(:schema) do
|
5
|
+
define_schema(:users, id: :Int, name: :String, age: :Int)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'projects provided attribute names' do
|
9
|
+
expect(schema.project(:name, :age).map(&:name)).to eql(%i[name age])
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'projects provided attributes' do
|
13
|
+
expect(schema.project(schema[:name], schema[:age]).map(&:name)).to eql(%i[name age])
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#rename' do
|
4
|
+
subject(:schema) do
|
5
|
+
define_schema(
|
6
|
+
:users,
|
7
|
+
user_id: :Int, user_name: :String, user_email: :String
|
8
|
+
)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:renamed) do
|
12
|
+
schema.rename(user_id: :id, user_name: :name)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns projected schema with renamed attributes' do
|
16
|
+
expect(renamed.map(&:name)).to eql(%i[user_id user_name user_email])
|
17
|
+
expect(renamed.map(&:alias)).to eql([:id, :name, nil])
|
18
|
+
expect(renamed.all?(&:aliased?)).to be(false)
|
19
|
+
expect(renamed[:user_id]).to be_aliased
|
20
|
+
expect(renamed[:user_name]).to be_aliased
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rom/schema/type'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema::Type do
|
4
|
+
describe '#inspect' do
|
5
|
+
context 'with a primitive definition' do
|
6
|
+
subject(:type) do
|
7
|
+
ROM::Schema::Type.new(ROM::Types::Int).meta(name: :id, primary_key: true)
|
8
|
+
end
|
9
|
+
|
10
|
+
specify do
|
11
|
+
expect(type.inspect).to eql("#<ROM::Schema::Type[Integer] name=:id primary_key=true>")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with a sum' do
|
16
|
+
subject(:type) do
|
17
|
+
ROM::Schema::Type.new(ROM::Types::Bool).meta(name: :admin)
|
18
|
+
end
|
19
|
+
|
20
|
+
specify do
|
21
|
+
expect(type.inspect).to eql("#<ROM::Schema::Type[TrueClass | FalseClass] name=:admin>")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#aliased' do
|
27
|
+
subject(:type) do
|
28
|
+
ROM::Schema::Type.new(ROM::Types::String).meta(name: :user_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
specify do
|
32
|
+
expect(type.as(:name).meta[:alias]).to eql(:name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#method_missing' do
|
37
|
+
subject(:type) do
|
38
|
+
ROM::Schema::Type.new(ROM::Types::Int).meta(name: :id, primary_key: true)
|
39
|
+
end
|
40
|
+
|
41
|
+
specify do
|
42
|
+
expect(type.meta).to eql(name: :id, primary_key: true)
|
43
|
+
end
|
44
|
+
|
45
|
+
specify do
|
46
|
+
expect { type.not_here }.to raise_error(NoMethodError, /not_here/)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rom/schema'
|
2
|
+
|
3
|
+
RSpec.describe ROM::Schema, '#wrap' do
|
4
|
+
subject(:schema) do
|
5
|
+
define_schema(:users, id: :Int, name: :String)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:wrapped) do
|
9
|
+
schema.wrap(:users)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns projected schema with renamed attributes using provided prefix' do
|
13
|
+
expect(wrapped.map(&:alias)).to eql(%i[users_id users_name])
|
14
|
+
expect(wrapped.map { |attr| attr.meta[:name] }).to eql(%i[id name])
|
15
|
+
expect(wrapped.all?(&:wrapped?)).to be(true)
|
16
|
+
end
|
17
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
RSpec.describe ROM::Schema do
|
2
2
|
describe '#to_h' do
|
3
3
|
it 'returns hash with attributes' do
|
4
|
-
attrs = { id: ROM::Types::Int, name: ROM::Types::String }
|
5
|
-
schema = ROM::Schema.
|
4
|
+
attrs = { id: ROM::Types::Int.meta(name: :id), name: ROM::Types::String.meta(name: :name) }
|
5
|
+
schema = ROM::Schema.define(:name, attributes: attrs.values)
|
6
6
|
|
7
7
|
expect(schema.to_h).to eql(attrs)
|
8
8
|
end
|