perpetuity 0.6.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +0 -1
- data/CHANGELOG.md +5 -0
- data/README.md +28 -1
- data/lib/perpetuity/mapper_registry.rb +22 -1
- data/lib/perpetuity/rails.rb +1 -0
- data/lib/perpetuity/rails_model.rb +41 -0
- data/lib/perpetuity/version.rb +1 -1
- data/lib/perpetuity.rb +6 -0
- data/perpetuity.gemspec +1 -1
- data/spec/perpetuity/mapper_registry_spec.rb +18 -0
- data/spec/perpetuity/rails_model_spec.rb +51 -0
- data/spec/support/stubbed_rails.rb +33 -0
- metadata +19 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f8013375d75e8b9cdc7a171ff15c51624709b3ba
|
4
|
+
data.tar.gz: 5f2a8546b037800548e2ec5588302552ba09323d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fbdf6dc761c95fffa557e4a430f0b711cd52bbedf1aecf8e85200d9287bd385f27620c7c61606597dc51044312929d4576ac063a9ecde7c223c087e6b2438851
|
7
|
+
data.tar.gz: 101f30e6be3207d717dc3e0d2cfbbf27b20793fc6550c2bdd2c998cd34175444eb68a3acc54443c35535950709f3a25b28c256bb201809237cd98fa97067c70f
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
## Version 0.7.0
|
2
|
+
|
3
|
+
- Add `Perpetuity::RailsModel`, an ActiveModel-compliant mixin
|
4
|
+
- Check Rails app directory for mappers dynamically if the mapper registry is missing a particular model class
|
5
|
+
|
1
6
|
## Version 0.6.2
|
2
7
|
|
3
8
|
- Make sure `Retrieval#first` limits the query to a single item
|
data/README.md
CHANGED
@@ -27,7 +27,10 @@ Perpetuity.data_source :mongodb, 'my_database'
|
|
27
27
|
If your database is on another server or you need authentication, you can specify those as options:
|
28
28
|
|
29
29
|
```ruby
|
30
|
-
Perpetuity.data_source :mongodb, 'my_database', host: 'mongo.example.com',
|
30
|
+
Perpetuity.data_source :mongodb, 'my_database', host: 'mongo.example.com',
|
31
|
+
port: 27017,
|
32
|
+
username: 'mongo',
|
33
|
+
password: 'password'
|
31
34
|
```
|
32
35
|
|
33
36
|
## Setting up object mappers
|
@@ -210,6 +213,30 @@ Perpetuity[Article].reindex!
|
|
210
213
|
|
211
214
|
You could put this in a rake task to be executed when you deploy your app.
|
212
215
|
|
216
|
+
## Rails Integration
|
217
|
+
|
218
|
+
Let's face it, most Ruby apps run on Rails, so we need to be able to support it. Beginning with 0.7.0, Perpetuity automatically detects Rails when you configure it and will load Rails support at that point.
|
219
|
+
|
220
|
+
### Dynamic mapper reloading
|
221
|
+
|
222
|
+
Previous versions of Perpetuity would break when Rails reloaded your models in development mode due to class objects being different. It now reloads mappers dynamically based on whether the class has been reloaded.
|
223
|
+
|
224
|
+
In order for this to work, your mapper files need to be named `*_mapper.rb` and be stored anywhere inside your project's `app` directory.
|
225
|
+
|
226
|
+
### ActiveModel-compliant API
|
227
|
+
|
228
|
+
Perpetuity deals with POROs just fine but Rails does not. This is why you have to include `ActiveModel::Model` in your objects that you want to pass to various Rails methods (such as `redirect_to`, `form_for` and `render`).
|
229
|
+
|
230
|
+
In your models, including `ActiveModel::Model` in Rails 4 (or the underlying modules in Rails 3) will give you the API that Rails expects but that won't work with Perpetuity. For example, ActiveModel assumes an `id` method but your model may not provide it, so instead of including ActiveModel we provide a `RailsModel` mixin.
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
class Person
|
234
|
+
include Perpetuity::RailsModel
|
235
|
+
end
|
236
|
+
```
|
237
|
+
|
238
|
+
This will let Rails know how to talk to your models in the way that Perpetuity handles them.
|
239
|
+
|
213
240
|
## Contributing
|
214
241
|
|
215
242
|
There are plenty of opportunities to improve what's here and possibly some design decisions that need some more refinement. You can help. If you have ideas to build on this, send some love in the form of pull requests, issues or [tweets](http://twitter.com/jamie_gaskins) and I'll do what I can for them.
|
@@ -1,7 +1,9 @@
|
|
1
1
|
module Perpetuity
|
2
2
|
class MapperRegistry
|
3
|
+
include Enumerable
|
4
|
+
|
3
5
|
def initialize
|
4
|
-
@mappers = Hash.new
|
6
|
+
@mappers = Hash.new
|
5
7
|
end
|
6
8
|
|
7
9
|
def has_mapper? klass
|
@@ -9,11 +11,30 @@ module Perpetuity
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def [] klass
|
14
|
+
mapper_class = @mappers.fetch(klass) do
|
15
|
+
load_mappers
|
16
|
+
unless @mappers.has_key? klass
|
17
|
+
raise KeyError, "No mapper for #{klass}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
12
21
|
@mappers[klass].new(self)
|
13
22
|
end
|
14
23
|
|
15
24
|
def []= klass, mapper
|
16
25
|
@mappers[klass] = mapper
|
17
26
|
end
|
27
|
+
|
28
|
+
def each &block
|
29
|
+
@mappers.each &block
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_mappers
|
33
|
+
check_rails_app_for_mappers.each(&method(:load))
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_rails_app_for_mappers
|
37
|
+
Dir['app/**/*_mapper.rb']
|
38
|
+
end
|
18
39
|
end
|
19
40
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'perpetuity/rails_model'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Perpetuity
|
2
|
+
module RailsModel
|
3
|
+
def self.included klass
|
4
|
+
klass.extend ActiveModelish
|
5
|
+
end
|
6
|
+
|
7
|
+
def persisted?
|
8
|
+
defined? @id
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_param
|
12
|
+
@id if persisted?
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_key
|
16
|
+
[to_param] if persisted?
|
17
|
+
end
|
18
|
+
|
19
|
+
module ActiveModelish
|
20
|
+
def model_name
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def param_key
|
25
|
+
self.to_s.downcase.gsub('::', '_')
|
26
|
+
end
|
27
|
+
|
28
|
+
def route_key
|
29
|
+
if defined? ActiveSupport::Inflector
|
30
|
+
ActiveSupport::Inflector.pluralize(param_key)
|
31
|
+
else
|
32
|
+
param_key + 's'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def singular_route_key
|
37
|
+
param_key
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/perpetuity/version.rb
CHANGED
data/lib/perpetuity.rb
CHANGED
@@ -6,6 +6,7 @@ require "perpetuity/mapper_registry"
|
|
6
6
|
|
7
7
|
module Perpetuity
|
8
8
|
def self.configure &block
|
9
|
+
detect_rails
|
9
10
|
configuration.instance_exec(&block)
|
10
11
|
end
|
11
12
|
|
@@ -32,4 +33,9 @@ module Perpetuity
|
|
32
33
|
|
33
34
|
configure { data_source adapters[adapter].new(options.merge(db: db_name)) }
|
34
35
|
end
|
36
|
+
|
37
|
+
# Necessary to be able to check whether Rails is loaded and initialized
|
38
|
+
def self.detect_rails
|
39
|
+
require File.expand_path('../perpetuity/rails.rb', __FILE__) if defined? Rails
|
40
|
+
end
|
35
41
|
end
|
data/perpetuity.gemspec
CHANGED
@@ -18,6 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
# specify any dependencies here; for example:
|
20
20
|
s.add_development_dependency "rake"
|
21
|
-
s.add_development_dependency "rspec", "~> 2.
|
21
|
+
s.add_development_dependency "rspec", "~> 2.13"
|
22
22
|
s.add_runtime_dependency "moped"
|
23
23
|
end
|
@@ -12,5 +12,23 @@ module Perpetuity
|
|
12
12
|
it 'maps classes to instances of their mappers' do
|
13
13
|
registry[Object].should be_a mapper
|
14
14
|
end
|
15
|
+
|
16
|
+
it 'raises a KeyError when trying to find a mapper for a missing class' do
|
17
|
+
expect { registry[Class] }.to raise_error KeyError, 'No mapper for Class'
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'searching for specified mapper when it is not in the registry' do
|
21
|
+
let(:mapper_file) { 'app/mappers/status_mapper.rb' }
|
22
|
+
|
23
|
+
before do
|
24
|
+
stub_const 'Status', Class.new
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'loads the definition for the specified mapper class' do
|
28
|
+
Dir.should_receive(:[]).with('app/**/*_mapper.rb') { [mapper_file] }
|
29
|
+
registry.should_receive(:load).with(mapper_file)
|
30
|
+
registry.load_mappers
|
31
|
+
end
|
32
|
+
end
|
15
33
|
end
|
16
34
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'perpetuity/rails_model'
|
2
|
+
|
3
|
+
module Perpetuity
|
4
|
+
describe RailsModel do
|
5
|
+
let(:klass) do
|
6
|
+
Class.new do
|
7
|
+
include Perpetuity::RailsModel
|
8
|
+
attr_accessor :id
|
9
|
+
end
|
10
|
+
end
|
11
|
+
let(:object) { klass.new }
|
12
|
+
let(:wrapper) { object.to_model }
|
13
|
+
|
14
|
+
it 'determines whether it is persisted based on @id ivar' do
|
15
|
+
object.should_not be_persisted
|
16
|
+
object.id = 'lol'
|
17
|
+
object.should be_persisted
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns the id as to_param' do
|
21
|
+
object.to_param.should == nil
|
22
|
+
object.id = 'foo'
|
23
|
+
object.to_param.should == 'foo'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns the keys on the object' do
|
27
|
+
object.to_key.should == nil
|
28
|
+
object.id = 'bar'
|
29
|
+
object.to_key.should == ['bar']
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns the model name' do
|
33
|
+
klass.model_name.should == klass
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns the param_key' do
|
37
|
+
stub_const 'Foo::Bar', klass
|
38
|
+
Foo::Bar.param_key.should == 'foo_bar'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns the route_key' do
|
42
|
+
stub_const 'Foo::Bar', klass
|
43
|
+
Foo::Bar.route_key.should == 'foo_bars'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns the singular_route_key' do
|
47
|
+
stub_const 'Foo::Bar', klass
|
48
|
+
Foo::Bar.singular_route_key.should == 'foo_bar'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rails
|
2
|
+
def self.application
|
3
|
+
@application ||= Application.new
|
4
|
+
end
|
5
|
+
|
6
|
+
class Application
|
7
|
+
def config
|
8
|
+
@config ||= Configuration.new
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration
|
13
|
+
def middleware
|
14
|
+
@middleware ||= MiddlewareStack.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class MiddlewareStack
|
19
|
+
include Enumerable
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@stack = []
|
23
|
+
end
|
24
|
+
|
25
|
+
def use klass
|
26
|
+
@stack << klass
|
27
|
+
end
|
28
|
+
|
29
|
+
def each &block
|
30
|
+
@stack.each &block
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
CHANGED
@@ -1,62 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perpetuity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.7.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jamie Gaskins
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-21 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rake
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rspec
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version: 2.
|
33
|
+
version: '2.13'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version: 2.
|
40
|
+
version: '2.13'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: moped
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
description: Persistence layer for Ruby objects
|
@@ -92,6 +85,8 @@ files:
|
|
92
85
|
- lib/perpetuity/mongodb/query_intersection.rb
|
93
86
|
- lib/perpetuity/mongodb/query_union.rb
|
94
87
|
- lib/perpetuity/mongodb/serializer.rb
|
88
|
+
- lib/perpetuity/rails.rb
|
89
|
+
- lib/perpetuity/rails_model.rb
|
95
90
|
- lib/perpetuity/reference.rb
|
96
91
|
- lib/perpetuity/retrieval.rb
|
97
92
|
- lib/perpetuity/validations.rb
|
@@ -126,6 +121,7 @@ files:
|
|
126
121
|
- spec/perpetuity/mongodb/query_spec.rb
|
127
122
|
- spec/perpetuity/mongodb/query_union_spec.rb
|
128
123
|
- spec/perpetuity/mongodb/serializer_spec.rb
|
124
|
+
- spec/perpetuity/rails_model_spec.rb
|
129
125
|
- spec/perpetuity/reference_spec.rb
|
130
126
|
- spec/perpetuity/retrieval_spec.rb
|
131
127
|
- spec/perpetuity/validations/length_spec.rb
|
@@ -133,6 +129,7 @@ files:
|
|
133
129
|
- spec/perpetuity/validations_spec.rb
|
134
130
|
- spec/perpetuity_spec.rb
|
135
131
|
- spec/spec_helper.rb
|
132
|
+
- spec/support/stubbed_rails.rb
|
136
133
|
- spec/support/test_classes.rb
|
137
134
|
- spec/support/test_classes/article.rb
|
138
135
|
- spec/support/test_classes/book.rb
|
@@ -145,27 +142,26 @@ files:
|
|
145
142
|
- spec/support/test_classes/user.rb
|
146
143
|
homepage: https://github.com/jgaskins/perpetuity.git
|
147
144
|
licenses: []
|
145
|
+
metadata: {}
|
148
146
|
post_install_message:
|
149
147
|
rdoc_options: []
|
150
148
|
require_paths:
|
151
149
|
- lib
|
152
150
|
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
151
|
requirements:
|
155
|
-
- -
|
152
|
+
- - '>='
|
156
153
|
- !ruby/object:Gem::Version
|
157
154
|
version: '0'
|
158
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
|
-
none: false
|
160
156
|
requirements:
|
161
|
-
- -
|
157
|
+
- - '>='
|
162
158
|
- !ruby/object:Gem::Version
|
163
159
|
version: '0'
|
164
160
|
requirements: []
|
165
161
|
rubyforge_project:
|
166
|
-
rubygems_version:
|
162
|
+
rubygems_version: 2.0.3
|
167
163
|
signing_key:
|
168
|
-
specification_version:
|
164
|
+
specification_version: 4
|
169
165
|
summary: Persistence library allowing serialization of Ruby objects
|
170
166
|
test_files:
|
171
167
|
- spec/integration/associations_spec.rb
|
@@ -194,6 +190,7 @@ test_files:
|
|
194
190
|
- spec/perpetuity/mongodb/query_spec.rb
|
195
191
|
- spec/perpetuity/mongodb/query_union_spec.rb
|
196
192
|
- spec/perpetuity/mongodb/serializer_spec.rb
|
193
|
+
- spec/perpetuity/rails_model_spec.rb
|
197
194
|
- spec/perpetuity/reference_spec.rb
|
198
195
|
- spec/perpetuity/retrieval_spec.rb
|
199
196
|
- spec/perpetuity/validations/length_spec.rb
|
@@ -201,6 +198,7 @@ test_files:
|
|
201
198
|
- spec/perpetuity/validations_spec.rb
|
202
199
|
- spec/perpetuity_spec.rb
|
203
200
|
- spec/spec_helper.rb
|
201
|
+
- spec/support/stubbed_rails.rb
|
204
202
|
- spec/support/test_classes.rb
|
205
203
|
- spec/support/test_classes/article.rb
|
206
204
|
- spec/support/test_classes/book.rb
|