perpetuity 1.0.0.beta → 1.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -2
- data/CHANGELOG.md +8 -0
- data/README.md +7 -9
- data/lib/perpetuity/attribute.rb +6 -1
- data/lib/perpetuity/attribute_set.rb +5 -1
- data/lib/perpetuity/config.rb +48 -1
- data/lib/perpetuity/mapper.rb +4 -6
- data/lib/perpetuity/version.rb +1 -1
- data/lib/perpetuity.rb +2 -5
- data/spec/integration/indexing_spec.rb +5 -3
- data/spec/integration/retrieval_spec.rb +26 -0
- data/spec/integration/update_spec.rb +0 -16
- data/spec/perpetuity/attribute_spec.rb +4 -0
- data/spec/perpetuity/config_spec.rb +26 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a1455076e7e95dfb019c9d2dde967df36e40ef5
|
4
|
+
data.tar.gz: f35c774af07f2890d4f012067694c888b4ad5c1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9cdc1e4fadbc9efeafc7887a42a0ed759472b0439de8519e6ad4d557eb910637dda9b247d0f06643e2dccc59cb4819746de06179dfbdbc01a84b3e9549cd314
|
7
|
+
data.tar.gz: 4ebd69b7c403320f2748e62dabc6f237c69bc2b21c59b2cf1e0426dbb7068735355e99445ebfedc2ba7527c456c5154c282304bce168273a1a031195ea1dad45
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## Version 1.0.0.beta2
|
2
|
+
|
3
|
+
- Allow data source to be configured with a URI. This lets you say `Perpetuity.data_source "postgres://user:password@postgres.example.com:5432/my_database"`, keeping you from having to split up the URI yourself.
|
4
|
+
- Remove overreaching rescue clauses to let exceptions get rescued inside the adapters
|
5
|
+
- Allow AttributeSet to be initialized w/ attributes
|
6
|
+
- Remove Mongo-specific code
|
7
|
+
|
8
|
+
|
1
9
|
## Version 1.0.0.beta
|
2
10
|
|
3
11
|
- Duplicate objects properly for the identity map. The identity map holds references to objects pulled out of the DB. We need to duplicate these references on insertion and retrieval from the identity map to make sure that modifications to an object do not pollute the version in the identity map.
|
data/README.md
CHANGED
@@ -13,26 +13,22 @@ In the Data Mapper pattern, the objects you work with don't understand how to pe
|
|
13
13
|
Add the following to your Gemfile and run `bundle` to install it.
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
gem 'perpetuity'
|
16
|
+
gem 'perpetuity-mongodb', '~> 1.0.0.beta' # if using MongoDB
|
17
|
+
gem 'perpetuity-postgres' # if using Postgres
|
17
18
|
```
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
```ruby
|
22
|
-
gem 'perpetuity/mongodb' # if using MongoDB
|
23
|
-
gem 'perpetuity/postgres' # if using Postgres
|
24
|
-
```
|
20
|
+
Note that you do not need to explicitly declare the `perpetuity` gem as a dependency. The database adapter takes care of that for you. It works just like including `rspec-rails` into your Rails app.
|
25
21
|
|
26
22
|
## Configuration
|
27
23
|
|
28
|
-
The only currently
|
24
|
+
The only currently-1.0-quality adapter is MongoDB, but stay tuned for the [Postgres adapter](https://github.com/jgaskins/perpetuity-postgres). The simplest configuration is with the following line:
|
29
25
|
|
30
26
|
```ruby
|
31
27
|
Perpetuity.data_source :mongodb, 'my_mongo_database'
|
32
28
|
Perpetuity.data_source :postgres, 'my_pg_database'
|
33
29
|
```
|
34
30
|
|
35
|
-
*Note:* You cannot use different databases in the same app like that. At least, not yet. :-)
|
31
|
+
*Note:* You cannot use different databases in the same app like that. At least, not yet. :-) Possibly a 1.1 feature?
|
36
32
|
|
37
33
|
If your database is on another server/port or you need authentication, you can specify those as options:
|
38
34
|
|
@@ -43,6 +39,8 @@ Perpetuity.data_source :mongodb, 'my_database', host: 'mongo.example.com',
|
|
43
39
|
password: 'password'
|
44
40
|
```
|
45
41
|
|
42
|
+
If you are using Perpetuity with a multithreaded application, you can specify a `:pool_size` parameter to set up a connection pool. If you omit this parameter, it will use the data source's default pool size.
|
43
|
+
|
46
44
|
## Setting up object mappers
|
47
45
|
|
48
46
|
Object mappers are generated by the following:
|
data/lib/perpetuity/attribute.rb
CHANGED
@@ -2,12 +2,16 @@ module Perpetuity
|
|
2
2
|
class AttributeSet
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
-
def initialize
|
5
|
+
def initialize *attributes
|
6
6
|
@attributes = {}
|
7
|
+
attributes.each do |attribute|
|
8
|
+
self << attribute
|
9
|
+
end
|
7
10
|
end
|
8
11
|
|
9
12
|
def << attribute
|
10
13
|
@attributes[attribute.name] = attribute
|
14
|
+
self
|
11
15
|
end
|
12
16
|
|
13
17
|
def [] name
|
data/lib/perpetuity/config.rb
CHANGED
@@ -1,11 +1,58 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
1
3
|
module Perpetuity
|
2
4
|
class Configuration
|
3
5
|
def data_source *args
|
4
6
|
if args.any?
|
5
|
-
|
7
|
+
db = args.first
|
8
|
+
|
9
|
+
case db
|
10
|
+
when String
|
11
|
+
args[0] = URI(args[0])
|
12
|
+
@db = data_source_from_url(*args)
|
13
|
+
when Symbol
|
14
|
+
adapter = args.shift
|
15
|
+
db_name = args.shift
|
16
|
+
options = args.shift || {}
|
17
|
+
adapter_class = Perpetuity.const_get(adapter(adapter))
|
18
|
+
|
19
|
+
@db = adapter_class.new(options.merge(db: db_name))
|
20
|
+
end
|
6
21
|
end
|
7
22
|
|
8
23
|
@db
|
9
24
|
end
|
25
|
+
|
26
|
+
def data_source_from_url *args
|
27
|
+
uri = args.shift
|
28
|
+
options = args.shift || {}
|
29
|
+
|
30
|
+
protocol = uri.scheme
|
31
|
+
klass = Perpetuity.const_get(adapter(protocol))
|
32
|
+
db_options = {
|
33
|
+
db: uri.path[1..-1],
|
34
|
+
username: uri.user,
|
35
|
+
password: uri.password,
|
36
|
+
host: uri.host,
|
37
|
+
port: uri.port,
|
38
|
+
}
|
39
|
+
if options.key? :pool_size
|
40
|
+
db_options[:pool_size] = options[:pool_size]
|
41
|
+
end
|
42
|
+
|
43
|
+
klass.new(db_options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.adapters
|
47
|
+
@adapters ||= {
|
48
|
+
dynamodb: 'DynamoDB',
|
49
|
+
mongodb: 'MongoDB',
|
50
|
+
postgres: 'Postgres',
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def adapter name
|
55
|
+
self.class.adapters[name.to_sym]
|
56
|
+
end
|
10
57
|
end
|
11
58
|
end
|
data/lib/perpetuity/mapper.rb
CHANGED
@@ -202,15 +202,13 @@ module Perpetuity
|
|
202
202
|
end
|
203
203
|
|
204
204
|
def increment object, attribute, count=1
|
205
|
-
|
206
|
-
|
207
|
-
raise ArgumentError.new('Attempted to increment a non-numeric value')
|
205
|
+
id = id_for(object) || object
|
206
|
+
data_source.increment mapped_class, id, attribute, count
|
208
207
|
end
|
209
208
|
|
210
209
|
def decrement object, attribute, count=1
|
211
|
-
|
212
|
-
|
213
|
-
raise ArgumentError.new('Attempted to decrement a non-numeric value')
|
210
|
+
id = id_for(object) || object
|
211
|
+
data_source.increment mapped_class, id, attribute, -count
|
214
212
|
end
|
215
213
|
|
216
214
|
def sample
|
data/lib/perpetuity/version.rb
CHANGED
data/lib/perpetuity.rb
CHANGED
@@ -27,11 +27,8 @@ module Perpetuity
|
|
27
27
|
@mapper_registry ||= MapperRegistry.new
|
28
28
|
end
|
29
29
|
|
30
|
-
def self.data_source
|
31
|
-
|
32
|
-
adapter_class = const_get(adapters[adapter])
|
33
|
-
|
34
|
-
configure { data_source adapter_class.new(options.merge(db: db_name)) }
|
30
|
+
def self.data_source *args
|
31
|
+
configure { data_source *args }
|
35
32
|
end
|
36
33
|
|
37
34
|
# Necessary to be able to check whether Rails is loaded and initialized
|
@@ -4,7 +4,7 @@ describe 'indexing' do
|
|
4
4
|
let(:mapper_class) do
|
5
5
|
Class.new(Perpetuity::Mapper) do
|
6
6
|
map Object
|
7
|
-
attribute :name
|
7
|
+
attribute :name, type: String
|
8
8
|
index :name, unique: true
|
9
9
|
end
|
10
10
|
end
|
@@ -18,7 +18,7 @@ describe 'indexing' do
|
|
18
18
|
let(:mapper) { mapper_class.new }
|
19
19
|
let(:name_index) do
|
20
20
|
mapper.indexes.find do |index|
|
21
|
-
index.attribute.
|
21
|
+
index.attribute.name == :name
|
22
22
|
end
|
23
23
|
end
|
24
24
|
let(:db_name) { Perpetuity.configuration.data_source.db }
|
@@ -39,8 +39,10 @@ describe 'indexing' do
|
|
39
39
|
|
40
40
|
it 'creates indexes' do
|
41
41
|
mapper.reindex!
|
42
|
+
mapper.data_source.active_indexes(Object).map do |index|
|
43
|
+
index.attribute.name.to_s
|
44
|
+
end.should include 'name'
|
42
45
|
name_index.should be_active
|
43
|
-
mapper.remove_index! name_index
|
44
46
|
end
|
45
47
|
|
46
48
|
it 'specifies uniqueness of the index' do
|
@@ -223,4 +223,30 @@ describe "retrieval" do
|
|
223
223
|
retrieved.title.should be_a String
|
224
224
|
retrieved.title.should == fake_title
|
225
225
|
end
|
226
|
+
|
227
|
+
describe 'Enumerable methods within queries' do
|
228
|
+
let(:article_with_comments) do
|
229
|
+
Article.new(SecureRandom.hex, SecureRandom.hex).tap do |a|
|
230
|
+
a.comments << Comment.new
|
231
|
+
end
|
232
|
+
end
|
233
|
+
let(:article_without_comments) do
|
234
|
+
Article.new(SecureRandom.hex, SecureRandom.hex)
|
235
|
+
end
|
236
|
+
let(:articles) { [ article_with_comments, article_without_comments ] }
|
237
|
+
|
238
|
+
before { mapper.insert articles }
|
239
|
+
|
240
|
+
it 'checks for the existence of attributes in an array' do
|
241
|
+
results = mapper.select { |article| article.comments.any? }.to_a
|
242
|
+
results.should include article_with_comments
|
243
|
+
results.should_not include article_without_comments
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'checks that an array has no elements' do
|
247
|
+
results = mapper.select { |article| article.comments.none? }.to_a
|
248
|
+
results.should include article_without_comments
|
249
|
+
results.should_not include article_with_comments
|
250
|
+
end
|
251
|
+
end
|
226
252
|
end
|
@@ -90,21 +90,5 @@ describe 'updating' do
|
|
90
90
|
mapper.decrement article, :views, 10
|
91
91
|
mapper.find(mapper.id_for(article)).views.should == view_count - 11
|
92
92
|
end
|
93
|
-
|
94
|
-
context 'with an object with the specified attribute missing' do
|
95
|
-
let(:article) { Article.new('title', 'body', nil, nil, nil) }
|
96
|
-
|
97
|
-
it 'raises an exception when incrementing' do
|
98
|
-
expect { mapper.increment article, :views }.to raise_error(
|
99
|
-
ArgumentError, 'Attempted to increment a non-numeric value')
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'raises an exception when decrementing' do
|
103
|
-
expect { mapper.decrement article, :views }.to raise_error(
|
104
|
-
ArgumentError, 'Attempted to decrement a non-numeric value')
|
105
|
-
end
|
106
|
-
end
|
107
93
|
end
|
108
94
|
end
|
109
|
-
|
110
|
-
|
@@ -1,13 +1,36 @@
|
|
1
1
|
require 'perpetuity/config'
|
2
|
+
require 'perpetuity/postgres'
|
2
3
|
|
3
4
|
module Perpetuity
|
4
5
|
describe Configuration do
|
5
6
|
let(:config) { Configuration.new }
|
6
7
|
|
7
8
|
it 'sets a data source' do
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
config.data_source :postgres,
|
10
|
+
'perpetuity',
|
11
|
+
username: 'username',
|
12
|
+
password: 'password',
|
13
|
+
host: 'host',
|
14
|
+
port: 1337
|
15
|
+
|
16
|
+
config.data_source.should be_a Postgres
|
17
|
+
config.data_source.db.should == 'perpetuity'
|
18
|
+
config.data_source.username.should == 'username'
|
19
|
+
config.data_source.password.should == 'password'
|
20
|
+
config.data_source.host.should == 'host'
|
21
|
+
config.data_source.port.should == 1337
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'allows a URL as its data source' do
|
25
|
+
db = "postgres://username:password@host:1337/database"
|
26
|
+
data_source = config.data_source(db, pool_size: 20)
|
27
|
+
data_source.should be_a Postgres
|
28
|
+
data_source.username.should == 'username'
|
29
|
+
data_source.password.should == 'password'
|
30
|
+
data_source.host.should == 'host'
|
31
|
+
data_source.port.should == 1337
|
32
|
+
data_source.db.should == 'database'
|
33
|
+
data_source.pool_size.should == 20
|
11
34
|
end
|
12
35
|
end
|
13
36
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perpetuity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamie Gaskins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-12-
|
11
|
+
date: 2013-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
124
|
version: 1.3.1
|
125
125
|
requirements: []
|
126
126
|
rubyforge_project:
|
127
|
-
rubygems_version: 2.0.
|
127
|
+
rubygems_version: 2.0.3
|
128
128
|
signing_key:
|
129
129
|
specification_version: 4
|
130
130
|
summary: Persistence library allowing serialization of Ruby objects
|