rom-mapper 0.2.0 → 0.3.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 +1 -1
- data/Gemfile +6 -3
- data/lib/rom-mapper.rb +1 -0
- data/lib/rom/header.rb +2 -4
- data/lib/rom/header/attribute.rb +6 -2
- data/lib/rom/mapper.rb +7 -9
- data/lib/rom/mapper/model_dsl.rb +4 -1
- data/lib/rom/mapper/version.rb +1 -1
- data/lib/rom/processor/transproc.rb +25 -6
- data/rom-mapper.gemspec +2 -3
- data/spec/integration/mapper_spec.rb +98 -0
- data/spec/unit/rom/mapper/model_dsl_spec.rb +19 -0
- data/spec/unit/rom/processor/transproc_spec.rb +25 -1
- metadata +12 -36
- data/lib/rom/mapper/header.rb +0 -85
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e261943dc4114a157a1f142045a0f5ee033dd5c5
|
4
|
+
data.tar.gz: 06c40a576ebf206f9719c161f332f43a5dbf075c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f3dd818d7f91c3c73828bd8ed93354e41183bd86d3a3a30c1f8a26bad02994a37ed86c22befc4fa473d11b788595805a015d41792226ba12947fd6af71a984f
|
7
|
+
data.tar.gz: d53d9d99ad4be33c2faf1eca94eff0cf05bd75966e2cf6267afda48c605d7551772f141d3cb1c0b4f370d9a6bf3d9344838b456f9abde81cd303f3774d994115
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -2,8 +2,11 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
+
gem 'transproc', github: 'solnic/transproc', branch: 'master'
|
6
|
+
gem 'rom-support', github: 'rom-rb/rom-support', branch: 'master'
|
7
|
+
|
5
8
|
group :test do
|
6
|
-
gem 'anima'
|
9
|
+
gem 'anima', '~> 0.2.0'
|
7
10
|
gem 'virtus'
|
8
11
|
gem 'inflecto', '~> 0.0', '>= 0.0.2'
|
9
12
|
|
@@ -13,7 +16,7 @@ group :test do
|
|
13
16
|
end
|
14
17
|
|
15
18
|
group :benchmarks do
|
16
|
-
gem 'benchmark-ips', '~> 2.2
|
19
|
+
gem 'benchmark-ips', '~> 2.2'
|
17
20
|
end
|
18
21
|
|
19
22
|
group :tools do
|
@@ -26,7 +29,7 @@ group :tools do
|
|
26
29
|
gem 'byebug'
|
27
30
|
|
28
31
|
platform :mri do
|
29
|
-
gem 'mutant', '
|
32
|
+
gem 'mutant', '~> 0.8.0'
|
30
33
|
gem 'mutant-rspec'
|
31
34
|
end
|
32
35
|
end
|
data/lib/rom-mapper.rb
CHANGED
data/lib/rom/header.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'equalizer'
|
2
|
-
|
3
1
|
require 'rom/header/attribute'
|
4
2
|
|
5
3
|
module ROM
|
@@ -11,7 +9,7 @@ module ROM
|
|
11
9
|
# @private
|
12
10
|
class Header
|
13
11
|
include Enumerable
|
14
|
-
include Equalizer
|
12
|
+
include Dry::Equalizer(:attributes, :model)
|
15
13
|
|
16
14
|
# @return [Class] optional model associated with a header
|
17
15
|
#
|
@@ -182,7 +180,7 @@ module ROM
|
|
182
180
|
#
|
183
181
|
# @api private
|
184
182
|
def initialize_tuple_keys
|
185
|
-
@tuple_keys = mapping.keys + non_primitives.flat_map(&:tuple_keys)
|
183
|
+
@tuple_keys = mapping.keys.flatten + non_primitives.flat_map(&:tuple_keys)
|
186
184
|
end
|
187
185
|
|
188
186
|
# Set all tuple keys from all attributes popping from Unwrap and Ungroup
|
data/lib/rom/header/attribute.rb
CHANGED
@@ -9,7 +9,7 @@ module ROM
|
|
9
9
|
#
|
10
10
|
# @private
|
11
11
|
class Attribute
|
12
|
-
include Equalizer
|
12
|
+
include Dry::Equalizer(:name, :key, :type)
|
13
13
|
|
14
14
|
# @return [Symbol] name of an attribute
|
15
15
|
#
|
@@ -93,6 +93,10 @@ module ROM
|
|
93
93
|
def mapping
|
94
94
|
{ key => name }
|
95
95
|
end
|
96
|
+
|
97
|
+
def union?
|
98
|
+
key.is_a? ::Array
|
99
|
+
end
|
96
100
|
end
|
97
101
|
|
98
102
|
# Embedded attribute is a special attribute type that has a header
|
@@ -101,7 +105,7 @@ module ROM
|
|
101
105
|
#
|
102
106
|
# @private
|
103
107
|
class Embedded < Attribute
|
104
|
-
include Equalizer
|
108
|
+
include Dry::Equalizer(:name, :key, :type, :header)
|
105
109
|
|
106
110
|
# return [Header] header of an attribute
|
107
111
|
#
|
data/lib/rom/mapper.rb
CHANGED
@@ -1,15 +1,12 @@
|
|
1
1
|
require 'rom/mapper/dsl'
|
2
2
|
|
3
|
-
require 'rom/support/inheritance_hook'
|
4
|
-
|
5
3
|
module ROM
|
6
4
|
# Mapper is a simple object that uses transformers to load relations
|
7
5
|
#
|
8
6
|
# @private
|
9
7
|
class Mapper
|
10
|
-
extend ROM::Support::InheritanceHook
|
11
8
|
include DSL
|
12
|
-
include Equalizer
|
9
|
+
include Dry::Equalizer(:transformers, :header)
|
13
10
|
|
14
11
|
defines :relation, :register_as, :symbolize_keys,
|
15
12
|
:prefix, :prefix_separator, :inherit_header, :reject_keys
|
@@ -62,9 +59,7 @@ module ROM
|
|
62
59
|
#
|
63
60
|
# @api private
|
64
61
|
def self.build(header = self.header, processor = :transproc)
|
65
|
-
|
66
|
-
transformers = headers(header).map(&processor.method(:build))
|
67
|
-
new(transformers, header)
|
62
|
+
new(header, processor)
|
68
63
|
end
|
69
64
|
|
70
65
|
# @api private
|
@@ -76,8 +71,11 @@ module ROM
|
|
76
71
|
end
|
77
72
|
|
78
73
|
# @api private
|
79
|
-
def initialize(
|
80
|
-
|
74
|
+
def initialize(header, processor = :transproc)
|
75
|
+
processor = Mapper.processors.fetch(processor)
|
76
|
+
@transformers = self.class.headers(header).map do |header|
|
77
|
+
processor.build(self, header)
|
78
|
+
end
|
81
79
|
@header = header
|
82
80
|
end
|
83
81
|
|
data/lib/rom/mapper/model_dsl.rb
CHANGED
@@ -48,7 +48,10 @@ module ROM
|
|
48
48
|
# @api private
|
49
49
|
def build_class
|
50
50
|
return klass if klass
|
51
|
-
|
51
|
+
included_attrs = attributes.reject do |_name, opts|
|
52
|
+
opts && opts[:exclude]
|
53
|
+
end
|
54
|
+
builder.call(included_attrs.map(&:first)) if builder
|
52
55
|
end
|
53
56
|
end
|
54
57
|
end
|
data/lib/rom/mapper/version.rb
CHANGED
@@ -21,6 +21,7 @@ module ROM
|
|
21
21
|
import ::Transproc::ArrayTransformations
|
22
22
|
import ::Transproc::HashTransformations
|
23
23
|
import ::Transproc::ClassTransformations
|
24
|
+
import ::Transproc::ProcTransformations
|
24
25
|
|
25
26
|
def self.identity(tuple)
|
26
27
|
tuple
|
@@ -29,8 +30,20 @@ module ROM
|
|
29
30
|
def self.filter_empty(arr)
|
30
31
|
arr.reject { |row| row.values.all?(&:nil?) }
|
31
32
|
end
|
33
|
+
|
34
|
+
def self.inject_union_value(tuple, name, keys, coercer)
|
35
|
+
values = tuple.values_at(*keys)
|
36
|
+
result = coercer.call(*values)
|
37
|
+
|
38
|
+
tuple.merge(name => result)
|
39
|
+
end
|
32
40
|
end
|
33
41
|
|
42
|
+
# @return [Mapper] mapper that this processor belongs to
|
43
|
+
#
|
44
|
+
# @api private
|
45
|
+
attr_reader :mapper
|
46
|
+
|
34
47
|
# @return [Header] header from a mapper
|
35
48
|
#
|
36
49
|
# @api private
|
@@ -58,12 +71,13 @@ module ROM
|
|
58
71
|
# @return [Transproc::Function]
|
59
72
|
#
|
60
73
|
# @api private
|
61
|
-
def self.build(header)
|
62
|
-
new(header).to_transproc
|
74
|
+
def self.build(mapper, header)
|
75
|
+
new(mapper, header).to_transproc
|
63
76
|
end
|
64
77
|
|
65
78
|
# @api private
|
66
|
-
def initialize(header)
|
79
|
+
def initialize(mapper, header)
|
80
|
+
@mapper = mapper
|
67
81
|
@header = header
|
68
82
|
@model = header.model
|
69
83
|
@mapping = header.mapping
|
@@ -111,8 +125,13 @@ module ROM
|
|
111
125
|
# @api private
|
112
126
|
def visit_attribute(attribute)
|
113
127
|
coercer = attribute.meta[:coercer]
|
114
|
-
if
|
115
|
-
|
128
|
+
if attribute.union?
|
129
|
+
compose do |ops|
|
130
|
+
ops << t(:inject_union_value, attribute.name, attribute.key, coercer)
|
131
|
+
ops << t(:reject_keys, attribute.key)
|
132
|
+
end
|
133
|
+
elsif coercer
|
134
|
+
t(:map_value, attribute.name, t(:bind, mapper, coercer))
|
116
135
|
elsif attribute.typed?
|
117
136
|
t(:map_value, attribute.name, t(:"to_#{attribute.type}"))
|
118
137
|
end
|
@@ -369,7 +388,7 @@ module ROM
|
|
369
388
|
#
|
370
389
|
# @api private
|
371
390
|
def row_proc_from(attribute)
|
372
|
-
new(attribute.header).row_proc
|
391
|
+
new(mapper, attribute.header).row_proc
|
373
392
|
end
|
374
393
|
|
375
394
|
# Return a new instance of the processor
|
data/rom-mapper.gemspec
CHANGED
@@ -15,9 +15,8 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.test_files = `git ls-files -- {spec}/*`.split("\n")
|
16
16
|
gem.license = 'MIT'
|
17
17
|
|
18
|
-
gem.add_dependency '
|
19
|
-
gem.add_dependency '
|
20
|
-
gem.add_dependency 'rom-support', '~> 0.1', '>= 0.1.0'
|
18
|
+
gem.add_dependency 'dry-equalizer', '~> 0.2'
|
19
|
+
gem.add_dependency 'rom-support', '~> 1.0.0.beta1'
|
21
20
|
|
22
21
|
gem.add_development_dependency 'rake', '~> 10.3'
|
23
22
|
gem.add_development_dependency 'rspec', '~> 3.3'
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ROM::Mapper do
|
4
|
+
let(:mapper_klass) do
|
5
|
+
Class.new(ROM::Mapper).tap do |mapper_klass|
|
6
|
+
mapper_klass.class_eval(&mapper_body)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
let(:mapper) { mapper_klass.build }
|
10
|
+
|
11
|
+
subject { mapper.call(tuples) }
|
12
|
+
|
13
|
+
describe '.attribute' do
|
14
|
+
context 'with block' do
|
15
|
+
let(:tuples) { [{ key: 'bar' }] }
|
16
|
+
let(:results) { [{ key: 'foo_bar' }] }
|
17
|
+
let(:mapper_body) do
|
18
|
+
proc do
|
19
|
+
attribute(:key) { |key| [prefix, key].join('_') }
|
20
|
+
|
21
|
+
def prefix
|
22
|
+
'foo'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'creates the attribute from the proc with the mapper as the binding' do
|
28
|
+
is_expected.to match_array(results)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '.embedded' do
|
34
|
+
context 'with block' do
|
35
|
+
let(:tuples) { [{ items: { key: 'bar' } }] }
|
36
|
+
let(:results) { [{ items: { key: 'foo_bar' } }] }
|
37
|
+
let(:mapper_body) do
|
38
|
+
proc do
|
39
|
+
embedded :items, type: :hash do
|
40
|
+
attribute(:key) { |key| [prefix, key].join('_') }
|
41
|
+
end
|
42
|
+
|
43
|
+
def prefix
|
44
|
+
'foo'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'creates the attribute from the proc with the mapper as the binding' do
|
50
|
+
is_expected.to match_array(results)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '.wrap' do
|
56
|
+
context 'attribute with block' do
|
57
|
+
let(:tuples) { [{ key: 'bar' }] }
|
58
|
+
let(:results) { [{ items: { key: 'foo_bar' } }] }
|
59
|
+
let(:mapper_body) do
|
60
|
+
proc do
|
61
|
+
wrap :items do
|
62
|
+
attribute(:key) { |key| [prefix, key].join('_') }
|
63
|
+
end
|
64
|
+
|
65
|
+
def prefix
|
66
|
+
'foo'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'creates the attribute from the proc with the mapper as the binding' do
|
72
|
+
is_expected.to match_array(results)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '.unwrap' do
|
78
|
+
context 'attribute with block' do
|
79
|
+
let(:tuples) { [{ items: { key: 'bar' } }] }
|
80
|
+
let(:results) { [{ key: 'foo_bar' }] }
|
81
|
+
let(:mapper_body) do
|
82
|
+
proc do
|
83
|
+
unwrap :items do
|
84
|
+
attribute(:key) { |key| [prefix, key].join('_') }
|
85
|
+
end
|
86
|
+
|
87
|
+
def prefix
|
88
|
+
'foo'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'creates the attribute from the proc with the mapper as the binding' do
|
94
|
+
is_expected.to match_array(results)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ROM::Mapper::ModelDSL do
|
4
|
+
describe '#model' do
|
5
|
+
it 'calls the builder with non-excluded attributes only' do
|
6
|
+
definition_class = Class.new do
|
7
|
+
include ROM::Mapper::ModelDSL
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@attributes = [[:name], [:title, { exclude: true }]]
|
11
|
+
@builder = ->(attrs) { Struct.new(*attrs) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
model_instance = definition_class.new.model.new
|
15
|
+
expect(model_instance).to respond_to(:name)
|
16
|
+
expect(model_instance).to_not respond_to(:title)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -2,8 +2,9 @@ require 'spec_helper'
|
|
2
2
|
require 'virtus'
|
3
3
|
|
4
4
|
describe ROM::Processor::Transproc do
|
5
|
-
subject(:transproc) { ROM::Processor::Transproc.build(header) }
|
5
|
+
subject(:transproc) { ROM::Processor::Transproc.build(binding, header) }
|
6
6
|
|
7
|
+
let(:binding) { nil }
|
7
8
|
let(:header) { ROM::Header.coerce(attributes, options) }
|
8
9
|
let(:options) { {} }
|
9
10
|
|
@@ -67,6 +68,29 @@ describe ROM::Processor::Transproc do
|
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
71
|
+
describe 'key from exsisting keys' do
|
72
|
+
let(:attributes) do
|
73
|
+
coercer = ->(a,b) { b + a }
|
74
|
+
[[:c, {from: [:a, :b], coercer: coercer} ]]
|
75
|
+
end
|
76
|
+
|
77
|
+
let(:relation) do
|
78
|
+
[
|
79
|
+
{a: 'works', b: 'this'}
|
80
|
+
]
|
81
|
+
end
|
82
|
+
|
83
|
+
let (:expected_result) do
|
84
|
+
[
|
85
|
+
{c: 'thisworks'}
|
86
|
+
]
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'returns tuples a new key added based on exsiting keys' do
|
90
|
+
expect(transproc[relation]).to eql(expected_result)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
70
94
|
describe 'rejecting keys' do
|
71
95
|
let(:options) { { reject_keys: true } }
|
72
96
|
|
metadata
CHANGED
@@ -1,69 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rom-mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: dry-equalizer
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: equalizer
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.0'
|
34
|
-
- - ">="
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: 0.0.10
|
37
|
-
type: :runtime
|
38
|
-
prerelease: false
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
requirements:
|
41
|
-
- - "~>"
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '0.0'
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: 0.0.10
|
26
|
+
version: '0.2'
|
47
27
|
- !ruby/object:Gem::Dependency
|
48
28
|
name: rom-support
|
49
29
|
requirement: !ruby/object:Gem::Requirement
|
50
30
|
requirements:
|
51
31
|
- - "~>"
|
52
32
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
54
|
-
- - ">="
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: 0.1.0
|
33
|
+
version: 1.0.0.beta1
|
57
34
|
type: :runtime
|
58
35
|
prerelease: false
|
59
36
|
version_requirements: !ruby/object:Gem::Requirement
|
60
37
|
requirements:
|
61
38
|
- - "~>"
|
62
39
|
- !ruby/object:Gem::Version
|
63
|
-
version:
|
64
|
-
- - ">="
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: 0.1.0
|
40
|
+
version: 1.0.0.beta1
|
67
41
|
- !ruby/object:Gem::Dependency
|
68
42
|
name: rake
|
69
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,7 +88,6 @@ files:
|
|
114
88
|
- lib/rom/mapper.rb
|
115
89
|
- lib/rom/mapper/attribute_dsl.rb
|
116
90
|
- lib/rom/mapper/dsl.rb
|
117
|
-
- lib/rom/mapper/header.rb
|
118
91
|
- lib/rom/mapper/model_dsl.rb
|
119
92
|
- lib/rom/mapper/version.rb
|
120
93
|
- lib/rom/model_builder.rb
|
@@ -124,10 +97,12 @@ files:
|
|
124
97
|
- rakelib/mutant.rake
|
125
98
|
- rakelib/rubocop.rake
|
126
99
|
- rom-mapper.gemspec
|
100
|
+
- spec/integration/mapper_spec.rb
|
127
101
|
- spec/spec_helper.rb
|
128
102
|
- spec/support/constant_leak_finder.rb
|
129
103
|
- spec/support/mutant.rb
|
130
104
|
- spec/unit/rom/mapper/dsl_spec.rb
|
105
|
+
- spec/unit/rom/mapper/model_dsl_spec.rb
|
131
106
|
- spec/unit/rom/mapper_spec.rb
|
132
107
|
- spec/unit/rom/processor/transproc_spec.rb
|
133
108
|
homepage: http://rom-rb.org
|
@@ -145,9 +120,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
145
120
|
version: '0'
|
146
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
122
|
requirements:
|
148
|
-
- - "
|
123
|
+
- - ">"
|
149
124
|
- !ruby/object:Gem::Version
|
150
|
-
version:
|
125
|
+
version: 1.3.1
|
151
126
|
requirements: []
|
152
127
|
rubyforge_project:
|
153
128
|
rubygems_version: 2.4.5
|
@@ -155,3 +130,4 @@ signing_key:
|
|
155
130
|
specification_version: 4
|
156
131
|
summary: ROM mapper component
|
157
132
|
test_files: []
|
133
|
+
has_rdoc:
|
data/lib/rom/mapper/header.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module ROM
|
4
|
-
class Mapper
|
5
|
-
|
6
|
-
# Mapper header wrapping axiom header and providing mapping information
|
7
|
-
#
|
8
|
-
# @private
|
9
|
-
class Header
|
10
|
-
include Enumerable, Concord.new(:header, :attributes), Adamantium
|
11
|
-
|
12
|
-
# Build a header
|
13
|
-
#
|
14
|
-
# @api private
|
15
|
-
def self.build(input, options = {})
|
16
|
-
return input if input.is_a?(self)
|
17
|
-
|
18
|
-
keys = options.fetch(:keys, [])
|
19
|
-
header = Axiom::Relation::Header.coerce(input, keys: keys)
|
20
|
-
|
21
|
-
mapping = options.fetch(:map, {})
|
22
|
-
attributes = header.each_with_object({}) { |field, object|
|
23
|
-
attribute = Attribute.coerce(field, mapping[field.name])
|
24
|
-
object[attribute.name] = attribute
|
25
|
-
}
|
26
|
-
|
27
|
-
new(header, attributes)
|
28
|
-
end
|
29
|
-
|
30
|
-
# Return attribute mapping
|
31
|
-
#
|
32
|
-
# @api private
|
33
|
-
def mapping
|
34
|
-
each_with_object({}) { |attribute, hash|
|
35
|
-
hash.update attribute.mapping
|
36
|
-
}
|
37
|
-
end
|
38
|
-
memoize :mapping
|
39
|
-
|
40
|
-
# Return all key attributes
|
41
|
-
#
|
42
|
-
# @return [Array<Attribute>]
|
43
|
-
#
|
44
|
-
# @api public
|
45
|
-
def keys
|
46
|
-
# FIXME: find a way to simplify this
|
47
|
-
header.keys.flat_map { |key_header|
|
48
|
-
key_header.flat_map { |key|
|
49
|
-
attributes.values.select { |attribute|
|
50
|
-
attribute.tuple_key == key.name
|
51
|
-
}
|
52
|
-
}
|
53
|
-
}
|
54
|
-
end
|
55
|
-
memoize :keys
|
56
|
-
|
57
|
-
# Return attribute with the given name
|
58
|
-
#
|
59
|
-
# @return [Attribute]
|
60
|
-
#
|
61
|
-
# @api public
|
62
|
-
def [](name)
|
63
|
-
attributes.fetch(name)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Return attribute names
|
67
|
-
#
|
68
|
-
# @api private
|
69
|
-
def attribute_names
|
70
|
-
map(&:name)
|
71
|
-
end
|
72
|
-
|
73
|
-
# Iterate over attributes
|
74
|
-
#
|
75
|
-
# @api private
|
76
|
-
def each(&block)
|
77
|
-
return to_enum unless block_given?
|
78
|
-
attributes.each_value(&block)
|
79
|
-
self
|
80
|
-
end
|
81
|
-
|
82
|
-
end # Header
|
83
|
-
|
84
|
-
end # Mapper
|
85
|
-
end # ROM
|