active_mapper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +62 -0
  9. data/Rakefile +1 -0
  10. data/active_mapper.gemspec +26 -0
  11. data/lib/active_mapper/adapter/active_record/order/attribute.rb +34 -0
  12. data/lib/active_mapper/adapter/active_record/order.rb +30 -0
  13. data/lib/active_mapper/adapter/active_record/query/attribute.rb +63 -0
  14. data/lib/active_mapper/adapter/active_record/query/expression.rb +63 -0
  15. data/lib/active_mapper/adapter/active_record/query.rb +23 -0
  16. data/lib/active_mapper/adapter/active_record.rb +96 -0
  17. data/lib/active_mapper/adapter/memory/order/attribute.rb +40 -0
  18. data/lib/active_mapper/adapter/memory/order.rb +31 -0
  19. data/lib/active_mapper/adapter/memory/query/attribute.rb +61 -0
  20. data/lib/active_mapper/adapter/memory/query/expression.rb +81 -0
  21. data/lib/active_mapper/adapter/memory/query.rb +22 -0
  22. data/lib/active_mapper/adapter/memory.rb +80 -0
  23. data/lib/active_mapper/adapter.rb +7 -0
  24. data/lib/active_mapper/mapper.rb +107 -0
  25. data/lib/active_mapper/relation.rb +133 -0
  26. data/lib/active_mapper/version.rb +3 -0
  27. data/lib/active_mapper.rb +24 -0
  28. data/spec/active_mapper/adapter/active_record/order_spec.rb +11 -0
  29. data/spec/active_mapper/adapter/active_record_spec.rb +164 -0
  30. data/spec/active_mapper/adapter/memory_spec.rb +158 -0
  31. data/spec/active_mapper/mapper_spec.rb +195 -0
  32. data/spec/active_mapper/relation_spec.rb +190 -0
  33. data/spec/active_mapper_spec.rb +25 -0
  34. data/spec/features/active_record_spec.rb +7 -0
  35. data/spec/features/memory_spec.rb +5 -0
  36. data/spec/spec_helper.rb +30 -0
  37. data/spec/support/models/user.rb +20 -0
  38. data/spec/support/shared/active_mapper_integration.rb +129 -0
  39. metadata +162 -0
@@ -0,0 +1,195 @@
1
+ require 'spec_helper'
2
+ describe ActiveMapper::Mapper do
3
+ let(:adapter) { ActiveMapper::Adapter::Memory.new }
4
+ let(:mapper) { ActiveMapper::Mapper.new(User, adapter) }
5
+ let(:user) { User.new(name: 'user', age: 28) }
6
+ let(:other_user) { User.new(name: 'other', age: 35) }
7
+
8
+ before do
9
+ mapper.save(user)
10
+ mapper.save(other_user)
11
+ end
12
+
13
+ describe '#all?' do
14
+ it 'is true when all objects match' do
15
+ expect(mapper.all? { |user| user.age > 18 }).to be_true
16
+ end
17
+
18
+ it 'is false when all objects do not match' do
19
+ expect(mapper.all? { |user| user.age > 28 }).to be_false
20
+ end
21
+ end
22
+
23
+ describe '#any?' do
24
+ it 'is true when any objects match' do
25
+ expect(mapper.any? { |user| user.age == 28 }).to be_true
26
+ end
27
+
28
+ it 'is false when no objects match' do
29
+ expect(mapper.any? { |user| user.age > 35 }).to be_false
30
+ end
31
+ end
32
+
33
+ describe '#none?' do
34
+ it 'is true when no objects match' do
35
+ expect(mapper.none? { |user| user.age == 18 }).to be_true
36
+ end
37
+
38
+ it 'is false when any objects match' do
39
+ expect(mapper.none? { |user| user.age == 28 }).to be_false
40
+ end
41
+ end
42
+
43
+ describe '#one?' do
44
+ it 'is true when one object matches' do
45
+ expect(mapper.one? { |user| user.age == 28 }).to be_true
46
+ end
47
+
48
+ it 'is false when no objects match' do
49
+ expect(mapper.one? { |user| user.age > 35 }).to be_false
50
+ end
51
+
52
+ it 'is false when more than one object matches' do
53
+ expect(mapper.one? { |user| user.age > 18 }).to be_false
54
+ end
55
+ end
56
+
57
+ describe '#count' do
58
+ it 'counts the all objects' do
59
+ expect(mapper.count).to eq(2)
60
+ end
61
+
62
+ it 'counts matching objects' do
63
+ expect(mapper.count { |user| user.age < 35 }).to eq(1)
64
+ end
65
+ end
66
+
67
+ describe '#min' do
68
+ it 'finds the minimum value' do
69
+ expect(mapper.min(:age)).to eq(28)
70
+ end
71
+ end
72
+
73
+ describe '#max' do
74
+ it 'finds the maximum value' do
75
+ expect(mapper.max(:age)).to eq(35)
76
+ end
77
+ end
78
+
79
+ describe '#minmax' do
80
+ it 'finds the minium and maximum values' do
81
+ expect(mapper.minmax(:age)).to eq([28, 35])
82
+ end
83
+ end
84
+
85
+ describe '#average' do
86
+ it 'finds the average value' do
87
+ expect(mapper.avg(:age)).to eq(31.5)
88
+ end
89
+ end
90
+
91
+ describe '#sum' do
92
+ it 'finds the total value' do
93
+ expect(mapper.sum(:age)).to eq(63)
94
+ end
95
+ end
96
+
97
+ describe '#find' do
98
+ it 'finds the object with the matching id' do
99
+ expect(mapper.find(user.id)).to eq(user)
100
+ end
101
+
102
+ it 'finds the first matching object' do
103
+ expect(mapper.find { |user| user.age > 21 }).to eq(user)
104
+ end
105
+ end
106
+
107
+ describe '#find_all' do
108
+ it 'finds all objects' do
109
+ expect(mapper.find_all.to_a).to eq([user, other_user])
110
+ end
111
+
112
+ it 'finds all matching objects' do
113
+ expect(mapper.find_all { |user| user.age < 30 }.to_a).to eq([user])
114
+ end
115
+ end
116
+
117
+ describe '#last' do
118
+ it 'finds the last matching object' do
119
+ expect(mapper.last { |user| user.age > 18 }).to eq(other_user)
120
+ end
121
+ end
122
+
123
+ describe '#select' do
124
+ it 'finds all matching objects' do
125
+ expect(mapper.select { |user| user.age < 30 }.to_a).to eq([user])
126
+ end
127
+ end
128
+
129
+ describe '#reject' do
130
+ it 'finds all non matching objects' do
131
+ expect(mapper.reject { |user| user.age == 28 }.to_a).to eq([other_user])
132
+ end
133
+ end
134
+
135
+ describe '#delete' do
136
+ it 'deletes the object' do
137
+ mapper.delete(user)
138
+
139
+ expect(mapper.find(user.id)).to be_nil
140
+ end
141
+ end
142
+
143
+ describe '#delete_if' do
144
+ it 'deletes all matching objects' do
145
+ mapper.delete_if { |user| user.age == 28 }
146
+
147
+ expect(mapper.find(user.id)).to be_nil
148
+ expect(mapper.find(other_user.id)).to eq(other_user)
149
+ end
150
+ end
151
+
152
+ describe '#clear' do
153
+ it 'deletes all objects' do
154
+ mapper.clear
155
+
156
+ expect(mapper.count).to eq(0)
157
+ end
158
+ end
159
+
160
+ describe '#keep_if' do
161
+ it 'deletes all non matching objects' do
162
+ mapper.keep_if { |user| user.age == 28 }
163
+
164
+ expect(mapper.find(user.id)).to eq(user)
165
+ expect(mapper.find(other_user.id)).to be_nil
166
+ end
167
+ end
168
+
169
+ describe '#save' do
170
+ before { mapper.clear }
171
+
172
+ it 'does not save invalid objects' do
173
+ user.stub(valid?: false)
174
+ expect(adapter).to_not receive(:insert)
175
+
176
+ expect(mapper.save(user)).to be_false
177
+ end
178
+
179
+ it 'creates unpersisted objects that are valid' do
180
+ user.stub(valid?: true)
181
+ user.id = nil
182
+
183
+ expect(adapter).to receive(:insert).with(User, user).and_return(1)
184
+ expect { mapper.save(user) }.to change(user, :id)
185
+ end
186
+
187
+ it 'updates persisted objects that are valid' do
188
+ user.stub(valid?: true)
189
+ mapper.save(user)
190
+
191
+ expect(adapter).to receive(:update).with(User, user)
192
+ expect { mapper.save(user) }.to_not change(user, :id)
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,190 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveMapper::Relation do
4
+ let(:adapter) { ActiveMapper::Adapter::Memory.new }
5
+ let(:user) { User.new(name: 'user', age: 28) }
6
+ let(:other_user) { User.new(name: 'other', age: 35) }
7
+
8
+ before do
9
+ user.id = adapter.insert(User, user)
10
+ other_user.id = adapter.insert(User, other_user)
11
+ end
12
+
13
+ def create_relation(&block)
14
+ ActiveMapper::Relation.new(User, adapter, &block)
15
+ end
16
+
17
+ describe '#any?' do
18
+ it 'is true when there are matching objects' do
19
+ relation = create_relation { |user| user.age == 28 }
20
+ expect(relation.any?).to be_true
21
+ end
22
+
23
+ it 'is false when there are no matching objects' do
24
+ relation = create_relation { |user| user.age == 18 }
25
+ expect(relation.any?).to be_false
26
+ end
27
+ end
28
+
29
+ describe '#none?' do
30
+ it 'is true when there are no matching objects' do
31
+ relation = create_relation { |user| user.age < 18 }
32
+
33
+ expect(relation.none?).to be_true
34
+ expect(relation.empty?).to be_true
35
+ end
36
+
37
+ it 'is false when there are matching objects' do
38
+ relation = create_relation { |user| user.age == 28 }
39
+
40
+ expect(relation.none?).to be_false
41
+ expect(relation.empty?).to be_false
42
+ end
43
+ end
44
+
45
+ describe '#one?' do
46
+ it 'is true when there is one matching object' do
47
+ relation = create_relation { |user| user.age == 28 }
48
+
49
+ expect(relation.one?).to be_true
50
+ end
51
+
52
+ it 'is false when there are no matching objects' do
53
+ relation = create_relation { |user| user.age < 18 }
54
+
55
+ expect(relation.one?).to be_false
56
+ end
57
+
58
+ it 'is false when there are is more than one matching object' do
59
+ relation = create_relation { |user| user.age > 18 }
60
+
61
+ expect(relation.one?).to be_false
62
+ end
63
+ end
64
+
65
+ describe '#count' do
66
+ it 'counts the number of matching objects' do
67
+ relation = create_relation { |user| user.age == 28 }
68
+
69
+ expect(relation.count).to eq(1)
70
+ expect(relation.length).to eq(1)
71
+ expect(relation.size).to eq(1)
72
+ end
73
+ end
74
+
75
+ describe '#min' do
76
+ it 'calculates the minimum value' do
77
+ expect(create_relation.min(:age)).to eql(28)
78
+ end
79
+ end
80
+
81
+ describe '#max' do
82
+ it 'calculates the maximum value' do
83
+ expect(create_relation.max(:age)).to eq(35)
84
+ end
85
+ end
86
+
87
+ describe '#minmax' do
88
+ it 'calculates the minimum and maximum values' do
89
+ expect(create_relation.minmax(:age)).to eq([28, 35])
90
+ end
91
+ end
92
+
93
+ describe '#avg' do
94
+ it 'calculates the average value' do
95
+ expect(create_relation.avg(:age)).to eq(31.5)
96
+ end
97
+ end
98
+
99
+ describe '#sum' do
100
+ it 'calculates the total value' do
101
+ expect(create_relation.sum(:age)).to eq(63)
102
+ end
103
+ end
104
+
105
+ describe '#drop' do
106
+ it 'offsets by the number of objects' do
107
+ expect(create_relation.drop(1).to_a).to eq([other_user])
108
+ end
109
+ end
110
+
111
+ describe '#select' do
112
+ it 'returns matching objects' do
113
+ relation = create_relation { |user| user.name == 'user' }.select { |user| user.age == 28 }.to_a
114
+
115
+ expect(relation).to include(user)
116
+ expect(relation).to_not include(other_user)
117
+ end
118
+ end
119
+
120
+ describe '#reject' do
121
+ it 'returns non matching objects' do
122
+ relation = create_relation { |user| user.age > 18 }.reject { |user| user.name == 'user' }.to_a
123
+
124
+ expect(relation).to include(other_user)
125
+ expect(relation).to_not include(user)
126
+ end
127
+ end
128
+
129
+ describe '#first' do
130
+ it 'returns the first matching object' do
131
+ expect(create_relation.first).to eq(user)
132
+ end
133
+
134
+ it 'returns the first number of matching objects' do
135
+ expect(create_relation.first(2)).to eq([user, other_user])
136
+ end
137
+ end
138
+
139
+ describe '#last' do
140
+ it 'returns the last matching object' do
141
+ expect(create_relation.last).to eq(other_user)
142
+ end
143
+
144
+ it 'returns the last number of matching objects' do
145
+ expect(create_relation.last(2)).to eq([other_user, user])
146
+ end
147
+ end
148
+
149
+ describe '#take' do
150
+ it 'limits the number of records returned' do
151
+ expect(create_relation.take(1).to_a).to eq([user])
152
+ end
153
+ end
154
+
155
+ describe '#to_a' do
156
+ it 'finds all matching objects' do
157
+ expect(create_relation { |user| user.age == 28 }.to_a).to eq([user])
158
+ end
159
+ end
160
+
161
+ describe '#map' do
162
+ it 'maps the objects' do
163
+ expect(create_relation.map(&:name)).to eq(['user', 'other'])
164
+ end
165
+ end
166
+
167
+ describe '#each' do
168
+ it 'iterates through the objects' do
169
+ create_relation { |user| user.age == 18 }.each { |u| expect(u).to eq(user) }
170
+ end
171
+ end
172
+
173
+ describe '#sort_by' do
174
+ it 'sorts the objects by attribute' do
175
+ relation = create_relation.sort_by(&:name).to_a
176
+
177
+ expect(relation.first).to eq(other_user)
178
+ expect(relation.last).to eq(user)
179
+ end
180
+ end
181
+
182
+ describe '#reverse' do
183
+ it 'sets the opposite direction to order by' do
184
+ relation = create_relation.sort_by(&:age).reverse.to_a
185
+
186
+ expect(relation.first).to eq(other_user)
187
+ expect(relation.last).to eq(user)
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveMapper do
4
+ describe '.[]' do
5
+ it 'returns the stored mapper' do
6
+ expect(ActiveMapper[User].mapped_class).to eql(User)
7
+ end
8
+ end
9
+
10
+ describe '.adapter' do
11
+ let(:adapter) { double('Adapter') }
12
+
13
+ it 'returns the adapter that has been set' do
14
+ ActiveMapper.adapter = adapter
15
+
16
+ expect(ActiveMapper.adapter).to eq(adapter)
17
+ end
18
+
19
+ it 'defaults to the memory store' do
20
+ ActiveMapper.adapter = nil
21
+
22
+ expect(ActiveMapper.adapter).to be_a(ActiveMapper::Adapter::Memory)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'ActiveMapper with ActiveRecord adapter' do
4
+ setup_active_record('active_record_integration')
5
+
6
+ it_should_behave_like 'ActiveMapper Integration', ActiveMapper::Adapter::ActiveRecord.new
7
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'ActiveMapper with Memory adapter' do
4
+ it_should_behave_like 'ActiveMapper Integration', ActiveMapper::Adapter::Memory.new
5
+ end
@@ -0,0 +1,30 @@
1
+ require 'active_record'
2
+ require 'active_mapper'
3
+
4
+ Dir['./spec/support/**/*.rb'].each { |f| require f }
5
+
6
+ # stop deprecation message
7
+ I18n.enforce_available_locales = false
8
+
9
+ class CreateUsers < ActiveRecord::Migration
10
+ def up
11
+ create_table :users do |t|
12
+ t.string :name
13
+ t.integer :age
14
+ t.timestamps
15
+ end
16
+ end
17
+ end
18
+
19
+ def setup_active_record(name)
20
+ db = "./spec/support/db/#{name}.sqlite3"
21
+
22
+ before(:all) do
23
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: db)
24
+ CreateUsers.new.migrate(:up)
25
+ end
26
+
27
+ after(:all) do
28
+ File.delete(db)
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ class User
2
+ include ActiveModel::Model
3
+
4
+ attr_accessor :id, :name, :age, :created_at, :updated_at
5
+
6
+ validates :name, presence: true
7
+ validates :age, presence: true, numericality: { only_integer: true }
8
+
9
+ def persisted?
10
+ id
11
+ end
12
+
13
+ def ==(other)
14
+ if id
15
+ id == other.id
16
+ else
17
+ object_id == other.object_id
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,129 @@
1
+ shared_examples_for 'ActiveMapper Integration' do |adapter|
2
+ let(:mapper) { ActiveMapper::Mapper.new(User, adapter) }
3
+ let(:user) { User.new(name: 'user', age: 28) }
4
+ let(:other_user) { User.new(name: 'other', age: 35) }
5
+
6
+ after { mapper.clear }
7
+
8
+ it 'can create and modify records' do
9
+ mapper.save(user)
10
+ user.name = 'Changed'
11
+ user.age = 18
12
+ mapper.save(user)
13
+
14
+ record = mapper.find(user.id)
15
+
16
+ expect(record.name).to eq('Changed')
17
+ expect(record.age).to eq(18)
18
+ end
19
+
20
+ it 'can delete records' do
21
+ mapper.save(user)
22
+ mapper.delete(user)
23
+
24
+ expect(mapper.find(user.id)).to be_nil
25
+
26
+ user.id = nil
27
+
28
+ mapper.save(user)
29
+ mapper.save(other_user)
30
+ mapper.clear
31
+
32
+ expect(mapper.count).to eq(0)
33
+
34
+ user.id = nil
35
+ other_user.id = nil
36
+
37
+ mapper.save(user)
38
+ mapper.save(other_user)
39
+ mapper.delete_if { |user| user.age < 35 }
40
+
41
+ expect(mapper.find(other_user.id)).to eq(other_user)
42
+ expect(mapper.find(user.id)).to be_nil
43
+
44
+ user.id = nil
45
+ other_user.id = nil
46
+
47
+ mapper.save(user)
48
+ mapper.save(other_user)
49
+ mapper.keep_if { |user| user.age < 35 }
50
+
51
+ expect(mapper.find(user.id)).to eq(user)
52
+ expect(mapper.find(other_user.id)).to be_nil
53
+ end
54
+
55
+ it 'can retrieve the first, last and all records' do
56
+ mapper.save(user)
57
+ mapper.save(other_user)
58
+
59
+ expect(mapper.first).to eq(user)
60
+ expect(mapper.last).to eq(other_user)
61
+
62
+ records = mapper.find_all.to_a
63
+
64
+ expect(records).to include(user)
65
+ expect(records).to include(other_user)
66
+ end
67
+
68
+ it 'can count records' do
69
+ mapper.save(user)
70
+ mapper.save(other_user)
71
+
72
+ expect(mapper.count).to eq(2)
73
+ expect(mapper.count { |user| user.age < 35 }).to eq(1)
74
+ end
75
+
76
+ it 'can query for records' do
77
+ mapper.save(user)
78
+ mapper.save(other_user)
79
+
80
+ expect(mapper.reject { |user| user.name == 'user' }.to_a).to eq([other_user])
81
+ expect(mapper.first { |user| user.name.in 'user' }).to eq(user)
82
+ expect(mapper.first { |user| user.name.not_in 'user' }).to eq(other_user)
83
+ expect(mapper.first { |user| user.name.starts_with 'us' }).to eq(user)
84
+ expect(mapper.first { |user| user.name.contains 'th' }).to eq(other_user)
85
+ expect(mapper.first { |user| user.name.ends_with 'er' }).to eq(user)
86
+ expect(mapper.first { |user| user.name == 'user' }).to eq(user)
87
+ expect(mapper.first { |user| user.name != 'user' }).to eq(other_user)
88
+ expect(mapper.first { |user| user.age > 30 }).to eq(other_user)
89
+ expect(mapper.first { |user| user.age >= 35 }).to eq(other_user)
90
+ expect(mapper.first { |user| user.age < 35 }).to eq(user)
91
+ expect(mapper.first { |user| user.age <= 28 }).to eq(user)
92
+ expect(mapper.first { |user| !(user.age == 28) }).to eq(other_user)
93
+ expect(mapper.first { |user| (user.name == 'user') & (user.age > 18) }).to eq(user)
94
+ expect(mapper.first { |user| (user.name == 'other') | (user.age == 35) }).to eq(other_user)
95
+ end
96
+
97
+ it 'can aggregate data' do
98
+ mapper.save(user)
99
+ mapper.save(other_user)
100
+
101
+ expect(mapper.max(:age)).to eq(35)
102
+ expect(mapper.min(:age)).to eq(28)
103
+ expect(mapper.minmax(:age)).to eq([28, 35])
104
+ expect(mapper.avg(:age)).to eq(31.5)
105
+ expect(mapper.sum(:age)).to eq(63)
106
+ end
107
+
108
+ it 'can sort records' do
109
+ other_user.age = user.age
110
+
111
+ mapper.save(user)
112
+ mapper.save(other_user)
113
+
114
+ records = mapper.find_all.sort_by { |user| [user.name, user.age] }.to_a
115
+
116
+ expect(records.first).to eq(other_user)
117
+ expect(records.last).to eq(user)
118
+
119
+ records = mapper.find_all.sort_by { |user| [user.age, -user.name] }.to_a
120
+
121
+ expect(records.first).to eq(user)
122
+ expect(records.last).to eq(other_user)
123
+
124
+ records = mapper.find_all.sort_by { |user| [user.age, -user.name] }.reverse.to_a
125
+
126
+ expect(records.first).to eq(other_user)
127
+ expect(records.last).to eq(user)
128
+ end
129
+ end