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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e6705adfb6aafad45d73afe6fd8fc8da9ecb7d0
4
- data.tar.gz: c7bb3bc720c641e4b5951188591279b4fda33baa
3
+ metadata.gz: 5a1455076e7e95dfb019c9d2dde967df36e40ef5
4
+ data.tar.gz: f35c774af07f2890d4f012067694c888b4ad5c1d
5
5
  SHA512:
6
- metadata.gz: 94d4440cfb7076313402de2f8055d81fc7151504dacc1bc3e7004549ab60605f04f3cf6342dcd56893dd85e4714d39327ffe240b31fd51ebe9cb2342261c4941
7
- data.tar.gz: 8d868e8b3ba8a5fdc63b9a8ac2e32ff24bcac8b09275cadff37262be8e7ef1e39586b7c067e50627247131249a3692f467e635855332cf1350a617192d03bbf6
6
+ metadata.gz: e9cdc1e4fadbc9efeafc7887a42a0ed759472b0439de8519e6ad4d557eb910637dda9b247d0f06643e2dccc59cb4819746de06179dfbdbc01a84b3e9549cd314
7
+ data.tar.gz: 4ebd69b7c403320f2748e62dabc6f237c69bc2b21c59b2cf1e0426dbb7068735355e99445ebfedc2ba7527c456c5154c282304bce168273a1a031195ea1dad45
data/.travis.yml CHANGED
@@ -1,8 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - rbx-19mode
5
- - jruby-19mode
4
+ - rbx
6
5
  - 2.0.0
6
+ matrix:
7
+ allow_failures:
8
+ - rvm: rbx
7
9
  services:
8
10
  - mongodb
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
- **NOTE:** In version 1.0, you will need to install the Perpetuity database adapter, which will pull in the core Perpetuity gem:
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 supported persistence method is MongoDB, but stay tuned for the [Postgres adapter](https://github.com/jgaskins/perpetuity-postgres). Other schemaless solutions can probably be implemented easily. The simplest configuration is with the following line:
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:
@@ -24,11 +24,16 @@ module Perpetuity
24
24
  end
25
25
 
26
26
  def to_s
27
- name
27
+ name.to_s
28
28
  end
29
29
 
30
30
  def =~ regexp
31
31
  name.to_s =~ regexp
32
32
  end
33
+
34
+ def == other
35
+ other.is_a?(self.class) &&
36
+ name.to_s == other.name.to_s
37
+ end
33
38
  end
34
39
  end
@@ -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
@@ -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
- @db = args.pop
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
@@ -202,15 +202,13 @@ module Perpetuity
202
202
  end
203
203
 
204
204
  def increment object, attribute, count=1
205
- data_source.increment mapped_class, id_for(object), attribute, count
206
- rescue Moped::Errors::OperationFailure
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
- data_source.increment mapped_class, id_for(object), attribute, -count
212
- rescue Moped::Errors::OperationFailure
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
@@ -1,3 +1,3 @@
1
1
  module Perpetuity
2
- VERSION = "1.0.0.beta"
2
+ VERSION = "1.0.0.beta2"
3
3
  end
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 adapter, db_name, options={}
31
- adapters = { dynamodb: 'DynamoDB', mongodb: 'MongoDB', postgres: 'Postgres' }
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.to_s == :name
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
-
@@ -26,5 +26,9 @@ module Perpetuity
26
26
  it 'can match a regex' do
27
27
  expect(attribute =~ /article/).to be_true
28
28
  end
29
+
30
+ it 'uses its name when converted to a string' do
31
+ attribute.to_s.should == 'article'
32
+ end
29
33
  end
30
34
  end
@@ -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
- db = double('db')
9
- config.data_source db
10
- config.data_source.should == db
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.beta
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-15 00:00:00.000000000 Z
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.6
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