perpetuity 0.7.3 → 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile +3 -0
  4. data/README.md +18 -8
  5. data/lib/perpetuity.rb +4 -4
  6. data/lib/perpetuity/attribute.rb +9 -0
  7. data/lib/perpetuity/attribute_set.rb +4 -6
  8. data/lib/perpetuity/data_injectable.rb +1 -1
  9. data/lib/perpetuity/duplicator.rb +27 -0
  10. data/lib/perpetuity/mapper.rb +9 -14
  11. data/lib/perpetuity/version.rb +1 -1
  12. data/perpetuity.gemspec +0 -1
  13. data/spec/integration/associations_spec.rb +2 -6
  14. data/spec/integration/indexing_spec.rb +1 -1
  15. data/spec/integration/persistence_spec.rb +3 -2
  16. data/spec/integration/retrieval_spec.rb +5 -13
  17. data/spec/perpetuity/attribute_set_spec.rb +1 -1
  18. data/spec/perpetuity/attribute_spec.rb +6 -1
  19. data/spec/perpetuity/duplicator_spec.rb +35 -0
  20. data/spec/perpetuity/mapper_spec.rb +21 -2
  21. data/spec/perpetuity_spec.rb +2 -2
  22. data/spec/spec_helper.rb +8 -2
  23. data/spec/support/test_classes.rb +22 -26
  24. data/spec/support/test_classes/topic.rb +5 -0
  25. data/spec/support/test_classes/user.rb +1 -1
  26. metadata +7 -55
  27. data/lib/perpetuity/mongodb.rb +0 -230
  28. data/lib/perpetuity/mongodb/index.rb +0 -52
  29. data/lib/perpetuity/mongodb/nil_query.rb +0 -11
  30. data/lib/perpetuity/mongodb/query.rb +0 -33
  31. data/lib/perpetuity/mongodb/query_attribute.rb +0 -66
  32. data/lib/perpetuity/mongodb/query_expression.rb +0 -94
  33. data/lib/perpetuity/mongodb/query_intersection.rb +0 -16
  34. data/lib/perpetuity/mongodb/query_union.rb +0 -16
  35. data/lib/perpetuity/mongodb/serializer.rb +0 -174
  36. data/lib/perpetuity/validations.rb +0 -1
  37. data/lib/perpetuity/validations/length.rb +0 -36
  38. data/lib/perpetuity/validations/presence.rb +0 -14
  39. data/lib/perpetuity/validations/validation_set.rb +0 -28
  40. data/spec/integration/mongodb_spec.rb +0 -218
  41. data/spec/integration/validations_spec.rb +0 -17
  42. data/spec/perpetuity/mongodb/index_spec.rb +0 -44
  43. data/spec/perpetuity/mongodb/query_attribute_spec.rb +0 -58
  44. data/spec/perpetuity/mongodb/query_expression_spec.rb +0 -67
  45. data/spec/perpetuity/mongodb/query_intersection_spec.rb +0 -16
  46. data/spec/perpetuity/mongodb/query_spec.rb +0 -79
  47. data/spec/perpetuity/mongodb/query_union_spec.rb +0 -16
  48. data/spec/perpetuity/mongodb/serializer_spec.rb +0 -212
  49. data/spec/perpetuity/validations/length_spec.rb +0 -53
  50. data/spec/perpetuity/validations/presence_spec.rb +0 -30
  51. data/spec/perpetuity/validations_spec.rb +0 -87
