vorpal 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTFlNjY4ZjU3YWRhNmY2ZDFmZmFiMTBiMTk3ZWY5ZjVhYjc1NTAzYw==
4
+ YWYyMjQxMmIzZmI2MDc1Zjg0MWNkNGNmZDBjZmE1YWFmMjRkYmYzZQ==
5
5
  data.tar.gz: !binary |-
6
- N2FkZmQzZDBiMjg1MWU5MzJjYzcwMzUxNGNjMzk1NGE0NjkyMjNkYw==
6
+ ZjhmMTY1ZmY3Y2QwZmE3ZGM4ZjNlOGM0MTFjM2EyZjRiZTI0ZWY0Ng==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NTA5MTJmMWMzM2I5YzE5MmNkYjYzNDhlMzA0NjczZThkMzE1M2M2NDBiYzFj
10
- ZGE3OTU0Zjc0NGNlNzA4Y2RiNTM4OTgyZjk1ZmY2MjgzNjY4NTNmM2NkMDI4
11
- MjFlMGYwNzQzZWNiN2FiYTA1MzE3YTk1YmNmZTRmOTNlYzM2MWI=
9
+ MzI5ZjJkNTkwMGViNDViNWFjNTYzMzYwNTY3ZjRlYzkxZTY2ZjZiZDVjNGVh
10
+ ODY0MjcxNzA3OTY5MWY1ZjM3MmRjMDRmZmU2OGQ3NTQ5MjkxM2RjYjliZTdl
11
+ ZGE4NjdhYzM1YjM5YTUzMmJjNWM3Yjk1YThhNTNmNjA4OWIwMjM=
12
12
  data.tar.gz: !binary |-
13
- YTJhOTJhMjFkZmYwMDJlYmQwZDVmZWY0MzkwMzgyNzRhZDA0NWYyZGFlM2Iy
14
- NDZmYzc5MzUyNGM4MzFiOTIwYWIxMDRiNWUzMzJlYTcwY2YwMWEzNjRmOGM3
15
- MGM4Nzg1MzRjMzUxNzgzZmFjOTg2YjU3ZDQ2ZmM0NTlkZDNkMWE=
13
+ NDc0MTcxNzdiZmJlMGIwYmZmZWVlOTEyZDU1YjIxMmViNTQ0NTk1ZjM2Zjhl
14
+ MzZjZWU4ZWVmNDM0NjE0ZTlmNzNhOTA3NjM5YzUyYjBjZjE0MjZmYjYxMzdl
15
+ Y2E1M2U4ODQ1NDM4MDMxZmNkZjNlN2MxNjgwY2Q5ZDQ0MzNmMzg=
data/README.md CHANGED
@@ -230,7 +230,7 @@ For example:
230
230
 
231
231
  **Q.** How do I get serialization?
232
232
 
