vorpal 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NjI3OWU1NDlmYjJjZjAyOTZkZmU5NThmZjJjMDI4NzVlNGE1MjFjZA==
4
+ OGY3ZWI5YTQ3OWEyNDJlYjFkNmQwOTlkNWQyMmUyMzc1YmJhOTY1Yg==
5
5
  data.tar.gz: !binary |-
6
- ZGJlYjljY2ViYTk0MzdhMWYxZjEyMWU5NmZjMGUxMzU2YTI3MzRmMw==
6
+ MGI1ZmVhOWMyNTQ3NWY0MTdjOThlOGQ0NzAyNDNkNTg0OTVkMTNkYQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZDAzMmU1MmVlNzYwYTlmNTk0NGIxMGExZTgwMDIwN2I5YzQ4NTNiNTQ5ZGRi
10
- ZjRiYjhjNDJiM2RmN2I4MGRiMzY3NTNiOTE0ZGUwMzhjZGE5ZWE1Y2EyZTk2
11
- Y2JmMmY3YzUyZDZkODYxYzVlMzhkNTg3ZThiMDIzY2ZlNzNhYzU=
9
+ ZWI5MWU2ZGY4YWM1OWZkNjk2M2UzYWE5MzgyOTlhNzFjYjYyYzgyYTczNGUz
10
+ NWEzMTExYmVlOTI3YmM4YjAxZTc1NGM4MDM1YTE4MzgwNTVkN2RhYWIxNWZm
11
+ ZGZhOGM0OGFlMTMxYjlhNzgzOWEzOTkyNjhjOWY4ZDhhYTMyZTg=
12
12
  data.tar.gz: !binary |-
13
- ZTZhZWExODIxYWQzNTlkNDJkMzg0OWI4NWVlOTMxYzZlNzk1ZTQzZmZlYjEz
14
- NGRhM2Q1MjIxYjQ4N2M5NWRiMjc4YmNmMjQ5MWNiYTEwZWU3NGYwYjhjNzkx
15
- OTc0YzFiODY3NWNkZTMyOWJiODVhYzQyZGJkYjRlYzAwMGFiMjk=
13
+ ZDE2YjJkNjk1Mzk0NDlmNmVlYjU4YmUzZTA4MjMyZWY0MDhkYTYzNWExMjI3
14
+ YmFkMzMxM2ExODEzNzVlMDYyZjZjNzRhZTFlM2IxNWQwNTI0MWIzNjU3MjUy
15
+ MjQwOGRkYzU4Nzc0ZjY3NGYwODcxNDhlZDNjMWUxM2RjZmE1YWE=
data/.gitignore CHANGED
@@ -13,3 +13,4 @@
13
13
  *.o
14
14
  *.a
15
15
  mkmf.log
16
+ /projectFilesBackup
data/README.md CHANGED
@@ -1,21 +1,29 @@
1
1
  # Vorpal
2
2
 
3
- Separate your domain model from your delivery mechanism.
3
+ Separate your domain model from your persistence mechanism. Some problems call for a really sharp tool.
4
+
5
+
6
+ > One, two! One, two! and through and through
7
+
8
+ > The vorpal blade went snicker-snack!
9
+
10
+ > He left it dead, and with its head
11
+
12
+ > He went galumphing back.
13
+
4
14
 
5
15
  ## Overview