@@ -1 +0,0 @@
1
- require 'perpetuity/validations/validation_set'
@@ -1,36 +0,0 @@
1
- module Perpetuity
2
- module Validations
3
- class Length
4
- def initialize attribute, options
5
- @attribute = attribute
6
- @at_least = nil
7
- @at_most = nil
8
- options.each do |option, value|
9
- send option, value
10
- end
11
- end
12
-
13
- def pass? object
14
- length = object.send(@attribute).length
15
-
16
- return false unless @at_least.nil? or @at_least <= length
17
- return false unless @at_most.nil? or @at_most >= length
18
-
19
- true
20
- end
21
-
22
- def at_least value
23
- @at_least = value
24
- end
25
-
26
- def at_most value
27
- @at_most = value
28
- end
29
-
30
- def between range
31
- at_least range.min
32
- at_most range.max
33
- end
34
- end
35
- end
36
- end
@@ -1,14 +0,0 @@
1
- module Perpetuity
2
- module Validations
3
- class Presence
4
- def initialize attribute
5
- @attribute = attribute
6
- end
7
-
8
- def pass? object
9
- !object.send(@attribute).nil? &&
10
- object.send(@attribute).strip != ''
11
- end
12
- end
13
- end
14
- end
@@ -1,28 +0,0 @@
1
- require 'perpetuity/validations/length'
2
- require 'perpetuity/validations/presence'
3
- require 'set'
4
-
5
- module Perpetuity
6
- class ValidationSet < Set
7
-
8
- def valid? object
9
- each do |validation|
10
- return false unless validation.pass?(object)
11
- end
12
-
13
- true
14
- end
15
-
16
- def invalid? object
17
- !valid? object
18
- end
19
-
20
- def present attribute
21
- self << Perpetuity::Validations::Presence.new(attribute)
22
- end
23
-
24
- def length attribute, options = {}
25
- self << Perpetuity::Validations::Length.new(attribute, options)
26
- end
27
- end
28
- end
@@ -1,218 +0,0 @@
1
- require 'perpetuity/mongodb'
2
- require 'date'
3
-
4
- module Perpetuity
5
- describe MongoDB do
6
- let(:mongo) { MongoDB.new db: 'perpetuity_gem_test' }
7
- let(:klass) { String }
8
- subject { mongo }
9
-
10
- it 'is not connected when instantiated' do
11
- mongo.should_not be_connected
12
- end
13
-
14
- it 'connects to its host' do
15
- mongo.connect
16
- mongo.should be_connected
17
- end
18
-
19
- it 'connects automatically when accessing the database' do
20
- mongo.database
21
- mongo.should be_connected
22
- end
23
-
24
- describe 'initialization params' do
25
- let(:host) { double('host') }
26
- let(:port) { double('port') }
27
- let(:db) { double('db') }
28
- let(:pool_size) { double('pool size') }
29
- let(:username) { double('username') }
30
- let(:password) { double('password') }
31
- let(:mongo) do
32
- MongoDB.new(
33
- host: host,
34
- port: port,
35
- db: db,
36
- pool_size: pool_size,
37
- username: username,
38
- password: password
39
- )
40
- end
41
- subject { mongo }
42
-
43
- its(:host) { should == host }
44
- its(:port) { should == port }
45
- its(:db) { should == db }
46
- its(:pool_size) { should == pool_size }
47
- its(:username) { should == username }
48
- its(:password) { should == password }
49
- end
50
-
51
- it 'inserts documents into a collection' do
52
- expect { mongo.insert klass, name: 'foo' }.to change { mongo.count klass }.by 1
53
- end
54
-
55
- it 'inserts multiple documents into a collection' do
56
- expect { mongo.insert klass, [{name: 'foo'}, {name: 'bar'}] }
57
- .to change { mongo.count klass }.by 2
58
- end
59
-
60
- it 'removes all documents from a collection' do
61
- mongo.insert klass, {}
62
- mongo.delete_all klass
63
- mongo.count(klass).should == 0
64
- end
65
-
66
- it 'counts the documents in a collection' do
67
- mongo.delete_all klass
68
- 3.times do
69
- mongo.insert klass, {}
70
- end
71
- mongo.count(klass).should == 3
72
- end
73
-
74
- it 'counts the documents matching a query' do
75
- mongo.delete_all klass
76
- 1.times { mongo.insert klass, { name: 'bar' } }
77
- 3.times { mongo.insert klass, { name: 'foo' } }
78
- mongo.count(klass) { |o| o.name == 'foo' }.should == 3
79
- end
80
-
81
- it 'gets the first document in a collection' do
82
- value = {value: 1}
83
- mongo.insert klass, value
84
- mongo.first(klass)[:hypothetical_value].should == value['value']
85
- end
86
-
87
- it 'gets all of the documents in a collection' do
88
- values = [{value: 1}, {value: 2}]
89
- mongo.should_receive(:retrieve).with(Object, mongo.nil_query, {})
90
- .and_return(values)
91
- mongo.all(Object).should == values
92
- end
93
-
94
- it 'retrieves by id if the id is a string' do
95
- time = Time.now.utc
96
- id = mongo.insert Object, {inserted: time}
97
-
98
- object = mongo.retrieve(Object, mongo.query{|o| o.id == id.to_s }).first
99
- retrieved_time = object["inserted"]
100
- retrieved_time.to_f.should be_within(0.001).of time.to_f
101
- end
102
-
103
- describe 'serialization' do
104
- let(:object) { Object.new }
105
- let(:foo_attribute) { double('Attribute', name: :foo) }
106
- let(:baz_attribute) { double('Attribute', name: :baz) }
107
- let(:mapper) { double('Mapper',
108
- mapped_class: Object,
109
- mapper_registry: {},
110
- attribute_set: Set[foo_attribute, baz_attribute],
111
- data_source: mongo,
112
- ) }
113
-
114
- before do
115
- object.instance_variable_set :@foo, 'bar'
116
- object.instance_variable_set :@baz, 'quux'
117
- end
118
-
119
- it 'serializes objects' do
120
- mongo.serialize(object, mapper).should == {
121
- 'foo' => 'bar',
122
- 'baz' => 'quux'
123
- }
124
- end
125
-
126
- it 'can serialize only modified attributes of objects' do
127
- updated = object.dup
128
- updated.instance_variable_set :@foo, 'foo'
129
-
130
- serialized = mongo.serialize_changed_attributes(updated, object, mapper)
131
- serialized.should == { 'foo' => 'foo' }
132
- end
133
- end
134
-
135
- describe 'serializable objects' do
136
- let(:serializable_values) { [nil, true, false, 1, 1.2, '', [], {}, Time.now] }
137
-
138
- it 'can insert serializable values' do
139
- serializable_values.each do |value|
140
- mongo.insert(Object, {value: value}).should be_a Moped::BSON::ObjectId
141
- mongo.can_serialize?(value).should be_true
142
- end
143
- end
144
- end
145
-
146
- it 'generates a new query DSL object' do
147
- mongo.query { |object| object.whatever == 1 }.should respond_to :to_db
148
- end
149
-
150
- describe 'indexing' do
151
- let(:collection) { Object }
152
- let(:key) { 'object_id' }
153
-
154
- before { mongo.index collection, key }
155
- after { mongo.drop_collection collection }
156
-
157
- it 'adds indexes for the specified key on the specified collection' do
158
- indexes = mongo.indexes(collection).select{ |index| index.attribute == 'object_id' }
159
- indexes.should_not be_empty
160
- indexes.first.order.should be :ascending
161
- end
162
-
163
- it 'adds descending-order indexes' do
164
- index = mongo.index collection, 'hash', order: :descending
165
- index.order.should be :descending
166
- end
167
-
168
- it 'creates indexes on the database collection' do
169
- mongo.delete_all collection
170
- index = mongo.index collection, 'real_index', order: :descending, unique: true
171
- mongo.activate_index! index
172
-
173
- mongo.active_indexes(collection).should include index
174
- end
175
-
176
- it 'removes indexes' do
177
- mongo.drop_collection collection
178
- index = mongo.index collection, 'real_index', order: :descending, unique: true
179
- mongo.activate_index! index
180
- mongo.remove_index index
181
- mongo.active_indexes(collection).should_not include index
182
- end
183
- end
184
-
185
- describe 'atomic operations' do
186
- after(:all) { mongo.delete_all klass }
187
-
188
- it 'increments the value of an attribute' do
189
- id = mongo.insert klass, count: 1
190
- mongo.increment klass, id, :count
191
- mongo.increment klass, id, :count, 10
192
- query = mongo.query { |o| o.id == id }
193
- mongo.retrieve(klass, query).first['count'].should be == 12
194
- mongo.increment klass, id, :count, -1
195
- mongo.retrieve(klass, query).first['count'].should be == 11
196
- end
197
- end
198
-
199
- describe 'operation errors' do
200
- let(:data) { { foo: 'bar' } }
201
- let(:index) { mongo.index Object, :foo, unique: true }
202
-
203
- before do
204
- mongo.delete_all Object
205
- mongo.activate_index! index
206
- end
207
-
208
- after { mongo.drop_collection Object }
209
-
210
- it 'raises an exception when insertion fails' do
211
- mongo.insert Object, data
212
-
213
- expect { mongo.insert Object, data }.to raise_error DuplicateKeyError,
214
- 'Tried to insert Object with duplicate unique index: foo => "bar"'
215
- end
216
- end
217
- end
218
- end
@@ -1,17 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/test_classes'
3
-
4
- describe 'validations' do
5
- let(:car_mapper) { Perpetuity[Car] }
6
-
7
- it 'raises an exception when inserting an invalid object' do
8
- car = Car.new
9
- expect { car_mapper.insert car }.to raise_error
10
- end
11
-
12
- it 'does not raise an exception when validations are met' do
13
- car = Car.new
14
- car.make = "Volkswagen"
15
- expect { car_mapper.insert car }.not_to raise_error
16
- end
17
- end
@@ -1,44 +0,0 @@
1
- require 'perpetuity/mongodb/index'
2
-
3
- module Perpetuity
4
- class MongoDB
5
- describe Index do
6
- let(:attribute) { double(name: 'name') }
7
- let(:index) { Index.new(Object, attribute) }
8
-
9
- it 'is not active by default' do
10
- index.should_not be_active
11
- end
12
-
13
- it 'can be activated' do
14
- index.activate!
15
- index.should be_active
16
- end
17
-
18
- it 'can be unique' do
19
- index = Index.new(Object, attribute, unique: true)
20
- index.should be_unique
21
- end
22
-
23
- it 'is not unique by default' do
24
- index.should_not be_unique
25
- end
26
-
27
- describe 'index ordering' do
28
- it 'can be ordered in ascending order' do
29
- index = Index.new(Object, attribute, order: :ascending)
30
- index.order.should be :ascending
31
- end
32
-
33
- it 'is ordered ascending by default' do
34
- index.order.should be :ascending
35
- end
36
-
37
- it 'can be ordered in descending order' do
38
- index = Index.new(Object, attribute, order: :descending)
39
- index.order.should be :descending
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,58 +0,0 @@
1
- require 'perpetuity/mongodb/query_attribute'
2
-
3
- module Perpetuity
4
- describe MongoDB::QueryAttribute do
5
- let(:attribute) { MongoDB::QueryAttribute.new :attribute_name }
6
- subject { attribute }
7
-
8
- its(:name) { should == :attribute_name }
9
-
10
- it 'allows checking subattributes' do
11
- attribute.title.name.should == :'attribute_name.title'
12
- end
13
-
14
- it 'wraps .id subattribute in metadata' do
15
- attribute.id.name.should == :'attribute_name.__metadata__.id'
16
- end
17
-
18
- it 'wraps .klass subattribute in metadata' do
19
- attribute.klass.name.should == :'attribute_name.__metadata__.class'
20
- end
21
-
22
- it 'checks for equality' do
23
- (attribute == 1).should be_a MongoDB::QueryExpression
24
- end
25
-
26
- it 'checks for less than' do
27
- (attribute < 1).should be_a MongoDB::QueryExpression
28
- end
29
-
30
- it 'checks for <=' do
31
- (attribute <= 1).should be_a MongoDB::QueryExpression
32
- end
33
-
34
- it 'checks for greater than' do
35
- (attribute > 1).should be_a MongoDB::QueryExpression
36
- end
37
-
38
- it 'checks for >=' do
39
- (attribute >= 1).should be_a MongoDB::QueryExpression
40
- end
41
-
42
- it 'checks for inequality' do
43
- (attribute != 1).should be_a MongoDB::QueryExpression
44
- end
45
-
46
- it 'checks for regexp matches' do
47
- (attribute =~ /value/).should be_a MongoDB::QueryExpression
48
- end
49
-
50
- it 'checks for inclusion' do
51
- (attribute.in [1, 2, 3]).should be_a MongoDB::QueryExpression
52
- end
53
-
54
- it 'checks for its own truthiness' do
55
- attribute.to_db.should == ((attribute != false) & (attribute != nil)).to_db
56
- end
57
- end
58
- end
@@ -1,67 +0,0 @@
1
- require 'perpetuity/mongodb/query_expression'
2
-
3
- module Perpetuity
4
- describe MongoDB::QueryExpression do
5
- let(:expression) { MongoDB::QueryExpression.new :attribute, :equals, :value }
6
- subject { expression }
7
-
8
- describe 'translation to Mongo expressions' do
9
- it 'equality expression' do
10
- expression.to_db.should == { attribute: :value }
11
- end
12
-
13
- it 'less-than expression' do
14
- expression.comparator = :less_than
15
- expression.to_db.should == { attribute: { '$lt' => :value } }
16
- end
17
-
18
- it 'less-than-or-equal-to expression' do
19
- expression.comparator = :lte
20
- expression.to_db.should == { attribute: { '$lte' => :value } }
21
- end
22
-
23
- it 'greater-than expression' do
24
- expression.comparator = :greater_than
25
- expression.to_db.should == { attribute: { '$gt' => :value } }
26
- end
27
-
28
- it 'greater-than-or-equal-to expression' do
29
- expression.comparator = :gte
30
- expression.to_db.should == { attribute: { '$gte' => :value } }
31
- end
32
-
33
- it 'not-equal' do
34
- expression.comparator = :not_equal
35
- expression.to_db.should == { attribute: { '$ne' => :value } }
36
- end
37
-
38
- it 'checks for inclusion' do
39
- expression.comparator = :in
40
- expression.to_db.should == { attribute: { '$in' => :value } }
41
- end
42
-
43
- it 'checks for regexp matching' do
44
- expression.comparator = :matches
45
- expression.to_db.should == { attribute: :value }
46
- end
47
- end
48
-
49
- describe 'unions' do
50
- let(:lhs) { MongoDB::QueryExpression.new :first, :equals, :one }
51
- let(:rhs) { MongoDB::QueryExpression.new :second, :equals, :two }
52
-
53
- it 'converts | to an $or query' do
54
- (lhs | rhs).to_db.should == { '$or' => [{first: :one}, {second: :two}] }
55
- end
56
- end
57
-
58
- describe 'intersections' do
59
- let(:lhs) { MongoDB::QueryExpression.new :first, :equals, :one }
60
- let(:rhs) { MongoDB::QueryExpression.new :second, :equals, :two }
61
-
62
- it 'converts & to an $and query' do
63
- (lhs & rhs).to_db.should == { '$and' => [{first: :one}, {second: :two}] }
64
- end
65
- end
66
- end
67
- end