233
- **A.** You can use [ActiveModel::Serialization](http://api.rubyonrails.org/classes/ActiveModel/Serialization.html) or [ActiveModel::Serializers](https://github.com/rails-api/active_model_serializers) but they are not heartily recommended. The former is too coupled to the model and the latter is too coupled to Rails controllers. Vorpal includes the [SimpleSerializer](http://rubydoc.info/github/nulogy/vorpal/master/SimpleSerializer) and [SimpleDeserializer](http://rubydoc.info/github/nulogy/vorpal/master/SimpleDeserializer) for this purpose.
233
+ **A.** You can use [ActiveModel::Serialization](http://api.rubyonrails.org/classes/ActiveModel/Serialization.html) or [ActiveModel::Serializers](https://github.com/rails-api/active_model_serializers) but they are not heartily recommended. The former is too coupled to the model and the latter is too coupled to Rails controllers. Vorpal uses [SimpleSerializer](https://github.com/nulogy/simple_serializer) for this purpose.
234
234
 
235
235
  ## Running Tests
236
236
 
@@ -1,4 +1,5 @@
1
1
  require 'vorpal/identity_map'
2
+ require 'vorpal/traversal'
2
3
 
3
4
  module Vorpal
4
5
  class AggregateRepository
@@ -52,8 +53,7 @@ class AggregateRepository
52
53
  # operation.
53
54
  # @return [Object] Entity with the given primary key value and type.
54
55
  def load(id, domain_class, identity_map=IdentityMap.new)
55
- db_object = @configs.config_for(domain_class).load_by_id(id)
56
- hydrate(db_object, identity_map)
56
+ load_all([id], domain_class, identity_map).first
57
57
  end
58
58
 
59
59
  # Like {#load} but operates on multiple ids.
@@ -66,7 +66,10 @@ class AggregateRepository
66
66
  # operation.
67
67
  # @return [[Object]] Entities with the given primary key values and type.
68
68
  def load_all(ids, domain_class, identity_map=IdentityMap.new)
69
- ids.map { |id| load(id, domain_class, identity_map) }
69
+ ids.map do |id|
70
+ db_object = @configs.config_for(domain_class).load_by_id(id)
71
+ hydrate(db_object, identity_map)
72
+ end
70
73
  end
71
74
 
72
75
  # Removes an aggregate from the DB. Even if the aggregate contains unsaved
@@ -146,104 +149,6 @@ class AggregateRepository
146
149
  end
147
150
  end
148
151
 
149
- # @private
150
- class Traversal
151
- def initialize(configs)
152
- @configs = configs
153
- end
154
-
155
- def accept_for_domain(object, visitor, already_visited=[])
156
- return if object.nil?
157
-
158
- config = @configs.config_for(object.class)
159
- return if config.nil?
160
-
161
- return if already_visited.include?(object)
162
- already_visited << object
163
-
164
- visitor.visit_object(object, config)
165
-
166
- config.belongs_tos.each do |belongs_to_config|
167
- child = belongs_to_config.get_child(object)
168
- accept_for_domain(child, visitor, already_visited) if visitor.continue_traversal?(belongs_to_config)
169
-
170
- visitor.visit_belongs_to(object, child, belongs_to_config)
171
- end
172
-
173
- config.has_ones.each do |has_one_config|
174
- child = has_one_config.get_child(object)
175
- accept_for_domain(child, visitor, already_visited) if visitor.continue_traversal?(has_one_config)
176
-
177
- visitor.visit_has_one(object, child, has_one_config)
178
- end
179
-
180
- config.has_manys.each do |has_many_config|
181
- children = has_many_config.get_children(object)
182
- children.each do |child|
183
- accept_for_domain(child, visitor, already_visited) if visitor.continue_traversal?(has_many_config)
184
- end
185
- visitor.visit_has_many(object, children, has_many_config)
186
- end
187
- end
188
-
189
- def accept_for_db(db_object, visitor, already_visited=[])
190
- return if db_object.nil?
191
-
192
- config = @configs.config_for_db(db_object.class)
193
- return if config.nil?
194
-
195
- return if already_visited.include?(db_object)
196
- already_visited << db_object
197
-
198
- visitor.visit_object(db_object, config)
199
-
200
- config.belongs_tos.each do |belongs_to_config|
201
- child = belongs_to_config.load_child(db_object)
202
- accept_for_db(child, visitor, already_visited) if visitor.continue_traversal?(belongs_to_config)
203
-
204
- visitor.visit_belongs_to(db_object, child, belongs_to_config)
205
- end
206
-
207
- config.has_ones.each do |has_one_config|
208
- child = has_one_config.load_child(db_object)
209
- accept_for_db(child, visitor, already_visited) if visitor.continue_traversal?(has_one_config)
210
-
211
- visitor.visit_belongs_to(db_object, child, has_one_config)
212
- end
213
-
214
- config.has_manys.each do |has_many_config|
215
- children = has_many_config.load_children(db_object)
216
- children.each do |child|
217
- accept_for_db(child, visitor, already_visited) if visitor.continue_traversal?(has_many_config)
218
- end
219
- visitor.visit_has_many(db_object, children, has_many_config)
220
- end
221
- end
222
- end
223
-
224
- # @private
225
- module AggregateVisitorTemplate
226
- def visit_object(object, config)
227
- # override me!
228
- end
229
-
230
- def visit_belongs_to(parent, child, belongs_to_config)
231
- # override me!
232
- end
233
-
234
- def visit_has_one(parent, child, has_one_config)
235
- # override me!
236
- end
237
-
238
- def visit_has_many(parent, children, has_many_config)
239
- # override me!
240
- end
241
-
242
- def continue_traversal?(association_config)
243
- true
244
- end
245
- end
246
-
247
152
  # @private
248
153
  class SerializeVisitor
249
154
  include AggregateVisitorTemplate
@@ -1,5 +1,5 @@
1
- require 'simple_serializer/simple_serializer'
2
- require 'simple_serializer/simple_deserializer'
1
+ require 'simple_serializer/serializer'
2
+ require 'simple_serializer/deserializer'
3
3
  require 'vorpal/configs'
4
4
 
5
5
  module Vorpal
@@ -134,13 +134,13 @@ class ConfigBuilder
134
134
  end
135
135
 
136
136
  def serializer(attrs)
137
- Class.new(SimpleSerializer) do
137
+ Class.new(SimpleSerializer::Serializer) do
138
138
  attributes *attrs
139
139
  end
140
140
  end
141
141
 
142
142
  def deserializer(attrs)
143
- Class.new(SimpleDeserializer) do
143
+ Class.new(SimpleSerializer::Deserializer) do
144
144
  data_attributes *attrs
145
145
  end
146
146
  end
@@ -58,7 +58,7 @@ class ClassConfig
58
58
  end
59
59
 
60
60
  def find_in_db(object)
61
- db_class.find(object.id)
61
+ load_by_id(object.id)
62
62
  end
63
63
 
64
64
  def load_by_id(id)
@@ -5,22 +5,30 @@ class IdentityMap
5
5
  end
6
6
 
7
7
  def get(key_object)
8
- @entities[key_object]
8
+ @entities[key(key_object)]
9
9
  end
10
10
 
11
11
  def set(key_object, object)
12
- @entities[key_object] = object
12
+ @entities[key(key_object)] = object
13
13
  end
14
14
 
15
15
  def get_and_set(key_object)
16
16
  object = get(key_object)
17
- object = yield(key_object) if object.nil?
17
+ object = yield if object.nil?
18
18
  set(key_object, object)
19
19
  object
20
20
  end
21
21
 
22
22
  def map(key_objects)
23
- key_objects.map { |k| @entities[k] }
23
+ key_objects.map { |k| @entities[key(k)] }
24
+ end
25
+
26
+ private
27
+
28
+ def key(key_object)
29
+ return nil unless key_object
30
+ raise "Cannot put entity '#{key_object.inspect}' into IdentityMap without an id." if key_object.id.nil?
31
+ [key_object.id, key_object.class.name]
24
32
  end
25
33
  end
26
34
  end
@@ -0,0 +1,98 @@
1
+
2
+ # @private
3
+ class Traversal
4
+ def initialize(configs)
5
+ @configs = configs
6
+ end
7
+
8
+ def accept_for_domain(object, visitor, already_visited=[])
9
+ return if object.nil?
10
+
11
+ config = @configs.config_for(object.class)
12
+ return if config.nil?
13
+
14
+ return if already_visited.include?(object)
15
+ already_visited << object
16
+
17
+ visitor.visit_object(object, config)
18
+
19
+ config.belongs_tos.each do |belongs_to_config|
20
+ child = belongs_to_config.get_child(object)
21
+ accept_for_domain(child, visitor, already_visited) if visitor.continue_traversal?(belongs_to_config)
22
+
23
+ visitor.visit_belongs_to(object, child, belongs_to_config)
24
+ end
25
+
26
+ config.has_ones.each do |has_one_config|
27
+ child = has_one_config.get_child(object)
28
+ accept_for_domain(child, visitor, already_visited) if visitor.continue_traversal?(has_one_config)
29
+
30
+ visitor.visit_has_one(object, child, has_one_config)
31
+ end
32
+
33
+ config.has_manys.each do |has_many_config|
34
+ children = has_many_config.get_children(object)
35
+ children.each do |child|
36
+ accept_for_domain(child, visitor, already_visited) if visitor.continue_traversal?(has_many_config)
37
+ end
38
+ visitor.visit_has_many(object, children, has_many_config)
39
+ end
40
+ end
41
+
42
+ def accept_for_db(db_object, visitor, already_visited=[])
43
+ return if db_object.nil?
44
+
45
+ config = @configs.config_for_db(db_object.class)
46
+ return if config.nil?
47
+
48
+ return if already_visited.include?(db_object)
49
+ already_visited << db_object
50
+
51
+ visitor.visit_object(db_object, config)
52
+
53
+ config.belongs_tos.each do |belongs_to_config|
54
+ child = belongs_to_config.load_child(db_object)
55
+ accept_for_db(child, visitor, already_visited) if visitor.continue_traversal?(belongs_to_config)
56
+
57
+ visitor.visit_belongs_to(db_object, child, belongs_to_config)
58
+ end
59
+
60
+ config.has_ones.each do |has_one_config|
61
+ child = has_one_config.load_child(db_object)
62
+ accept_for_db(child, visitor, already_visited) if visitor.continue_traversal?(has_one_config)
63
+
64
+ visitor.visit_belongs_to(db_object, child, has_one_config)
65
+ end
66
+
67
+ config.has_manys.each do |has_many_config|
68
+ children = has_many_config.load_children(db_object)
69
+ children.each do |child|
70
+ accept_for_db(child, visitor, already_visited) if visitor.continue_traversal?(has_many_config)
71
+ end
72
+ visitor.visit_has_many(db_object, children, has_many_config)
73
+ end
74
+ end
75
+ end
76
+
77
+ # @private
78
+ module AggregateVisitorTemplate
79
+ def visit_object(object, config)
80
+ # override me!
81
+ end
82
+
83
+ def visit_belongs_to(parent, child, belongs_to_config)
84
+ # override me!
85
+ end
86
+
87
+ def visit_has_one(parent, child, has_one_config)
88
+ # override me!
89
+ end
90
+
91
+ def visit_has_many(parent, children, has_many_config)
92
+ # override me!
93
+ end
94
+
95
+ def continue_traversal?(association_config)
96
+ true
97
+ end
98
+ end
@@ -1,3 +1,3 @@
1
1
  module Vorpal
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
File without changes
@@ -1,4 +1,4 @@
1
- require 'integration_spec_helper'
1
+ require 'unit_spec_helper'
2
2
 
3
3
  require 'vorpal/config_builder'
4
4
 
@@ -6,8 +6,8 @@ describe Vorpal::ConfigBuilder do
6
6
  class Tester; end
7
7
 
8
8
  it 'includes the primary key in the list of fields' do
9
- builder = Vorpal::ConfigBuilder.new(Tester, {})
10
- config = builder.build
9
+ # builder = Vorpal::ConfigBuilder.new(Tester, {})
10
+ # config = builder.build
11
11
  # config.field
12
12
  end
13
13
  end
@@ -0,0 +1,51 @@
1
+ require 'unit_spec_helper'
2
+
3
+ require 'vorpal/identity_map'
4
+
5
+ describe Vorpal::IdentityMap do
6
+ let(:map) { Vorpal::IdentityMap.new }
7
+
8
+ it 'does not rely on the key objects implementation of hash and eql?' do
9
+ funny1 = build_funny_entity(1)
10
+ map.set(funny1, 'funny 1')
11
+
12
+ funny2 = build_funny_entity(2)
13
+ map.set(funny2, 'funny 2')
14
+
15
+ expect(map.get(funny1)).to eq('funny 1')
16
+ end
17
+
18
+ it 'raises an exception when the key object does not have an id set' do
19
+ entity = build_entity(nil)
20
+
21
+ expect { map.set(entity, 'something') }.to raise_error(/Cannot put entity/)
22
+ end
23
+
24
+ def build_entity(id)
25
+ entity = Entity.new
26
+ entity.id = id
27
+ entity
28
+ end
29
+
30
+ class Entity
31
+ attr_accessor :id
32
+ end
33
+
34
+ def build_funny_entity(id)
35
+ funny1 = Funny.new
36
+ funny1.id = id
37
+ funny1
38
+ end
39
+
40
+ class Funny
41
+ attr_accessor :id
42
+
43
+ def hash
44
+ 1
45
+ end
46
+
47
+ def eql?(other)
48
+ true
49
+ end
50
+ end
51
+ end
data/vorpal.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_runtime_dependency "simple_serializer", "~> 0.0.1"
21
22
 
22
23
  spec.add_development_dependency "rake", "~> 10.0"
23
24
  spec.add_development_dependency "rspec", "~> 3.0.0"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vorpal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Kirby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-02 00:00:00.000000000 Z
11
+ date: 2015-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: simple_serializer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.1
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rake
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,8 +108,6 @@ files:
94
108
  - LICENSE.txt
95
109
  - README.md
96
110
  - Rakefile
97
- - lib/simple_serializer/simple_deserializer.rb
98
- - lib/simple_serializer/simple_serializer.rb
99
111
  - lib/vorpal.rb
100
112
  - lib/vorpal/aggregate_repository.rb
101
113
  - lib/vorpal/config_builder.rb
@@ -103,10 +115,13 @@ files:
103
115
  - lib/vorpal/configuration.rb
104
116
  - lib/vorpal/hash_initialization.rb
105
117
  - lib/vorpal/identity_map.rb
118
+ - lib/vorpal/traversal.rb
106
119
  - lib/vorpal/version.rb
107
120
  - spec/integration_spec_helper.rb
121
+ - spec/unit_spec_helper.rb
108
122
  - spec/vorpal/aggregate_repository_spec.rb
109
123
  - spec/vorpal/class_config_builder_spec.rb
124
+ - spec/vorpal/identity_map_spec.rb
110
125
  - vorpal.gemspec
111
126
  homepage: https://github.com/nulogy/vorpal
112
127
  licenses:
@@ -134,5 +149,7 @@ specification_version: 4
134
149
  summary: Separate your domain model from your persistence mechanism.
135
150
  test_files:
136
151
  - spec/integration_spec_helper.rb
152
+ - spec/unit_spec_helper.rb
137
153
  - spec/vorpal/aggregate_repository_spec.rb
138
154
  - spec/vorpal/class_config_builder_spec.rb
155
+ - spec/vorpal/identity_map_spec.rb
@@ -1,67 +0,0 @@
1
- # Simple framelet for deserialization
2
- #
3
- # class SomeDeserializer < SimpleDeserializer
4
- # data_attributes :site_id, :name, :category_id, :integration_key
5
- #
6
- # def integration_key(old_integration_key)
7
- # "XX#{@data[:other_attr]}XX#{old_integration_key}XX"
8
- # end
9
- #
10
- # def set_category_id(category_id)
11
- # object.category = InventoryStatusCategory.from_id(category_id)
12
- # end
13
- # end
14
- #
15
- # Usage:
16
- #
17
- # SomeDeserializer.deserialize(object, data)
18
- # SomeDeserializer.new(object, data).deserialize
19
- #
20
- # SomeDeserializer.deserialize_array([object1, object2, ...], [data1, data2, ...])
21
- #
22
- class SimpleDeserializer
23
- class << self
24
- attr_accessor :_attributes
25
-
26
- def inherited(base)
27
- base._attributes = []
28
- end
29
-
30
- def data_attributes(*attrs)
31
- @_attributes.concat attrs
32
-
33
- attrs.each do |attr|
34
- define_method attr do |datum|
35
- datum
36
- end unless method_defined?(attr)
37
-
38
- define_method "set_#{attr}" do |datum|
39
- object.send("#{attr}=", send(attr, datum))
40
- end unless method_defined?("set_#{attr}")
41
- end
42
- end
43
-
44
- def deserialize_array(objects, data)
45
- objects.zip(data).map { |obj, datum| deserialize(obj, datum) }
46
- end
47
-
48
- def deserialize(object, data)
49
- self.new(object, data).deserialize
50
- end
51
- end
52
-
53
- attr_accessor :object
54
-
55
- def initialize(object, data)
56
- @object = object
57
- @data = data
58
- end
59
-
60
- def deserialize
61
- self.class._attributes.dup.each do |name|
62
- next unless @data.has_key?(name)
63
- send("set_#{name}", @data[name])
64
- end
65
- object
66
- end
67
- end
@@ -1,72 +0,0 @@
1
- # Simple framelet for serialization.
2
- #
3
- # API compatible with ActiveModel::Serializer but without all the complexity
4
- # and dependence on ActiveModel
5
- #
6
- # class SomeSerializer < SimpleSerializer
7
- # attributes :id, :name, :category_id, :errors
8
- #
9
- # def category_id
10
- # object.category.try(:id)
11
- # end
12
- #
13
- # def errors
14
- # ActiveModelErrorsSerializer.serialize_errors(object.errors, true) if object.errors.any?
15
- # end
16
- # end
17
- #
18
- # Usage:
19
- #
20
- # SomeSerializer.serialize(object)
21
- # SomeSerializer.new(object).serialize
22
- #
23
- # SomeSerializer.serialize_array([object])
24
- #
25
- class SimpleSerializer
26
- class << self
27
- attr_accessor :_attributes
28
-
29
- def inherited(base)
30
- base._attributes = []
31
- end
32
-
33
- def attributes(*attrs)
34
- @_attributes.concat attrs
35
-
36
- attrs.each do |attr|
37
- define_method attr do
38
- object.send(attr)
39
- end unless method_defined?(attr)
40
- end
41
- end
42
-
43
- def serialize_array(objects)
44
- objects.map { |obj| serialize(obj) }
45
- end
46
-
47
- def serialize(object)
48
- self.new(object).serialize
49
- end
50
-
51
- alias :as_json :serialize
52
- end
53
-
54
- attr_accessor :object
55
-
56
- def initialize(object, _={})
57
- @object = object
58
- end
59
-
60
- def attributes
61
- self.class._attributes.dup.each_with_object({}) do |name, hash|
62
- hash[name] = send(name)
63
- end
64
- end
65
-
66
- def serialize(_={})
67
- return nil if object.nil?
68
- attributes
69
- end
70
- alias :as_json :serialize
71
- end
72
-