6
- Vorpal is a [Data Mapper](http://martinfowler.com/eaaCatalog/dataMapper.html)-style ORM (object relational mapper) framelet that persists POROs (plain old Ruby objects) to a relational DB.
16
+ Vorpal is a [Data Mapper](http://martinfowler.com/eaaCatalog/dataMapper.html)-style ORM (object relational mapper) framelet that persists POROs (plain old Ruby objects) to a relational DB. It has been heavily influenced by concepts from [Domain Driven Design](http://www.infoq.com/minibooks/domain-driven-design-quickly).
7
17
 
8
- We say 'framelet' because it doesn't attempt to give you all the goodies that ORMs usually provide. Instead, it layers on top of an existing ORM and allows you to use the simplicity of the Active Record pattern where appropriate and the power of the Data Mapper pattern when you need it.
18
+ We say 'framelet' because it doesn't attempt to give you all the goodies that ORMs usually provide. Instead, it layers on top of an existing ORM and allows you to take advantage of the ease of the [Active Record](http://www.martinfowler.com/eaaCatalog/activeRecord.html) pattern where appropriate and the power of the [Data Mapper](http://martinfowler.com/eaaCatalog/dataMapper.html) pattern when you need it.
9
19
 
10
- 3 things set it apart from existing Ruby ORMs (ActiveRecord and Datamapper):
20
+ 3 things set it apart from existing main-stream Ruby ORMs ([ActiveRecord](http://api.rubyonrails.org/files/activerecord/README_rdoc.html), [Datamapper](http://datamapper.org/), and [Sequel](http://sequel.jeremyevans.net/)):
11
21
 
12
22
  1. It keeps persistence concerns separate from domain logic. In other words, your domain models don't have to extend ActiveRecord::Base (or something else) in order to get saved to a DB.
13
23
  1. It works with [Aggregates](http://martinfowler.com/bliki/DDD_Aggregate.html) rather than individual objects.
14
24
  1. It plays nicely with ActiveRecord objects!
15
25
 
16
- [Perpetuity](https://github.com/jgaskins/perpetuity) has a great introduction.
17
-
18
- Talk about EDR? Victor has a good explanation of why domain model and delivery mechanism should be separated.
26
+ This last point is incredibly important because applications that grow organically can get very far without needing to separate persistence and domain logic. But when they do, Vorpal will play nicely with all that legacy code.
19
27
 
20
28
  ## Installation
21
29
 
@@ -34,25 +42,24 @@ Or install it yourself as:
34
42
  $ gem install vorpal
35
43
 
36
44
  ## Usage
37
- Start with a domain model of POROs that form an aggregate:
45
+
46
+ **Warning! API still in flux! Expect it to change with every release until 0.1.0. After this point, semantic versioning will be used.**
47
+
48
+ Start with a domain model of POROs and AR::Base objects that form an aggregate:
38
49
 
39
50
  ```ruby
40
51
  class Tree; end
41
52
 
42
- class Trunk
53
+ class Branch
43
54
  include Virtus.model
44
55
 
45
56
  attribute :id, Integer
46
57
  attribute :length, Decimal
58
+ attribute :diameter, Decimal
47
59
  attribute :tree, Tree
48
60
  end
49
61
 
50
- class Branch
51
- include Virtus.model
52
-
53
- attribute :id, Integer
54
- attribute :length, Decimal
55
- attribute :tree, Tree
62
+ class Gardener < ActiveRecord::Base
56
63
  end
57
64
 
58
65
  class Tree
@@ -60,103 +67,167 @@ class Tree
60
67
 
61
68
  attribute :id, Integer
62
69
  attribute :name, String
63
- attribute :trunk, Trunk
70
+ attribute :gardener, Gardener
64
71
  attribute :branches, Array[Branch]
65
72
  end
66
73
  ```
67
74
 
68
- Along with a relational model:
75
+ In this aggregate, the Tree is the root and the Branches are inside the aggregate boundary. The Gardener is not technically part of the aggregate but is required for the aggregate to make sense so we say that it is on the aggregate boundary.
76
+
77
+ POROs must have setters and getters for all fields and associations that are to be persisted. They must also provide a no argument constructor.
78
+
79
+ Along with a relational model (in PostgreSQL):
69
80
 
70
81
  ```sql
71
82
  CREATE TABLE trees
72
83
  (
73
84
  id serial NOT NULL,
74
85
  name text,
75
- trunk_id integer
76
- )
86
+ gardener_id integer
87
+ );
77
88
 
78
- CREATE TABLE trunks
89
+ CREATE TABLE gardeners
79
90
  (
80
91
  id serial NOT NULL,
81
- length numeric
82
- )
92
+ name text
93
+ );
83
94
 
84
95
  CREATE TABLE branches
85
96
  (
86
97
  id serial NOT NULL,
87
98
  length numeric,
99
+ diameter numeric,
88
100
  tree_id integer
89
- )
101
+ );
90
102
  ```
91
103
 
92
104
  Create a repository configured to persist the aggregate to the relational model:
93
105
 
94
106
  ```ruby
95
- repository = Persistence::Configuration.define do
96
- map Tree do
97
- fields :name
98
- belongs_to :trunk
99
- has_many :branches
100
- end
107
+ require 'vorpal'
101
108
 
102
- map Trunk do
103
- fields :length
104
- has_one :tree
109
+ module TreeRepository
110
+ extend self
111
+
112
+ @repository = Vorpal.define do
113
+ map Tree do
114
+ fields :name
115
+ belongs_to :gardener, owned: false
116
+ has_many :branches
117
+ end
118
+
119
+ map Gardener
120
+
121
+ map Branch do
122
+ fields :length, :diameter
123
+ belongs_to :tree
124
+ end
125
+ end
126
+
127
+ def find(id)
128
+ @repository.load(id, Tree)
129
+ end
130
+
131
+ def save(tree)
132
+ @repository.persist(tree)
133
+ end
134
+
135
+ def destroy(tree)
136
+ @repository.destroy(tree)
105
137
  end
106
138
 
107
- map Branch do
108
- fields :length
109
- belongs_to :tree
139
+ class ARTree < ActiveRecord::Base
140
+ self.table_name = 'trees'
141
+ end
142
+
143
+ class ARBranch < ActiveRecord::Base
144
+ self.table_name = 'branches'
110
145
  end
111
146
  end
112
147
  ```
113
- Why don't we use DDD language? I see no mention of aggregates and entities!
148
+
149
+ Here we've used the `owned` flag on the `belongs_to` from the Tree to the Gardener to show that the Gardener is on the aggregate boundary.
114
150
 
115
151
  And use it:
116
152
 
117
153
  ```ruby
118
- repository.persist(big_tree)
154
+ # Saves/updates the given Tree as well as all Branches referenced by it,
155
+ # but not Gardeners.
156
+ TreeRepository.save(big_tree)
119
157
 
120
- small_tree = repository.load(small_tree_id, Tree)
158
+ # Loads the given Tree as well as all Branches and Gardeners
159
+ # referenced by it.
160
+ small_tree = TreeRepository.find(small_tree_id)
121
161
 
122
- repository.destroy(dead_tree)
162
+ # Destroys the given Tree as well as all Branches referenced by it,
163
+ # but not Gardeners.
164
+ TreeRepository.destroy(dead_tree)
123
165
  ```
124
166
 
125
- Show implementation of a repository using the aggregate repository!!!
126
-
127
- Talk about aggregate boundary.
128
-
129
- ### With ActiveRecord
130
- TBD
131
-
132
167
  ## API Documentation
133
168
 
134
- (http://rubydoc.info/github/nulogy/vorpal/master/frames)
169
+ http://rubydoc.info/github/nulogy/vorpal/master/frames
135
170
 
136
171
  ## Caveats
137
172
  It also does not do some things that you might expect from other ORMs:
138
173
 
139
- 1. There is no lazy loading of associations. This might sound like a big deal, but with [correctly designed aggregates](http://dddcommunity.org/library/vernon_2011/) it turns out to be very minor.
140
- 1. There is no managing of transactions. It is the strong opinion of the authors that managing transactions is an application-level concern.
174
+ 1. No lazy loading of associations. This might sound like a big deal, but with [correctly designed aggregates](http://dddcommunity.org/library/vernon_2011/) it turns out not to be.
175
+ 1. No managing of transactions. It is the strong opinion of the authors that managing transactions is an application-level concern.
141
176
  1. No support for validations. Validations are not a persistence concern.
142
- 1. Only supports primary keys called `id`.
177
+ 1. No AR-style callbacks. Use Infrastructure, Application, or Domain [services](http://martinfowler.com/bliki/EvansClassification.html) instead.
178
+ 1. No has-many-through associations. Use two has-many associations to a join entity instead.
179
+ 1. The `id` field is reserved for database primary keys. If you have a natural key/id on your domain model, name it something that makes sense for your domain. It is the strong opinion of the authors that using natural keys as foreign keys is a bad idea. This mixes domain and persistence concerns.
180
+
181
+ ## Constraints
182
+ 1. Persisted entities must have getters and setters for all persisted fields and associations. They do not need to be public.
143
183
  1. Only supports PostgreSQL.
144
- 1. Requires domain entities to have a special implementation of `#initialize`.
145
- 1. Has a dependency on ActiveRecord.
146
- 1. No facilities for querying the DB.
147
- 1. Identity map only applies to a single `#load` or `#load_all` call.
148
- 1. Clients cannot specify primary key values.
149
184
 
150
185
  ## Future Enhancements
151
186
  * Aggregate updated_at.
152
187
  * Support for other DBMSs.
153
- * Identity map for an entire application transaction.
188
+ * Support for other ORMs.
154
189
  * Value objects.
155
- * Remove dependency on ActiveRecord (optimistic locking? connection pooling?)
156
- * Application-generated primary key ids.
190
+ * Remove dependency on ActiveRecord (optimistic locking? updated_at, created_at support? Data type conversions?)
157
191
  * More efficient object loading (use fewer queries.)
158
- * Do not require special `#initialize` method? Provide a hook for an instance factory?
159
- * Single table inheritance?
192
+ * Different fields names in domain models than in the DB.
193
+
194
+ ## FAQ
195
+
196
+ **Q.** Why do I care about separating my persistence mechanism from my domain models?
197
+
198
+ **A.** It generally comes back to the [Single Responsibility Principle](http://en.wikipedia.org/wiki/Single_responsibility_principle). Here are some resources for the curious:
199
+ * [Architecture, the Lost Years](https://www.youtube.com/watch?v=WpkDN78P884) - talk by Bob Martin.
200
+ * [Hexagonal Architecture Pattern](http://alistair.cockburn.us/Hexagonal+architecture) - Alistair Cockburn.
201
+ * [Perpetuity](https://github.com/jgaskins/perpetuity) - a Ruby [Data Mapper](http://martinfowler.com/eaaCatalog/dataMapper.html)-style ORM.
202
+ * [EDR](http://victorsavkin.com/post/41016739721/building-rich-domain-models-in-rails-separating) - another [Data Mapper](http://martinfowler.com/eaaCatalog/dataMapper.html)-style ORM framelet by Victor Savkin.
203
+
204
+ **Q.** How do I do more complicated queries against the DB without direct access to ActiveRecord?
205
+
206
+ **A.** Create a method on a [Repository](http://martinfowler.com/eaaCatalog/repository.html)! They have full access to the DB/ORM so you can use [Arel](https://github.com/rails/arel) and go [crazy](http://asciicasts.com/episodes/239-activerecord-relation-walkthrough) or use direct SQL if you want.
207
+
208
+ **Q.** How do I do validations now that I don't have access to ActiveRecord anymore?
209
+
210
+ **A.** Depends on what kind of validations you want to do:
211
+ * For validating single attributes on a model: [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations.html) work very well.
212
+ * For validating whole objects or object compositions (like the state of an Aggregate): Validator objects are preferred. Chapter 5 of [Implementing Domain Driven Design](https://vaughnvernon.co/?page_id=168) contains more guidance.
213
+
214
+ **Q.** How do I use Rails view helpers like [`form_for`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for)?
215
+
216
+ **A.** Check out [ActiveModel::Model](http://api.rubyonrails.org/classes/ActiveModel/Model.html). For more complex use-cases consider using a [Form](http://rhnh.net/2012/12/03/form-objects-in-rails) [Object](https://www.reinteractive.net/posts/158-form-objects-in-rails).
217
+
218
+ **Q.** How do I get dirty checking?
219
+
220
+ **A.** Check out [ActiveModel::Dirty](http://api.rubyonrails.org/classes/ActiveModel/Dirty.html).
221
+
222
+ **Q.** How do I get serialization?
223
+
224
+ **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.
225
+
226
+ ## Contributors
227
+
228
+ * [Sean Kirby](https://github.com/sskirby)
229
+ * [Paul Sobocinski](https://github.com/psobocinski)
230
+ * [Jason Cheong-Kee-You](https://github.com/jchunky)
160
231
 
161
232
  ## Contributing
162
233
 
@@ -1,5 +1,28 @@
1
1
  require "vorpal/version"
2
+ require "vorpal/configuration"
2
3
 
4
+ # Allows easy creation of {Vorpal::AggregateRepository}
5
+ # instances.
6
+ #
7
+ # ```ruby
8
+ # repository = Vorpal.define do
9
+ # map Tree do
10
+ # fields :name
11
+ # belongs_to :trunk
12
+ # has_many :branches
13
+ # end
14
+ #
15
+ # map Trunk do
16
+ # fields :length
17
+ # has_one :tree
18
+ # end
19
+ #
20
+ # map Branch do
21
+ # fields :length
22
+ # belongs_to :tree
23
+ # end
24
+ # end
25
+ # ```
3
26
  module Vorpal
4
- # Your code goes here...
27
+ extend Vorpal::Configuration
5
28
  end
@@ -61,8 +61,7 @@ class AggregateRepository
61
61
  # aggregates to be loaded.
62
62
  # @param domain_class [Class] Type of the roots of the aggregate to be loaded.
63
63
  # @return [[Object]] Entities with the given primary key values and type.
64
- def load_all(ids, domain_class)
65
- identity_map = IdentityMap.new
64
+ def load_all(ids, domain_class, identity_map=IdentityMap.new)
66
65
  ids.map { |id| load(id, domain_class, identity_map) }
67
66
  end
68
67
 
@@ -2,30 +2,8 @@ require 'vorpal/aggregate_repository'
2
2
  require 'vorpal/config_builder'
3
3
 
4
4
  module Vorpal
5
- # Allows easy creation of {Vorpal::AggregateRepository}
6
- # instances.
7
- #
8
- # ```ruby
9
- # repository = Vorpal::Configuration.define do
10
- # map Tree do
11
- # fields :name
12
- # belongs_to :trunk
13
- # has_many :branches
14
- # end
15
- #
16
- # map Trunk do
17
- # fields :length
18
- # has_one :tree
19
- # end
20
- #
21
- # map Branch do
22
- # fields :length
23
- # belongs_to :tree
24
- # end
25
- # end
26
- # ```
5
+
27
6
  module Configuration
28
- extend self
29
7
 
30
8
  # Configures and creates a {Vorpal::AggregateRepository} instance.
31
9
  #
@@ -1,3 +1,3 @@
1
1
  module Vorpal
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  require 'integration_spec_helper'
2
2
 
3
- require 'vorpal/configuration'
3
+ require 'vorpal'
4
4
 
5
5
  require 'virtus'
6
6
 
@@ -596,7 +596,7 @@ describe 'Aggregate Repository' do
596
596
  private
597
597
 
598
598
  def configure_polymorphic_has_many
599
- Vorpal::Configuration.define do
599
+ Vorpal.define do
600
600
  map Tree do
601
601
  fields :name
602
602
  has_many :branches
@@ -620,7 +620,7 @@ private
620
620
  end
621
621
 
622
622
  def configure_polymorphic_belongs_to
623
- Vorpal::Configuration.define do
623
+ Vorpal.define do
624
624
  map Bug do
625
625
  fields :name
626
626
  belongs_to :lives_on, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
@@ -637,7 +637,7 @@ private
637
637
  end
638
638
 
639
639
  def configure_ar_polymorphic_belongs_to
640
- Vorpal::Configuration.define do
640
+ Vorpal.define do
641
641
  map Tree do
642
642
  fields :name
643
643
  belongs_to :environment, owned: false, fk: :environment_id, fk_type: :environment_type, child_class: Swamp
@@ -648,7 +648,7 @@ private
648
648
  end
649
649
 
650
650
  def configure_unowned_polymorphic_belongs_to
651
- Vorpal::Configuration.define do
651
+ Vorpal.define do
652
652
  map Bug do
653
653
  fields :name
654
654
  belongs_to :lives_on, owned: false, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
@@ -665,7 +665,7 @@ private
665
665
  end
666
666
 
667
667
  def configure_unowned
668
- Vorpal::Configuration.define do
668
+ Vorpal.define do
669
669
  map Tree do
670
670
  fields :name
671
671
  has_many :branches, owned: false
@@ -683,7 +683,7 @@ private
683
683
  end
684
684
 
685
685
  def configure_recursive
686
- Vorpal::Configuration.define do
686
+ Vorpal.define do
687
687
  map Branch do
688
688
  fields :length
689
689
  has_many :branches
@@ -697,7 +697,7 @@ private
697
697
  end
698
698
 
699
699
  def configure_with_cycle
700
- Vorpal::Configuration.define do
700
+ Vorpal.define do
701
701
  map Branch do
702
702
  fields :length
703
703
  belongs_to :tree
@@ -711,7 +711,7 @@ private
711
711
  end
712
712
 
713
713
  def configure
714
- Vorpal::Configuration.define do
714
+ Vorpal.define do
715
715
  map Tree do
716
716
  fields :name
717
717
  belongs_to :trunk
@@ -732,7 +732,7 @@ private
732
732
  end
733
733
 
734
734
  def configure_has_one
735
- Vorpal::Configuration.define do
735
+ Vorpal.define do
736
736
  map Trunk do
737
737
  fields :length
738
738
  has_one :tree
@@ -745,7 +745,7 @@ private
745
745
  end
746
746
 
747
747
  def configure_unowned_has_one
748
- Vorpal::Configuration.define do
748
+ Vorpal.define do
749
749
  map Trunk do
750
750
  fields :length
751
751
  has_one :tree, owned: false
@@ -1,10 +1,12 @@
1
1
  require 'integration_spec_helper'
2
2
 
3
- describe ConfigBuilder do
3
+ require 'vorpal/config_builder'
4
+
5
+ describe Vorpal::ConfigBuilder do
4
6
  class Tester; end
5
7
 
6
8
  it 'includes the primary key in the list of fields' do
7
- builder = ConfigBuilder.new(Tester, {})
9
+ builder = Vorpal::ConfigBuilder.new(Tester, {})
8
10
  config = builder.build
9
11
  # config.field
10
12
  end
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Vorpal::VERSION
9
9
  spec.authors = ["Sean Kirby"]
10
10
  spec.email = ["seank@nulogy.com"]
11
- spec.summary = %q{Separate your domain model from your delivery mechanism.}
11
+ spec.summary = %q{Separate your domain model from your persistence mechanism.}
12
12
  spec.description = %q{An ORM framelet that fits on top of ActiveRecord to give you 'Data Mapper' semantics.}
13
13
  spec.homepage = "https://github.com/nulogy/vorpal"
14
14
  spec.license = "MIT"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vorpal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Kirby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-28 00:00:00.000000000 Z
11
+ date: 2015-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -142,12 +142,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
142
  version: '0'
143
143
  requirements: []
144
144
  rubyforge_project:
145
- rubygems_version: 2.1.11
145
+ rubygems_version: 2.4.5
146
146
  signing_key:
147
147
  specification_version: 4
148
- summary: Separate your domain model from your delivery mechanism.
148
+ summary: Separate your domain model from your persistence mechanism.
149
149
  test_files:
150
150
  - spec/integration_spec_helper.rb
151
151
  - spec/vorpal/aggregate_repository_spec.rb
152
152
  - spec/vorpal/class_config_builder_spec.rb
153
- has_rdoc: