rom 0.6.0.beta3 → 0.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -101,8 +101,8 @@ describe ROM::Setup do
101
101
  expect(env.relations).to eql(ROM::RelationRegistry.new)
102
102
  end
103
103
 
104
- it 'builds empty readers' do
105
- expect(env.readers).to eql(ROM::ReaderRegistry.new)
104
+ it 'builds empty mappers' do
105
+ expect(env.mappers).to eql(ROM::Registry.new)
106
106
  end
107
107
 
108
108
  it 'builds empty commands' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0.beta3
4
+ version: 0.6.0.rc1
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-03-03 00:00:00.000000000 Z
11
+ date: 2015-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: transproc
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.1.2
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
29
  version: '0.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.1.2
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: equalizer
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -152,8 +158,8 @@ files:
152
158
  - lib/rom/model_builder.rb
153
159
  - lib/rom/processor.rb
154
160
  - lib/rom/processor/transproc.rb
155
- - lib/rom/reader.rb
156
161
  - lib/rom/relation.rb
162
+ - lib/rom/relation/class_interface.rb
157
163
  - lib/rom/relation/composite.rb
158
164
  - lib/rom/relation/curried.rb
159
165
  - lib/rom/relation/lazy.rb
@@ -220,7 +226,6 @@ files:
220
226
  - spec/unit/rom/memory/storage_spec.rb
221
227
  - spec/unit/rom/model_builder_spec.rb
222
228
  - spec/unit/rom/processor/transproc_spec.rb
223
- - spec/unit/rom/reader_spec.rb
224
229
  - spec/unit/rom/registry_spec.rb
225
230
  - spec/unit/rom/relation/composite_spec.rb
226
231
  - spec/unit/rom/relation/lazy_spec.rb
data/lib/rom/reader.rb DELETED
@@ -1,174 +0,0 @@
1
- module ROM
2
- # Exposes mapped tuples via enumerable interface
3
- #
4
- # See example for each method
5
- #
6
- # @api public
7
- class Reader
8
- include Enumerable
9
- include Equalizer.new(:path, :relation, :mapper)
10
-
11
- # Map relation to an array using a mapper
12
- #
13
- # @return [Array]
14
- #
15
- # @api public
16
- alias_method :to_ary, :to_a
17
-
18
- # @return [String] access path used to read a relation
19
- #
20
- # @api private
21
- attr_reader :path
22
-
23
- # @return [Relation] relation used by the reader
24
- #
25
- # @api private
26
- attr_reader :relation
27
-
28
- # @return [MapperRegistry] registry of mappers used by the reader
29
- #
30
- # @api private
31
- attr_reader :mappers
32
-
33
- # @return [Mapper] mapper to read the relation
34
- #
35
- # @api private
36
- attr_reader :mapper
37
-
38
- # Builds a reader instance for the provided relation
39
- #
40
- # @param [Symbol] name of the root relation
41
- # @param [Relation] relation that the reader will use
42
- # @param [MapperRegistry] mappers registry of mappers
43
- # @param [Array<Symbol>] method_names a list of method names exposed by the relation
44
- #
45
- # @return [Reader]
46
- #
47
- # @api private
48
- def self.build(name, relation, mappers, method_names = [])
49
- klass = build_class(relation, method_names)
50
- klass.new(name, relation, mappers)
51
- end
52
-
53
- # Build a reader subclass for the relation
54
- #
55
- # This method defines public methods on the class narrowing down data access
56
- # only to the methods exposed by a given relation
57
- #
58
- # @param [Relation] relation that the reader will use
59
- # @param [Array<Symbol>] method_names a list of method names exposed by the relation
60
- #
61
- # @return [Class]
62
- #
63
- # @api private
64
- def self.build_class(relation, method_names)
65
- klass_name = "#{Reader.name}[#{Inflector.camelize(relation.name)}]"
66
-
67
- ClassBuilder.new(name: klass_name, parent: Reader).call do |klass|
68
- method_names.each do |method_name|
69
- klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
70
- def #{method_name}(*args, &block)
71
- new_relation = relation.send(#{method_name.inspect}, *args, &block)
72
- self.class.new(
73
- new_path(#{method_name.to_s.inspect}), new_relation, mappers
74
- )
75
- end
76
- RUBY
77
- end
78
- end
79
- end
80
-
81
- # @api private
82
- def initialize(path, relation, mappers, mapper = nil)
83
- @path = path.to_s
84
- @relation = relation
85
- @mappers = mappers
86
- @mapper = mapper || mappers.by_path(@path)
87
- end
88
-
89
- # @api private
90
- def header
91
- mapper.header
92
- end
93
-
94
- # Yields tuples mapped to objects
95
- #
96
- # @example
97
- #
98
- # # accessing root relation
99
- # rom.read(:users).each { |user| # ... }
100
- #
101
- # # accessing virtual relations
102
- # rom.read(:users).adults.recent.active.each { |user| # ... }
103
- #
104
- # @api public
105
- def each
106
- mapper.call(relation).each { |tuple| yield(tuple) }
107
- end
108
-
109
- # Returns a single tuple from the relation if there is one.
110
- #
111
- # @raise [ROM::TupleCountMismatchError] if the relation contains more than
112
- # one tuple
113
- #
114
- # @api public
115
- def one
116
- if relation.count > 1
117
- raise(
118
- TupleCountMismatchError,
119
- 'The relation consists of more than one tuple'
120
- )
121
- else
122
- mapper.call(relation).first
123
- end
124
- end
125
-
126
- # Like [one], but additionally raises an error if the relation is empty.
127
- #
128
- # @raise [ROM::TupleCountMismatchError] if the relation does not contain
129
- # exactly one tuple
130
- #
131
- # @api public
132
- def one!
133
- one || raise(
134
- TupleCountMismatchError,
135
- 'The relation does not contain any tuples'
136
- )
137
- end
138
-
139
- # Map tuples using a specific mapper if name is provided
140
- #
141
- # Defaults to Enumerable#map behavior
142
- #
143
- # @example
144
- #
145
- # rom.read(:users).map(:my_mapper_name)
146
- # rom.read(:users).map { |user| ... }
147
- #
148
- # @return [Array,Reader]
149
- #
150
- # @api public
151
- def map(*args)
152
- if args.any?
153
- mappers[args[0]].call(relation)
154
- else
155
- super
156
- end
157
- end
158
-
159
- private
160
-
161
- # @api private
162
- def method_missing(name, *)
163
- raise(
164
- NoRelationError,
165
- "undefined relation #{name.inspect} within #{path.inspect}"
166
- )
167
- end
168
-
169
- # @api private
170
- def new_path(name)
171
- path.dup << ".#{name}"
172
- end
173
- end
174
- end
@@ -1,146 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ROM::Reader do
4
- subject(:reader) { ROM::Reader.new(name, relation, mappers) }
5
-
6
- let(:name) { :users }
7
- let(:relation) { [jane, joe] }
8
- let(:jane) { { name: 'Jane' } }
9
- let(:joe) { { name: 'Joe' } }
10
- let(:mappers) { ROM::MapperRegistry.new(users: mapper) }
11
- let(:mapper) { double('mapper', header: []) }
12
-
13
- describe '.build' do
14
- subject(:reader) do
15
- ROM::Reader.build(name, relation, mappers, [:all])
16
- end
17
-
18
- before do
19
- relation.instance_exec do
20
- def name
21
- 'users'
22
- end
23
-
24
- def all(*_args)
25
- find_all
26
- end
27
- end
28
- end
29
-
30
- it 'sets reader class name' do
31
- expect(reader.class.name).to eql("ROM::Reader[Users]")
32
- end
33
-
34
- it 'defines methods from relation' do
35
- block = proc {}
36
-
37
- user_id = 1
38
-
39
- expect(relation).to receive(:all)
40
- .with(user_id, &block)
41
- .and_return([joe])
42
-
43
- expect(mapper).to receive(:call)
44
- .with([joe])
45
- .and_return([joe])
46
-
47
- result = reader.all(user_id, &block)
48
-
49
- expect(result.path).to eql('users.all')
50
- expect(result.to_a).to eql([joe])
51
- end
52
-
53
- it 'raises error when relation does not respond to the method' do
54
- expect { reader.not_here }
55
- .to raise_error(ROM::NoRelationError, /not_here/)
56
- end
57
-
58
- it 'raises error when relation does not respond to the method with args' do
59
- expect { reader.find_by_id(1) }
60
- .to raise_error(ROM::NoRelationError, /find_by_id/)
61
- end
62
- end
63
-
64
- describe '#initialize' do
65
- it 'raises error when mapper cannot be found' do
66
- expect { ROM::Reader.new(:not_here, relation, mappers) }
67
- .to raise_error(ROM::MapperMissingError, /not_here/)
68
- end
69
- end
70
-
71
- describe '#each' do
72
- it 'yields mapped tuples from relations' do
73
- expect(mapper).to receive(:call)
74
- .with(relation)
75
- .and_return(relation)
76
-
77
- result = []
78
- reader.each { |user| result << user }
79
- expect(result).to eql([jane, joe])
80
- end
81
- end
82
-
83
- shared_examples_for 'one and one!' do |method|
84
- context 'with a single tuple' do
85
- let(:relation) { [jane] }
86
-
87
- it 'returns a single tuple' do
88
- expect(mapper).to receive(:call)
89
- .with(relation)
90
- .and_return(relation)
91
-
92
- expect(reader.public_send(method)).to eql(jane)
93
- end
94
- end
95
-
96
- context 'with more than one tuple' do
97
- it 'raises an error' do
98
- expect { reader.public_send(method) }
99
- .to raise_error(ROM::TupleCountMismatchError)
100
- end
101
- end
102
- end
103
-
104
- describe '#one' do
105
- it_should_behave_like 'one and one!', :one
106
-
107
- context 'without any tuple' do
108
- let(:relation) { [] }
109
-
110
- it 'returns nil' do
111
- expect(mapper).to receive(:call)
112
- .with(relation)
113
- .and_return(relation)
114
-
115
- expect(reader.one).to be_nil
116
- end
117
- end
118
- end
119
-
120
- describe '#one!' do
121
- it_should_behave_like 'one and one!', :one!
122
-
123
- context 'without any tuple' do
124
- let(:relation) { [] }
125
-
126
- it 'raises an error' do
127
- expect(mapper).to receive(:call)
128
- .with(relation)
129
- .and_return(relation)
130
-
131
- expect { reader.one! }.to raise_error(ROM::TupleCountMismatchError)
132
- end
133
- end
134
- end
135
-
136
- describe '#to_ary' do
137
- it 'casts relation to an array with loaded objects' do
138
- expect(mapper).to receive(:call)
139
- .with(relation)
140
- .and_return(relation)
141
-
142
- result = reader.to_ary
143
- expect(result).to eql(relation)
144
- end
145
- end
146
- end