perpetuity 0.4.6 → 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## Version 0.4.7
2
+
3
+ - Use instance variables rather than attr_readers in IdentityMap (avoids calling methods during `load_association!`).
4
+ - Fixed a bug with MongoDB authentication.
5
+ - Use attribute names rather than a stringified attribute for MongoDB indexes.
6
+ - Fixed a bug with deserializing attributes of namespaced classes. — [Jaap Groeneveld](https://github.com/jgroeneveld)
7
+ - Fixed serialization of `Perpetuity::Reference` attributes caused by resaving an object that did not have all of its referenced associations loaded.
8
+
1
9
  ## Version 0.4.6
2
10
 
3
11
  - Fix an inconsistency between `mongo` and `moped` gems. Previously, the MongoDB adapter relied on the fail-fast behavior of the `mongo` gem so we had no need to check for errors. Moped does not do that by default, which resulted in incorrect behavior of the gem when an object was not persisted.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Perpetuity [![Build Status](https://secure.travis-ci.org/jgaskins/perpetuity.png)](http://travis-ci.org/jgaskins/perpetuity)
1
+ # Perpetuity [![Build Status](https://secure.travis-ci.org/jgaskins/perpetuity.png)](http://travis-ci.org/jgaskins/perpetuity) [![Code Climate](https://codeclimate.com/github/jgaskins/perpetuity.png)](https://codeclimate.com/github/jgaskins/perpetuity)
2
2
 
3
3
  Perpetuity is a simple Ruby object persistence layer that attempts to follow Martin Fowler's Data Mapper pattern, allowing you to use plain-old Ruby objects in your Ruby apps in order to decouple your domain logic from the database as well as speed up your tests. There is no need for your model classes to inherit from another class or even include a mix-in.
4
4
 
@@ -2,16 +2,17 @@ module Perpetuity
2
2
  class IdentityMap
3
3
  def initialize objects, attribute, mapper_registry
4
4
  @map = Hash[
5
- objects.map(&attribute)
5
+ objects.map { |object| object.instance_variable_get("@#{attribute}") }
6
6
  .flatten
7
7
  .group_by(&:klass)
8
8
  .map { |klass, ref|
9
- [klass,
10
- Hash[
11
- mapper_registry[klass].select { |object|
12
- object.id.in ref.map(&:id).uniq
13
- }.map { |obj| [obj.id, obj] }
14
- ]
9
+ [
10
+ klass,
11
+ Hash[
12
+ mapper_registry[klass].select { |object|
13
+ object.id.in ref.map(&:id).uniq
14
+ }.map { |obj| [obj.id, obj] }
15
+ ]
15
16
  ]
16
17
  }
17
18
  ]
@@ -103,7 +103,7 @@ module Perpetuity
103
103
  identity_map = IdentityMap.new(objects, attribute, mapper_registry)
104
104
 
105
105
  objects.each do |object|
106
- reference = object.send(attribute)
106
+ reference = object.instance_variable_get("@#{attribute}")
107
107
  if reference.is_a? Array
108
108
  refs = reference
109
109
  real_objects = refs.map { |ref| identity_map[ref.klass][ref.id] }
@@ -40,8 +40,12 @@ module Perpetuity
40
40
  self == other
41
41
  end
42
42
 
43
+ def attribute_name
44
+ attribute.respond_to?(:name) ? attribute.name : attribute
45
+ end
46
+
43
47
  def hash
44
- "#{collection}/#{attribute}:#{unique?}:#{order}".hash
48
+ "#{collection}/#{attribute_name}:#{unique?}:#{order}".hash
45
49
  end
46
50
  end
47
51
  end
@@ -17,25 +17,27 @@ module Perpetuity
17
17
  @password = options[:password]
18
18
  @session = nil
19
19
  @indexes = Hash.new { |hash, key| hash[key] = active_indexes(key) }
20
+ @connected = false
20
21
  end
21
22
 
22
23
  def session
23
- @session ||= Moped::Session.new(["#{host}:#{port}"])
24
- @session.with(safe: true)
24
+ @session ||= Moped::Session.new(["#{host}:#{port}"]).with(safe: true)
25
25
  end
26
26
 
27
27
  def connect
28
28
  session.login(@username, @password) if @username and @password
29
+ @connected = true
29
30
  session
30
31
  end
31
32
 
32
33
  def connected?
33
- !!@session
34
+ !!@connected
34
35
  end
35
36
 
36
37
  def database
37
- connect unless connected?
38
38
  session.use db
39
+ connect unless connected?
40
+ session
39
41
  end
40
42
 
41
43
  def collection klass
@@ -20,7 +20,9 @@ module Perpetuity
20
20
  attrs = mapper.class.attribute_set.map do |attrib|
21
21
  value = attribute_for object, attrib.name
22
22
 
23
- serialized_value = if value.is_a? Array
23
+ serialized_value = if value.is_a? Reference
24
+ serialize_reference value
25
+ elsif value.is_a? Array
24
26
  serialize_array(value, attrib.embedded?)
25
27
  elsif mapper.data_source.can_serialize? value
26
28
  value
@@ -74,8 +76,11 @@ module Perpetuity
74
76
  elsif data.is_a? Hash
75
77
  metadata = data.delete('__metadata__')
76
78
  if metadata
77
- klass = Object.const_get metadata['class']
79
+ klass = metadata['class'].split('::').inject(Kernel) do |scope, const_name|
80
+ scope.const_get(const_name)
81
+ end
78
82
  id = metadata['id']
83
+
79
84
  if id
80
85
  object = Reference.new(klass, id)
81
86
  else
@@ -123,13 +128,18 @@ module Perpetuity
123
128
  end
124
129
 
125
130
  def serialize_reference value
126
- unless value.is_a? PersistedObject
127
- mapper_registry[value.class].insert value
131
+ if value.is_a? Reference
132
+ reference = value
133
+ else
134
+ unless value.is_a? PersistedObject
135
+ mapper_registry[value.class].insert value
136
+ end
137
+ reference = Reference.new(value.class.to_s, value.id)
128
138
  end
129
139
  {
130
- '__metadata__' => {
131
- 'class' => value.class.to_s,
132
- 'id' => value.id
140
+ '__metadata__' => {
141
+ 'class' => reference.klass.to_s,
142
+ 'id' => reference.id
133
143
  }
134
144
  }
135
145
  end
@@ -1,3 +1,3 @@
1
1
  module Perpetuity
2
- VERSION = "0.4.6"
2
+ VERSION = "0.4.7"
3
3
  end
@@ -48,10 +48,6 @@ module Perpetuity
48
48
  its(:password) { should == password }
49
49
  end
50
50
 
51
- it 'uses the selected database' do
52
- mongo.database.name.should == 'perpetuity_gem_test'
53
- end
54
-
55
51
  it 'removes all documents from a collection' do
56
52
  mongo.insert klass, {}
57
53
  mongo.delete_all klass
@@ -93,5 +93,17 @@ describe 'Persistence' do
93
93
  Perpetuity[Book].insert book
94
94
  book.id.should eq "my-title-#{noise}"
95
95
  end
96
+
97
+ context 'with namespaced classes' do
98
+ let(:person) { CRM::Person.new }
99
+ let(:mapper) { Perpetuity[CRM::Person] }
100
+
101
+ before { person.name = 'Foo Bar' }
102
+
103
+ it 'persists even with colons in the names' do
104
+ mapper.insert person
105
+ person.should be_a Perpetuity::PersistedObject
106
+ end
107
+ end
96
108
  end
97
109
 
@@ -111,4 +111,19 @@ describe "retrieval" do
111
111
  ids.should_not include draft.id
112
112
  end
113
113
  end
114
+
115
+ context 'with namespaced classes' do
116
+ let(:article) { Article.new }
117
+ let(:person) { CRM::Person.new }
118
+ let(:mapper) { Perpetuity[Article] }
119
+
120
+ before { article.author = person }
121
+
122
+ it 'gets a CRM::Person object back' do
123
+ mapper.insert article
124
+ retrieved_article = mapper.find(article.id)
125
+ mapper.load_association! retrieved_article, :author
126
+ retrieved_article.author.should be_a CRM::Person
127
+ end
128
+ end
114
129
  end
@@ -25,6 +25,19 @@ describe 'updating' do
25
25
  mapper.save article
26
26
  mapper.find(article.id).title.should eq new_title
27
27
  end
28
+
29
+ it 'updates an object with referenced attributes' do
30
+ user = User.new
31
+ article.author = user
32
+ mapper.save article
33
+
34
+ retrieved_article = mapper.find(article.id)
35
+ retrieved_article.title = new_title
36
+ mapper.save retrieved_article
37
+
38
+ retrieved_article = mapper.find(retrieved_article.id)
39
+ retrieved_article.author.should be_a Perpetuity::Reference
40
+ end
28
41
  end
29
42
 
30
43
 
@@ -0,0 +1,5 @@
1
+ module CRM
2
+ class Person
3
+ attr_accessor :name
4
+ end
5
+ end
@@ -1,4 +1,4 @@
1
- %w( user article comment book message topic car ).each do |file|
1
+ %w( user article comment book message topic car crm_person).each do |file|
2
2
  require "support/test_classes/#{file}"
3
3
  end
4
4
 
@@ -55,3 +55,7 @@ Perpetuity.generate_mapper_for(Car) do
55
55
  present :make
56
56
  end
57
57
  end
58
+
59
+ Perpetuity.generate_mapper_for CRM::Person do
60
+ attribute :name
61
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perpetuity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.6
4
+ version: 0.4.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-04 00:00:00.000000000 Z
12
+ date: 2013-03-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -103,6 +103,7 @@ files:
103
103
  - spec/integration/associations_spec.rb
104
104
  - spec/integration/deletion_spec.rb
105
105
  - spec/integration/indexing_spec.rb
106
+ - spec/integration/mongodb_spec.rb
106
107
  - spec/integration/pagination_spec.rb
107
108
  - spec/integration/persistence_spec.rb
108
109
  - spec/integration/retrieval_spec.rb
@@ -121,7 +122,6 @@ files:
121
122
  - spec/perpetuity/mongodb/query_intersection_spec.rb
122
123
  - spec/perpetuity/mongodb/query_spec.rb
123
124
  - spec/perpetuity/mongodb/query_union_spec.rb
124
- - spec/perpetuity/mongodb_spec.rb
125
125
  - spec/perpetuity/persisted_object_spec.rb
126
126
  - spec/perpetuity/reference_spec.rb
127
127
  - spec/perpetuity/retrieval_spec.rb
@@ -136,6 +136,7 @@ files:
136
136
  - spec/support/test_classes/book.rb
137
137
  - spec/support/test_classes/car.rb
138
138
  - spec/support/test_classes/comment.rb
139
+ - spec/support/test_classes/crm_person.rb
139
140
  - spec/support/test_classes/message.rb
140
141
  - spec/support/test_classes/topic.rb
141
142
  - spec/support/test_classes/user.rb
@@ -151,15 +152,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
152
  - - ! '>='
152
153
  - !ruby/object:Gem::Version
153
154
  version: '0'
155
+ segments:
156
+ - 0
157
+ hash: 3471626582421512512
154
158
  required_rubygems_version: !ruby/object:Gem::Requirement
155
159
  none: false
156
160
  requirements:
157
161
  - - ! '>='
158
162
  - !ruby/object:Gem::Version
159
163
  version: '0'
164
+ segments:
165
+ - 0
166
+ hash: 3471626582421512512
160
167
  requirements: []
161
168
  rubyforge_project:
162
- rubygems_version: 1.8.24
169
+ rubygems_version: 1.8.25
163
170
  signing_key:
164
171
  specification_version: 3
165
172
  summary: Persistence library allowing serialization of Ruby objects
@@ -167,6 +174,7 @@ test_files:
167
174
  - spec/integration/associations_spec.rb
168
175
  - spec/integration/deletion_spec.rb
169
176
  - spec/integration/indexing_spec.rb
177
+ - spec/integration/mongodb_spec.rb
170
178
  - spec/integration/pagination_spec.rb
171
179
  - spec/integration/persistence_spec.rb
172
180
  - spec/integration/retrieval_spec.rb
@@ -185,7 +193,6 @@ test_files:
185
193
  - spec/perpetuity/mongodb/query_intersection_spec.rb
186
194
  - spec/perpetuity/mongodb/query_spec.rb
187
195
  - spec/perpetuity/mongodb/query_union_spec.rb
188
- - spec/perpetuity/mongodb_spec.rb
189
196
  - spec/perpetuity/persisted_object_spec.rb
190
197
  - spec/perpetuity/reference_spec.rb
191
198
  - spec/perpetuity/retrieval_spec.rb
@@ -200,6 +207,7 @@ test_files:
200
207
  - spec/support/test_classes/book.rb
201
208
  - spec/support/test_classes/car.rb
202
209
  - spec/support/test_classes/comment.rb
210
+ - spec/support/test_classes/crm_person.rb
203
211
  - spec/support/test_classes/message.rb
204
212
  - spec/support/test_classes/topic.rb
205
213
  - spec/support/test_classes/user.rb