datamappify 0.40.0 → 0.50.0
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 +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +65 -5
- data/Rakefile +1 -1
- data/datamappify.gemspec +2 -2
- data/lib/datamappify/data/criteria/active_record/find_multiple.rb +12 -0
- data/lib/datamappify/data/criteria/relational/find_multiple.rb +28 -0
- data/lib/datamappify/data/criteria/sequel/find_multiple.rb +12 -0
- data/lib/datamappify/data/mapper.rb +10 -0
- data/lib/datamappify/entity/active_model/compatibility.rb +13 -0
- data/lib/datamappify/entity/composable.rb +53 -0
- data/lib/datamappify/entity/relation.rb +61 -0
- data/lib/datamappify/entity.rb +7 -1
- data/lib/datamappify/repository/query_method/callbacks.rb +5 -24
- data/lib/datamappify/repository/query_method/find_multiple.rb +34 -0
- data/lib/datamappify/repository/query_methods.rb +7 -0
- data/lib/datamappify/repository/unit_of_work/persistent_states/object.rb +14 -9
- data/lib/datamappify/repository/unit_of_work/persistent_states.rb +11 -0
- data/lib/datamappify/version.rb +1 -1
- data/spec/entity/composable_spec.rb +25 -0
- data/spec/entity/relation_spec.rb +23 -0
- data/spec/entity_spec.rb +7 -1
- data/spec/lazy_spec.rb +1 -1
- data/spec/repository/callbacks_spec.rb +6 -0
- data/spec/repository/dirty_persistence_spec.rb +18 -0
- data/spec/repository/dirty_tracking_spec.rb +18 -0
- data/spec/repository/finders_spec.rb +30 -0
- data/spec/repository/persistence_spec.rb +4 -0
- data/spec/repository_spec.rb +1 -1
- data/spec/spec_helper.rb +6 -1
- data/spec/support/entities/comment.rb +2 -0
- data/spec/support/entities/computer.rb +11 -0
- data/spec/support/entities/computer_hardware.rb +8 -0
- data/spec/support/entities/computer_software.rb +9 -0
- data/spec/support/monkey_patches/database_cleaner.rb +12 -0
- data/spec/support/repositories/callbacks_chaining_repository.rb +48 -36
- data/spec/unit/entity/composable_spec.rb +66 -0
- data/spec/unit/entity/relation_spec.rb +36 -0
- data/spec/unit/repository/query_method_spec.rb +7 -0
- metadata +33 -15
- data/ERD.png +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51bd14425d7e0347cf2a97adff354cb262038152
|
|
4
|
+
data.tar.gz: f7fc7a27a71d6e5cb10c971f9a7e57fc968ac8d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef748d505249785e6da9518a05eaab78cca206517eb708900e43e4342bedf01be6f2c369f1570058866dc10a7ac4c7a560b5ddb0371c4b35e0a6b3abdc2e2eaf
|
|
7
|
+
data.tar.gz: e7a1d50c78433c4945b06507ad60fe366f7f9623fa806cafbf54a3b99229232dafca583ea31e1d3a827729eeffcf108f4712e607b5f80fde005abf66782885e4
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -14,7 +14,9 @@ Datamappify consists of three components:
|
|
|
14
14
|
- __Repository__ is responsible for data retrieval and persistence, e.g. `find`, `save` and `destroy`, etc.
|
|
15
15
|
- __Data__ as the name suggests, holds your model data. It contains ORM objects (ActiveRecord and Sequel, etc).
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Below is a high level and somewhat simplified overview of Datamappify's architecture.
|
|
18
|
+
|
|
19
|
+

|
|
18
20
|
|
|
19
21
|
Note: Datamappify is NOT affiliated with the [Datamapper](https://github.com/datamapper/) project.
|
|
20
22
|
|
|
@@ -48,6 +50,30 @@ class User
|
|
|
48
50
|
attribute :driver_license, String
|
|
49
51
|
attribute :health_care, String
|
|
50
52
|
|
|
53
|
+
# Nested entity composition - composing the entity with attributes from other entities
|
|
54
|
+
attributes_from Job
|
|
55
|
+
|
|
56
|
+
# optionally you may prefix the attributes, so that:
|
|
57
|
+
#
|
|
58
|
+
# :programming
|
|
59
|
+
#
|
|
60
|
+
# becomes:
|
|
61
|
+
#
|
|
62
|
+
# :hobby_programming
|
|
63
|
+
attributes_from Hobby, :prefix_with => :hobby
|
|
64
|
+
|
|
65
|
+
# Entity reference
|
|
66
|
+
#
|
|
67
|
+
# `references` is a convenient method for:
|
|
68
|
+
#
|
|
69
|
+
# attribute :account_id, Integer
|
|
70
|
+
# attr_accessor :account
|
|
71
|
+
#
|
|
72
|
+
# and it assigns `account_id` the correct value:
|
|
73
|
+
#
|
|
74
|
+
# user.account = account #=> user.account_id = account.id
|
|
75
|
+
references :account
|
|
76
|
+
|
|
51
77
|
validates :first_name, :presence => true,
|
|
52
78
|
:length => { :minimum => 2 }
|
|
53
79
|
validates :passport, :presence => true,
|
|
@@ -100,12 +126,14 @@ class UserRepository
|
|
|
100
126
|
end
|
|
101
127
|
```
|
|
102
128
|
|
|
103
|
-
|
|
129
|
+
_More repository APIs are being added, below is a list of the currently implemented APIs._
|
|
130
|
+
|
|
131
|
+
#### Retrieving an entity
|
|
104
132
|
|
|
105
133
|
Pass in an id.
|
|
106
134
|
|
|
107
135
|
```ruby
|
|
108
|
-
user
|
|
136
|
+
user = UserRepository.find(1)
|
|
109
137
|
```
|
|
110
138
|
|
|
111
139
|
#### Checking if an entity exists in the repository
|
|
@@ -116,6 +144,14 @@ Pass in an entity.
|
|
|
116
144
|
UserRepository.exists?(user)
|
|
117
145
|
```
|
|
118
146
|
|
|
147
|
+
#### Retrieving all entities
|
|
148
|
+
|
|
149
|
+
Returns an array of user entities.
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
users = UserRepository.all
|
|
153
|
+
```
|
|
154
|
+
|
|
119
155
|
#### Saving/updating entities
|
|
120
156
|
|
|
121
157
|
Pass in an entity.
|
|
@@ -128,6 +164,30 @@ UserRepository.save(user)
|
|
|
128
164
|
|
|
129
165
|
Datamappify supports attribute dirty tracking - only dirty attributes will be saved.
|
|
130
166
|
|
|
167
|
+
##### Mark attributes as dirty
|
|
168
|
+
|
|
169
|
+
Sometimes it's useful to manually mark the whole entity, or some attributes in the entity to be dirty - i.e. when you are submitting a form and only want to update the changed attributes. In this case, you could:
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
UserRepository.states.mark_as_dirty(user)
|
|
173
|
+
|
|
174
|
+
UserRepository.states.find(user).changed? #=> true
|
|
175
|
+
UserRepository.states.find(user).first_name_changed? #=> true
|
|
176
|
+
UserRepository.states.find(user).last_name_changed? #=> true
|
|
177
|
+
UserRepository.states.find(user).age_changed? #=> true
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Or:
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
UserRepository.states.mark_as_dirty(user, :first_name, :last_name)
|
|
184
|
+
|
|
185
|
+
UserRepository.states.find(user).changed? #=> true
|
|
186
|
+
UserRepository.states.find(user).first_name_changed? #=> true
|
|
187
|
+
UserRepository.states.find(user).last_name_changed? #=> true
|
|
188
|
+
UserRepository.states.find(user).age_changed? #=> false
|
|
189
|
+
```
|
|
190
|
+
|
|
131
191
|
#### Destroying an entity
|
|
132
192
|
|
|
133
193
|
Pass in an entity.
|
|
@@ -190,14 +250,14 @@ Refer to [CHANGELOG](CHANGELOG.md).
|
|
|
190
250
|
## Todo
|
|
191
251
|
|
|
192
252
|
- [Authoritative source](http://msdn.microsoft.com/en-au/library/ff649505.aspx).
|
|
193
|
-
-
|
|
194
|
-
- Support for configurable primary keys and foreign keys.
|
|
253
|
+
- Support for configurable primary keys and reference (foreign) keys.
|
|
195
254
|
|
|
196
255
|
## Similar Projects
|
|
197
256
|
|
|
198
257
|
- [Curator](https://github.com/braintree/curator)
|
|
199
258
|
- [Edr](https://github.com/nulogy/edr)
|
|
200
259
|
- [Minimapper](https://github.com/joakimk/minimapper)
|
|
260
|
+
- [Reform](https://github.com/apotonick/reform)
|
|
201
261
|
|
|
202
262
|
## Credits
|
|
203
263
|
|
data/Rakefile
CHANGED
data/datamappify.gemspec
CHANGED
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
|
20
20
|
|
|
21
21
|
spec.add_dependency "virtus", "~> 0.5"
|
|
22
22
|
spec.add_dependency "activemodel", ">= 4.0.0.rc1", "< 5"
|
|
23
|
-
spec.add_dependency "hooks", "~> 0.
|
|
23
|
+
spec.add_dependency "hooks", "~> 0.3.0"
|
|
24
24
|
|
|
25
25
|
spec.add_development_dependency "bundler", "~> 1.3"
|
|
26
26
|
spec.add_development_dependency "rake"
|
|
@@ -34,5 +34,5 @@ Gem::Specification.new do |spec|
|
|
|
34
34
|
spec.add_development_dependency "sqlite3"
|
|
35
35
|
spec.add_development_dependency "sequel"
|
|
36
36
|
spec.add_development_dependency "activerecord", ">= 4.0.0.rc1", "< 5"
|
|
37
|
-
spec.add_development_dependency "database_cleaner", "
|
|
37
|
+
spec.add_development_dependency "database_cleaner", "~> 1.0.1"
|
|
38
38
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Datamappify
|
|
2
|
+
module Data
|
|
3
|
+
module Criteria
|
|
4
|
+
module Relational
|
|
5
|
+
class FindMultiple < Common
|
|
6
|
+
alias_method :entity_class, :entity
|
|
7
|
+
|
|
8
|
+
def perform
|
|
9
|
+
records = source_class.where(criteria)
|
|
10
|
+
records.map do |record|
|
|
11
|
+
entity = entity_class.new
|
|
12
|
+
update_entity(entity, record)
|
|
13
|
+
entity
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def update_entity(entity, record)
|
|
20
|
+
attributes.each do |attribute|
|
|
21
|
+
entity.send("#{attribute.name}=", record.send(attribute.source_attribute_name))
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -34,6 +34,11 @@ module Datamappify
|
|
|
34
34
|
@default_source_class ||= default_provider.find_or_build_record_class(entity_class.name)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
# @return [String]
|
|
38
|
+
def default_source_class_name
|
|
39
|
+
entity_class.name
|
|
40
|
+
end
|
|
41
|
+
|
|
37
42
|
# @return [Set<Attribute>]
|
|
38
43
|
def attributes
|
|
39
44
|
@attributes ||= Set.new(default_attributes + custom_attributes)
|
|
@@ -45,6 +50,11 @@ module Datamappify
|
|
|
45
50
|
@classified_attributes ||= Set.new(attributes).classify(&:provider_name)
|
|
46
51
|
end
|
|
47
52
|
|
|
53
|
+
# @return [Array<Attribute>]
|
|
54
|
+
def attributes_from_default_source
|
|
55
|
+
classified_attributes[default_provider_name].classify(&:source_class_name)[default_source_class_name]
|
|
56
|
+
end
|
|
57
|
+
|
|
48
58
|
private
|
|
49
59
|
|
|
50
60
|
# @return [Array<Symbol>]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Datamappify
|
|
2
|
+
module Entity
|
|
3
|
+
module Composable
|
|
4
|
+
def self.included(klass)
|
|
5
|
+
klass.extend DSL
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module DSL
|
|
9
|
+
# @param entity_class [Entity]
|
|
10
|
+
#
|
|
11
|
+
# @param options [Hash]
|
|
12
|
+
#
|
|
13
|
+
# @return [void]
|
|
14
|
+
def attributes_from(entity_class, options = {})
|
|
15
|
+
entity_class.attribute_set.each do |attribute|
|
|
16
|
+
unless excluded_attributes(entity_class).include?(attribute.name)
|
|
17
|
+
self.attribute_set << tweak_attribute!(attribute, options)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
# @param entity_class [Entity]
|
|
25
|
+
#
|
|
26
|
+
# @return [Array]
|
|
27
|
+
def excluded_attributes(entity_class)
|
|
28
|
+
@excluded_attributes ||= entity_class.reference_keys << :id
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @param attribute [Virtus::Attribute]
|
|
32
|
+
#
|
|
33
|
+
# @param options [Hash]
|
|
34
|
+
#
|
|
35
|
+
# @return [Virtus::Attribute]
|
|
36
|
+
def tweak_attribute!(attribute, options)
|
|
37
|
+
prefix_attribute_name!(attribute, options[:prefix_with]) if options[:prefix_with]
|
|
38
|
+
|
|
39
|
+
attribute
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @param attribute [Virtus::Attribute]
|
|
43
|
+
#
|
|
44
|
+
# @param prefix [Symbol]
|
|
45
|
+
#
|
|
46
|
+
# @return [void]
|
|
47
|
+
def prefix_attribute_name!(attribute, prefix)
|
|
48
|
+
attribute.instance_variable_set :@name, :"#{prefix}_#{attribute.name}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Datamappify
|
|
2
|
+
module Entity
|
|
3
|
+
module Relation
|
|
4
|
+
def self.included(klass)
|
|
5
|
+
klass.class_eval do
|
|
6
|
+
cattr_accessor :reference_keys
|
|
7
|
+
extend DSL
|
|
8
|
+
|
|
9
|
+
self.reference_keys = []
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module DSL
|
|
14
|
+
# @param entity_name [Symbol, String]
|
|
15
|
+
#
|
|
16
|
+
# @return [void]
|
|
17
|
+
def references(entity_name)
|
|
18
|
+
attribute_name = :"#{entity_name}_id"
|
|
19
|
+
|
|
20
|
+
create_attribute attribute_name, Integer
|
|
21
|
+
create_accessor entity_name
|
|
22
|
+
record_attribute attribute_name
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
# @param entity_name (see #references)
|
|
28
|
+
#
|
|
29
|
+
# @return [void]
|
|
30
|
+
def create_accessor(entity_name)
|
|
31
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
|
32
|
+
attr_reader :#{entity_name}
|
|
33
|
+
|
|
34
|
+
def #{entity_name}=(entity)
|
|
35
|
+
@#{entity_name} = entity
|
|
36
|
+
self.#{entity_name}_id = entity.id
|
|
37
|
+
end
|
|
38
|
+
CODE
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @param name [Symbol]
|
|
42
|
+
#
|
|
43
|
+
# @param type [Class]
|
|
44
|
+
#
|
|
45
|
+
# @param options [any]
|
|
46
|
+
#
|
|
47
|
+
# @return [void]
|
|
48
|
+
def create_attribute(name, type, *args)
|
|
49
|
+
attribute name, type, *args
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @param attribute_name [Symbol]
|
|
53
|
+
#
|
|
54
|
+
# @return [Array]
|
|
55
|
+
def record_attribute(attribute_name)
|
|
56
|
+
self.reference_keys << attribute_name
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/datamappify/entity.rb
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
require 'observer'
|
|
2
2
|
require 'virtus'
|
|
3
|
+
require 'datamappify/entity/active_model/compatibility'
|
|
3
4
|
require 'datamappify/entity/lazy_checking'
|
|
5
|
+
require 'datamappify/entity/composable'
|
|
6
|
+
require 'datamappify/entity/relation'
|
|
4
7
|
|
|
5
8
|
module Datamappify
|
|
6
9
|
module Entity
|
|
@@ -9,8 +12,11 @@ module Datamappify
|
|
|
9
12
|
include Observable
|
|
10
13
|
include Virtus
|
|
11
14
|
include Virtus::Equalizer.new(inspect)
|
|
12
|
-
include ActiveModel::
|
|
15
|
+
include ::ActiveModel::Model
|
|
16
|
+
include ActiveModel::Compatibility
|
|
13
17
|
include LazyChecking
|
|
18
|
+
include Composable
|
|
19
|
+
include Relation
|
|
14
20
|
|
|
15
21
|
attribute :id, Integer
|
|
16
22
|
end
|
|
@@ -1,25 +1,5 @@
|
|
|
1
1
|
require 'hooks'
|
|
2
2
|
|
|
3
|
-
# Money-patches Hooks
|
|
4
|
-
module Hooks
|
|
5
|
-
module ClassMethods
|
|
6
|
-
# Added the ability to ignore callbacks if the previous callback returns `nil` or `false`
|
|
7
|
-
#
|
|
8
|
-
# @return [Boolean]
|
|
9
|
-
def run_hook_for(name, scope, *args)
|
|
10
|
-
callbacks = callbacks_for_hook(name)
|
|
11
|
-
|
|
12
|
-
callbacks.take_while do |callback|
|
|
13
|
-
if callback.kind_of? Symbol
|
|
14
|
-
scope.send(callback, *args)
|
|
15
|
-
else
|
|
16
|
-
scope.instance_exec(*args, &callback)
|
|
17
|
-
end
|
|
18
|
-
end.length == callbacks.length
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
3
|
module Datamappify
|
|
24
4
|
module Repository
|
|
25
5
|
module QueryMethod
|
|
@@ -31,7 +11,8 @@ module Datamappify
|
|
|
31
11
|
define_hooks :before_create, :after_create,
|
|
32
12
|
:before_update, :after_update,
|
|
33
13
|
:before_save, :after_save,
|
|
34
|
-
:before_destroy, :after_destroy
|
|
14
|
+
:before_destroy, :after_destroy,
|
|
15
|
+
:halts_on_falsey => true
|
|
35
16
|
end
|
|
36
17
|
end
|
|
37
18
|
|
|
@@ -63,7 +44,7 @@ module Datamappify
|
|
|
63
44
|
# @return [Boolean]
|
|
64
45
|
def run_hooks(types, filter, entity)
|
|
65
46
|
types.take_while do |type|
|
|
66
|
-
run_hook(hook_for(type, filter), entity)
|
|
47
|
+
run_hook(hook_for(type, filter), entity).not_halted?
|
|
67
48
|
end.length == types.length
|
|
68
49
|
end
|
|
69
50
|
|
|
@@ -73,9 +54,9 @@ module Datamappify
|
|
|
73
54
|
# @param filter [Symbol]
|
|
74
55
|
# e.g. :before or :after
|
|
75
56
|
#
|
|
76
|
-
# @return [
|
|
57
|
+
# @return [Symbol]
|
|
77
58
|
def hook_for(type, filter)
|
|
78
|
-
"#{filter}_#{type}"
|
|
59
|
+
:"#{filter}_#{type}"
|
|
79
60
|
end
|
|
80
61
|
end
|
|
81
62
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Datamappify
|
|
2
|
+
module Repository
|
|
3
|
+
module QueryMethod
|
|
4
|
+
class FindMultiple < Method
|
|
5
|
+
# @param options (see Method#initialize)
|
|
6
|
+
#
|
|
7
|
+
# @param where [Hash]
|
|
8
|
+
# a hash containing all the find criterias
|
|
9
|
+
def initialize(options, criteria)
|
|
10
|
+
super
|
|
11
|
+
@criteria = criteria
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @return [Array<Entity>]
|
|
15
|
+
def perform
|
|
16
|
+
dispatch_criteria_to_default_source(
|
|
17
|
+
:FindMultiple, data_mapper.entity_class, @criteria, attributes
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @see Method#reader?
|
|
22
|
+
def reader?
|
|
23
|
+
true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def attributes
|
|
29
|
+
data_mapper.attributes_from_default_source
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -28,6 +28,13 @@ module Datamappify
|
|
|
28
28
|
QueryMethod::Find.new(query_options, id).perform
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
# Returns a collection of all the entities in the repository
|
|
32
|
+
#
|
|
33
|
+
# @return [Array<Entity>]
|
|
34
|
+
def all
|
|
35
|
+
QueryMethod::FindMultiple.new(query_options, {}).perform
|
|
36
|
+
end
|
|
37
|
+
|
|
31
38
|
# @param entity [Entity]
|
|
32
39
|
# an entity or a collection of entities
|
|
33
40
|
#
|
|
@@ -33,6 +33,20 @@ module Datamappify
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# Mark selected or all attributes as dirty, useful for a non-persisted object
|
|
37
|
+
# or for manually trigger attributes update
|
|
38
|
+
#
|
|
39
|
+
# @param attrs [Symbol]
|
|
40
|
+
# An array or a hash of which the keys are attribute symbols
|
|
41
|
+
#
|
|
42
|
+
# @return [void]
|
|
43
|
+
def mark_as_dirty(*attributes)
|
|
44
|
+
attributes = attributes.any? ? attributes : attributes_for(@entity)
|
|
45
|
+
attributes.each do |name, _|
|
|
46
|
+
send(:attribute_will_change!, name)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
36
50
|
# Is the object new (not persisted yet)?
|
|
37
51
|
#
|
|
38
52
|
# @return [Boolean]
|
|
@@ -98,15 +112,6 @@ module Datamappify
|
|
|
98
112
|
instance_variable_set "@#{name}", Marshal.load(Marshal.dump(value))
|
|
99
113
|
end
|
|
100
114
|
|
|
101
|
-
# Mark all attributes as dirty, useful for a non-persisted object
|
|
102
|
-
#
|
|
103
|
-
# @return [void]
|
|
104
|
-
def mark_as_dirty
|
|
105
|
-
attributes_for(@entity).each do |name, _|
|
|
106
|
-
send(:attribute_will_change!, name)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
115
|
# Entity attributes, based on whether the entity is lazy loaded
|
|
111
116
|
#
|
|
112
117
|
# @param entity [Entity]
|
|
@@ -48,6 +48,17 @@ module Datamappify
|
|
|
48
48
|
|
|
49
49
|
attach(entity)
|
|
50
50
|
end
|
|
51
|
+
|
|
52
|
+
# @param entity [Entity]
|
|
53
|
+
#
|
|
54
|
+
# @param attrs (see Object#mark_as_dirty)
|
|
55
|
+
#
|
|
56
|
+
# @see Object#mark_as_dirty
|
|
57
|
+
#
|
|
58
|
+
# @return (see Object#mark_as_dirty)
|
|
59
|
+
def mark_as_dirty(entity, *attributes)
|
|
60
|
+
find(entity).mark_as_dirty(*attributes)
|
|
61
|
+
end
|
|
51
62
|
end
|
|
52
63
|
end
|
|
53
64
|
end
|
data/lib/datamappify/version.rb
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Datamappify::Entity do
|
|
4
|
+
subject { Computer.new }
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
subject.cpu = '286'
|
|
8
|
+
subject.ram = 8192
|
|
9
|
+
subject.hdd = 65536
|
|
10
|
+
subject.gfx = 'Voodoo'
|
|
11
|
+
subject.software_os = 'OS X'
|
|
12
|
+
subject.software_osx_id = 1
|
|
13
|
+
subject.software_windows_id = 2
|
|
14
|
+
subject.software_linux_id = 3
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
its(:cpu) { should == '286' }
|
|
18
|
+
its(:ram) { should == 8192 }
|
|
19
|
+
its(:hdd) { should == 65536 }
|
|
20
|
+
its(:gfx) { should == 'Voodoo' }
|
|
21
|
+
its(:software_os) { should == 'OS X' }
|
|
22
|
+
its(:software_osx_id) { should == 1 }
|
|
23
|
+
its(:software_windows_id) { should == 2 }
|
|
24
|
+
its(:software_linux_id) { should == 3 }
|
|
25
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples_for "entity relations" do |data_provider|
|
|
4
|
+
include_context "user repository", data_provider
|
|
5
|
+
|
|
6
|
+
let!(:comment_repository) { "CommentRepository#{data_provider}".constantize }
|
|
7
|
+
let(:comment) { comment_repository.save!(Comment.new) }
|
|
8
|
+
|
|
9
|
+
subject { comment }
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
subject.user = existing_user
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
its(:user_id) { should == existing_user.id }
|
|
16
|
+
its(:user) { should == existing_user }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe Datamappify::Entity do
|
|
20
|
+
DATA_PROVIDERS.each do |data_provider|
|
|
21
|
+
it_behaves_like "entity relations", data_provider
|
|
22
|
+
end
|
|
23
|
+
end
|
data/spec/entity_spec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Datamappify::Entity do
|
|
4
4
|
let(:user) { User.new }
|
|
@@ -36,5 +36,11 @@ describe Datamappify::Entity do
|
|
|
36
36
|
user.valid?.should == true
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
describe "conversion" do
|
|
41
|
+
subject { user }
|
|
42
|
+
|
|
43
|
+
it { should respond_to(:to_key) }
|
|
44
|
+
end
|
|
39
45
|
end
|
|
40
46
|
|
data/spec/lazy_spec.rb
CHANGED
|
@@ -94,6 +94,8 @@ describe Datamappify::Repository do
|
|
|
94
94
|
subject.should_receive(:performed).with(:before_save_1, entity).ordered
|
|
95
95
|
subject.should_receive(:performed).with(:before_save_2, entity).ordered
|
|
96
96
|
subject.should_receive(:performed).with(:before_save_3, entity).ordered
|
|
97
|
+
subject.should_receive(:performed).with(:before_create_1, entity).ordered
|
|
98
|
+
subject.should_receive(:performed).with(:before_create_2, entity).ordered
|
|
97
99
|
subject.should_not_receive(:performed).with(:after_save_1, entity)
|
|
98
100
|
subject.should_not_receive(:performed).with(:after_save_2, entity)
|
|
99
101
|
subject.should_not_receive(:performed).with(:after_save_3, entity)
|
|
@@ -108,6 +110,8 @@ describe Datamappify::Repository do
|
|
|
108
110
|
subject.should_receive(:performed).with(:before_save_1, entity).ordered
|
|
109
111
|
subject.should_receive(:performed).with(:before_save_2, entity).ordered
|
|
110
112
|
subject.should_not_receive(:performed).with(:before_save_3, entity)
|
|
113
|
+
subject.should_not_receive(:performed).with(:before_create_1, entity)
|
|
114
|
+
subject.should_not_receive(:performed).with(:before_create_2, entity)
|
|
111
115
|
subject.should_not_receive(:performed).with(:after_save_1, entity)
|
|
112
116
|
subject.should_not_receive(:performed).with(:after_save_2, entity)
|
|
113
117
|
subject.should_not_receive(:performed).with(:after_save_3, entity)
|
|
@@ -130,6 +134,8 @@ describe Datamappify::Repository do
|
|
|
130
134
|
subject.should_receive(:performed).with(:before_save_1, entity).ordered
|
|
131
135
|
subject.should_receive(:performed).with(:before_save_2, entity).ordered
|
|
132
136
|
subject.should_receive(:performed).with(:before_save_3, entity).ordered
|
|
137
|
+
subject.should_receive(:performed).with(:before_create_1, entity).ordered
|
|
138
|
+
subject.should_receive(:performed).with(:before_create_2, entity).ordered
|
|
133
139
|
subject.should_receive(:performed).with(:after_save_1, entity).ordered
|
|
134
140
|
subject.should_receive(:performed).with(:after_save_2, entity).ordered
|
|
135
141
|
subject.should_not_receive(:performed).with(:after_save_3, entity)
|
|
@@ -33,6 +33,24 @@ shared_examples_for "dirty persistence" do |data_provider|
|
|
|
33
33
|
|
|
34
34
|
user_repository.save(new_valid_user)
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
context "attributes manually marked as dirty" do
|
|
38
|
+
let!(:updated_user) { User.new(existing_user.attributes.merge(:first_name => 'Frasier')) }
|
|
39
|
+
|
|
40
|
+
it "performs when some attributes are marked as dirty" do
|
|
41
|
+
Datamappify::Logger.should_receive(:performed).with(update_method).once
|
|
42
|
+
|
|
43
|
+
user_repository.states.mark_as_dirty(updated_user, :first_name)
|
|
44
|
+
user_repository.save(updated_user)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "performs when the entity is marked as dirty" do
|
|
48
|
+
Datamappify::Logger.should_receive(:performed).with(update_method).at_least(:twice)
|
|
49
|
+
|
|
50
|
+
user_repository.states.mark_as_dirty(updated_user)
|
|
51
|
+
user_repository.save(updated_user)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
36
54
|
end
|
|
37
55
|
end
|
|
38
56
|
end
|
|
@@ -72,6 +72,24 @@ shared_examples_for "dirty tracking" do |data_provider|
|
|
|
72
72
|
user_repository.states.find(existing_user).changed?.should == false
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
|
+
|
|
76
|
+
describe "manually mark as dirty" do
|
|
77
|
+
it "marks an entity as dirty" do
|
|
78
|
+
user_repository.states.mark_as_dirty(existing_user)
|
|
79
|
+
user_repository.states.find(existing_user).changed?.should == true
|
|
80
|
+
user_repository.states.find(existing_user).first_name_changed?.should == true
|
|
81
|
+
user_repository.states.find(existing_user).last_name_changed?.should == true
|
|
82
|
+
user_repository.states.find(existing_user).age_changed?.should == true
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "marks entity attributes as dirty" do
|
|
86
|
+
user_repository.states.mark_as_dirty(existing_user, :first_name, :age)
|
|
87
|
+
user_repository.states.find(existing_user).changed?.should == true
|
|
88
|
+
user_repository.states.find(existing_user).first_name_changed?.should == true
|
|
89
|
+
user_repository.states.find(existing_user).last_name_changed?.should == false
|
|
90
|
+
user_repository.states.find(existing_user).age_changed?.should == true
|
|
91
|
+
end
|
|
92
|
+
end
|
|
75
93
|
end
|
|
76
94
|
end
|
|
77
95
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples_for "finders" do |data_provider|
|
|
4
|
+
include_context "user repository", data_provider
|
|
5
|
+
|
|
6
|
+
let!(:existing_user_1) { user_repository.save(new_valid_user.dup) }
|
|
7
|
+
let!(:existing_user_2) { user_repository.save(new_valid_user.dup) }
|
|
8
|
+
|
|
9
|
+
context "#{data_provider}" do
|
|
10
|
+
describe "#all" do
|
|
11
|
+
it "finds all entities in a repository" do
|
|
12
|
+
user_repository.all.should have(3).users
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "finds first entity" do
|
|
16
|
+
user_repository.all.first.should == existing_user
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "finds last entity" do
|
|
20
|
+
user_repository.all.last.should == existing_user_2
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe Datamappify::Repository do
|
|
27
|
+
DATA_PROVIDERS.each do |data_provider|
|
|
28
|
+
it_behaves_like "finders", data_provider
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -26,10 +26,12 @@ shared_examples_for "repository persistence" do |data_provider|
|
|
|
26
26
|
new_user.should be_kind_of(User)
|
|
27
27
|
new_user.first_name.should == 'Batman'
|
|
28
28
|
new_user.driver_license.should == 'ARKHAMCITY'
|
|
29
|
+
new_user.persisted?.should == true
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
it "failure" do
|
|
32
33
|
-> { user_repository.save!(new_invalid_user) }.should raise_error(Datamappify::Data::EntityNotSaved)
|
|
34
|
+
new_invalid_user.persisted?.should == false
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
it "updates existing records" do
|
|
@@ -47,6 +49,7 @@ shared_examples_for "repository persistence" do |data_provider|
|
|
|
47
49
|
|
|
48
50
|
persisted_user.first_name.should == 'Vivian'
|
|
49
51
|
persisted_user.driver_license.should == 'LOCOMOTE'
|
|
52
|
+
persisted_user.persisted?.should == true
|
|
50
53
|
end
|
|
51
54
|
|
|
52
55
|
it "updates existing and new records" do
|
|
@@ -64,6 +67,7 @@ shared_examples_for "repository persistence" do |data_provider|
|
|
|
64
67
|
|
|
65
68
|
persisted_user.first_name.should == 'Vivian'
|
|
66
69
|
persisted_user.health_care.should == 'BATMANCAVE'
|
|
70
|
+
persisted_user.persisted?.should == true
|
|
67
71
|
end
|
|
68
72
|
end
|
|
69
73
|
end
|
data/spec/repository_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
|
@@ -22,7 +22,12 @@ end
|
|
|
22
22
|
DATA_PROVIDERS = ENV['DATA_PROVIDER'] ? [ENV['DATA_PROVIDER']] : %w{ActiveRecord Sequel}
|
|
23
23
|
|
|
24
24
|
RSpec.configure do |config|
|
|
25
|
-
DatabaseCleaner.
|
|
25
|
+
DatabaseCleaner.add_cleaner(:sequel)
|
|
26
|
+
|
|
27
|
+
DatabaseCleaner[:sequel].strategy = :truncation
|
|
28
|
+
DatabaseCleaner[:active_record].strategy = :truncation
|
|
29
|
+
|
|
30
|
+
require File.expand_path('../support/monkey_patches/database_cleaner.rb', __FILE__)
|
|
26
31
|
|
|
27
32
|
config.before do
|
|
28
33
|
DatabaseCleaner.clean
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require_relative 'computer_hardware'
|
|
2
|
+
require_relative 'computer_software'
|
|
3
|
+
|
|
4
|
+
class Computer
|
|
5
|
+
include Datamappify::Entity
|
|
6
|
+
|
|
7
|
+
attribute :brand, String
|
|
8
|
+
|
|
9
|
+
attributes_from ComputerHardware
|
|
10
|
+
attributes_from ComputerSoftware, :prefix_with => :software
|
|
11
|
+
end
|
|
@@ -8,21 +8,25 @@ class CallbacksChainingRepository
|
|
|
8
8
|
map_attribute :last_name, 'Sequel::HeroUserLastName#last_name'
|
|
9
9
|
map_attribute :gender, 'Sequel::HeroUserLastName#gender'
|
|
10
10
|
|
|
11
|
-
before_save
|
|
12
|
-
before_save
|
|
13
|
-
before_save
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
after_save
|
|
11
|
+
before_save :before_save_1
|
|
12
|
+
before_save :before_save_2
|
|
13
|
+
before_save :before_save_3
|
|
14
|
+
before_create :before_create_1
|
|
15
|
+
before_create :before_create_2
|
|
16
|
+
after_save :after_save_1
|
|
17
|
+
after_save :after_save_2
|
|
18
|
+
after_save :after_save_3
|
|
17
19
|
|
|
18
20
|
private
|
|
19
21
|
|
|
20
|
-
def before_save_1(entity); performed(:before_save_1,
|
|
21
|
-
def before_save_2(entity); performed(:before_save_2,
|
|
22
|
-
def before_save_3(entity); performed(:before_save_3,
|
|
23
|
-
def
|
|
24
|
-
def
|
|
25
|
-
def
|
|
22
|
+
def before_save_1 (entity); performed(:before_save_1, entity); true; end
|
|
23
|
+
def before_save_2 (entity); performed(:before_save_2, entity); true; end
|
|
24
|
+
def before_save_3 (entity); performed(:before_save_3, entity); true; end
|
|
25
|
+
def before_create_1(entity); performed(:before_create_1, entity); true; end
|
|
26
|
+
def before_create_2(entity); performed(:before_create_2, entity); true; end
|
|
27
|
+
def after_save_1 (entity); performed(:after_save_1, entity); true; end
|
|
28
|
+
def after_save_2 (entity); performed(:after_save_2, entity); true; end
|
|
29
|
+
def after_save_3 (entity); performed(:after_save_3, entity); true; end
|
|
26
30
|
|
|
27
31
|
def performed(*args)
|
|
28
32
|
true
|
|
@@ -39,21 +43,25 @@ class CallbacksChainingPauseBeforeRepository
|
|
|
39
43
|
map_attribute :last_name, 'Sequel::HeroUserLastName#last_name'
|
|
40
44
|
map_attribute :gender, 'Sequel::HeroUserLastName#gender'
|
|
41
45
|
|
|
42
|
-
before_save
|
|
43
|
-
before_save
|
|
44
|
-
before_save
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
after_save
|
|
46
|
+
before_save :before_save_1
|
|
47
|
+
before_save :before_save_2
|
|
48
|
+
before_save :before_save_3
|
|
49
|
+
before_create :before_create_1
|
|
50
|
+
before_create :before_create_2
|
|
51
|
+
after_save :after_save_1
|
|
52
|
+
after_save :after_save_2
|
|
53
|
+
after_save :after_save_3
|
|
48
54
|
|
|
49
55
|
private
|
|
50
56
|
|
|
51
|
-
def before_save_1(entity); performed(:before_save_1,
|
|
52
|
-
def before_save_2(entity); performed(:before_save_2,
|
|
53
|
-
def before_save_3(entity); performed(:before_save_3,
|
|
54
|
-
def
|
|
55
|
-
def
|
|
56
|
-
def
|
|
57
|
+
def before_save_1 (entity); performed(:before_save_1, entity); true; end
|
|
58
|
+
def before_save_2 (entity); performed(:before_save_2, entity); false; end
|
|
59
|
+
def before_save_3 (entity); performed(:before_save_3, entity); true; end
|
|
60
|
+
def before_create_1(entity); performed(:before_create_1, entity); true; end
|
|
61
|
+
def before_create_2(entity); performed(:before_create_2, entity); true; end
|
|
62
|
+
def after_save_1 (entity); performed(:after_save_1, entity); true; end
|
|
63
|
+
def after_save_2 (entity); performed(:after_save_2, entity); true; end
|
|
64
|
+
def after_save_3 (entity); performed(:after_save_3, entity); true; end
|
|
57
65
|
|
|
58
66
|
def performed(*args)
|
|
59
67
|
true
|
|
@@ -70,21 +78,25 @@ class CallbacksChainingPauseAfterRepository
|
|
|
70
78
|
map_attribute :last_name, 'Sequel::HeroUserLastName#last_name'
|
|
71
79
|
map_attribute :gender, 'Sequel::HeroUserLastName#gender'
|
|
72
80
|
|
|
73
|
-
before_save
|
|
74
|
-
before_save
|
|
75
|
-
before_save
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
after_save
|
|
81
|
+
before_save :before_save_1
|
|
82
|
+
before_save :before_save_2
|
|
83
|
+
before_save :before_save_3
|
|
84
|
+
before_create :before_create_1
|
|
85
|
+
before_create :before_create_2
|
|
86
|
+
after_save :after_save_1
|
|
87
|
+
after_save :after_save_2
|
|
88
|
+
after_save :after_save_3
|
|
79
89
|
|
|
80
90
|
private
|
|
81
91
|
|
|
82
|
-
def before_save_1(entity); performed(:before_save_1,
|
|
83
|
-
def before_save_2(entity); performed(:before_save_2,
|
|
84
|
-
def before_save_3(entity); performed(:before_save_3,
|
|
85
|
-
def
|
|
86
|
-
def
|
|
87
|
-
def
|
|
92
|
+
def before_save_1 (entity); performed(:before_save_1, entity); true; end
|
|
93
|
+
def before_save_2 (entity); performed(:before_save_2, entity); true; end
|
|
94
|
+
def before_save_3 (entity); performed(:before_save_3, entity); true; end
|
|
95
|
+
def before_create_1(entity); performed(:before_create_1, entity); true; end
|
|
96
|
+
def before_create_2(entity); performed(:before_create_2, entity); true; end
|
|
97
|
+
def after_save_1 (entity); performed(:after_save_1, entity); true; end
|
|
98
|
+
def after_save_2 (entity); performed(:after_save_2, entity); false; end
|
|
99
|
+
def after_save_3 (entity); performed(:after_save_3, entity); true; end
|
|
88
100
|
|
|
89
101
|
def performed(*args)
|
|
90
102
|
true
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Datamappify::Entity
|
|
4
|
+
describe Datamappify::Entity::Composable do
|
|
5
|
+
class FarDistantEntity
|
|
6
|
+
include Datamappify::Entity
|
|
7
|
+
|
|
8
|
+
attribute :far_distant_attribute_one
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class DistantEntity
|
|
12
|
+
include Datamappify::Entity
|
|
13
|
+
|
|
14
|
+
attribute :distant_attribute_one, String
|
|
15
|
+
attribute :distant_attribute_two, Integer, :default => 42
|
|
16
|
+
|
|
17
|
+
references :far_distant_entity
|
|
18
|
+
|
|
19
|
+
attributes_from FarDistantEntity, :prefix_with => :far
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class AnotherEntity
|
|
23
|
+
include Datamappify::Entity
|
|
24
|
+
|
|
25
|
+
attribute :attribute_one, String, :default => 'Hello'
|
|
26
|
+
attribute :attribute_two, Integer
|
|
27
|
+
|
|
28
|
+
references :distant_entity
|
|
29
|
+
|
|
30
|
+
attributes_from DistantEntity
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class DummyEntity
|
|
34
|
+
include Datamappify::Entity
|
|
35
|
+
|
|
36
|
+
attribute :attribute_zero, String
|
|
37
|
+
|
|
38
|
+
attributes_from AnotherEntity, :prefix_with => :other
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
subject { DummyEntity.new }
|
|
42
|
+
|
|
43
|
+
describe "#attributes_from" do
|
|
44
|
+
its(:attributes) { should have_key(:attribute_zero) }
|
|
45
|
+
its(:attributes) { should have_key(:other_attribute_one) }
|
|
46
|
+
its(:attributes) { should have_key(:other_attribute_two) }
|
|
47
|
+
its(:attributes) { should have_key(:other_distant_attribute_one) }
|
|
48
|
+
its(:attributes) { should have_key(:other_distant_attribute_two) }
|
|
49
|
+
its(:attributes) { should have_key(:other_far_far_distant_attribute_one) }
|
|
50
|
+
|
|
51
|
+
its(:attributes) { should_not have_key(:attribute_one) }
|
|
52
|
+
its(:attributes) { should_not have_key(:attribute_two) }
|
|
53
|
+
its(:attributes) { should_not have_key(:distant_attribute_one) }
|
|
54
|
+
its(:attributes) { should_not have_key(:distant_attribute_two) }
|
|
55
|
+
|
|
56
|
+
its(:attributes) { should_not have_key(:distant_entity_id) }
|
|
57
|
+
its(:attributes) { should_not have_key(:other_distant_entity_id) }
|
|
58
|
+
its(:attributes) { should_not have_key(:far_distant_entity_id) }
|
|
59
|
+
its(:attributes) { should_not have_key(:other_far_distant_entity_id) }
|
|
60
|
+
its(:attributes) { should_not have_key(:far_far_distant_entity_id) }
|
|
61
|
+
|
|
62
|
+
its(:other_attribute_one) { should == 'Hello' }
|
|
63
|
+
its(:other_distant_attribute_two) { should == 42 }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Datamappify::Entity
|
|
4
|
+
describe Datamappify::Entity::Relation do
|
|
5
|
+
class DummyEntity
|
|
6
|
+
include Datamappify::Entity
|
|
7
|
+
|
|
8
|
+
references :another_entity
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class AnotherEntity
|
|
12
|
+
include Datamappify::Entity
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
subject { DummyEntity.new }
|
|
16
|
+
|
|
17
|
+
describe "#references" do
|
|
18
|
+
it { should respond_to(:another_entity_id) }
|
|
19
|
+
it { should respond_to(:another_entity_id=) }
|
|
20
|
+
it { should respond_to(:another_entity) }
|
|
21
|
+
it { should respond_to(:another_entity=) }
|
|
22
|
+
|
|
23
|
+
describe "assigns the correct attribute" do
|
|
24
|
+
let(:another_entity) { AnotherEntity.new.tap { |e| e.id = 42 } }
|
|
25
|
+
|
|
26
|
+
before do
|
|
27
|
+
subject.another_entity = another_entity
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
its(:another_entity_id) { should == 42 }
|
|
31
|
+
its(:another_entity) { should == another_entity }
|
|
32
|
+
its(:reference_keys) { should include(:another_entity_id) }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -37,6 +37,13 @@ module Datamappify::Repository::QueryMethod
|
|
|
37
37
|
it { should_not be_a_writer }
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
describe FindMultiple do
|
|
41
|
+
subject { FindMultiple }
|
|
42
|
+
|
|
43
|
+
it { should be_a_reader }
|
|
44
|
+
it { should_not be_a_writer }
|
|
45
|
+
end
|
|
46
|
+
|
|
40
47
|
describe Save do
|
|
41
48
|
subject { Save }
|
|
42
49
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: datamappify
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.50.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Fred Wu
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-05-
|
|
11
|
+
date: 2013-05-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: virtus
|
|
@@ -50,14 +50,14 @@ dependencies:
|
|
|
50
50
|
requirements:
|
|
51
51
|
- - ~>
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 0.
|
|
53
|
+
version: 0.3.0
|
|
54
54
|
type: :runtime
|
|
55
55
|
prerelease: false
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - ~>
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: 0.
|
|
60
|
+
version: 0.3.0
|
|
61
61
|
- !ruby/object:Gem::Dependency
|
|
62
62
|
name: bundler
|
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -236,22 +236,16 @@ dependencies:
|
|
|
236
236
|
name: database_cleaner
|
|
237
237
|
requirement: !ruby/object:Gem::Requirement
|
|
238
238
|
requirements:
|
|
239
|
-
- -
|
|
240
|
-
- !ruby/object:Gem::Version
|
|
241
|
-
version: 1.0.0.RC1
|
|
242
|
-
- - <
|
|
239
|
+
- - ~>
|
|
243
240
|
- !ruby/object:Gem::Version
|
|
244
|
-
version:
|
|
241
|
+
version: 1.0.1
|
|
245
242
|
type: :development
|
|
246
243
|
prerelease: false
|
|
247
244
|
version_requirements: !ruby/object:Gem::Requirement
|
|
248
245
|
requirements:
|
|
249
|
-
- -
|
|
250
|
-
- !ruby/object:Gem::Version
|
|
251
|
-
version: 1.0.0.RC1
|
|
252
|
-
- - <
|
|
246
|
+
- - ~>
|
|
253
247
|
- !ruby/object:Gem::Version
|
|
254
|
-
version:
|
|
248
|
+
version: 1.0.1
|
|
255
249
|
description: Compose and manage domain logic and data persistence separately and intelligently.
|
|
256
250
|
email:
|
|
257
251
|
- ifredwu@gmail.com
|
|
@@ -264,7 +258,6 @@ files:
|
|
|
264
258
|
- .travis.yml
|
|
265
259
|
- .yardopts
|
|
266
260
|
- CHANGELOG.md
|
|
267
|
-
- ERD.png
|
|
268
261
|
- Gemfile
|
|
269
262
|
- README.md
|
|
270
263
|
- Rakefile
|
|
@@ -277,6 +270,7 @@ files:
|
|
|
277
270
|
- lib/datamappify/data/criteria/active_record/exists.rb
|
|
278
271
|
- lib/datamappify/data/criteria/active_record/find.rb
|
|
279
272
|
- lib/datamappify/data/criteria/active_record/find_by_key.rb
|
|
273
|
+
- lib/datamappify/data/criteria/active_record/find_multiple.rb
|
|
280
274
|
- lib/datamappify/data/criteria/active_record/save.rb
|
|
281
275
|
- lib/datamappify/data/criteria/active_record/save_by_key.rb
|
|
282
276
|
- lib/datamappify/data/criteria/active_record/transaction.rb
|
|
@@ -284,6 +278,7 @@ files:
|
|
|
284
278
|
- lib/datamappify/data/criteria/relational/count.rb
|
|
285
279
|
- lib/datamappify/data/criteria/relational/find.rb
|
|
286
280
|
- lib/datamappify/data/criteria/relational/find_by_key.rb
|
|
281
|
+
- lib/datamappify/data/criteria/relational/find_multiple.rb
|
|
287
282
|
- lib/datamappify/data/criteria/relational/save.rb
|
|
288
283
|
- lib/datamappify/data/criteria/relational/save_by_key.rb
|
|
289
284
|
- lib/datamappify/data/criteria/sequel/count.rb
|
|
@@ -291,6 +286,7 @@ files:
|
|
|
291
286
|
- lib/datamappify/data/criteria/sequel/exists.rb
|
|
292
287
|
- lib/datamappify/data/criteria/sequel/find.rb
|
|
293
288
|
- lib/datamappify/data/criteria/sequel/find_by_key.rb
|
|
289
|
+
- lib/datamappify/data/criteria/sequel/find_multiple.rb
|
|
294
290
|
- lib/datamappify/data/criteria/sequel/save.rb
|
|
295
291
|
- lib/datamappify/data/criteria/sequel/save_by_key.rb
|
|
296
292
|
- lib/datamappify/data/criteria/sequel/transaction.rb
|
|
@@ -303,7 +299,10 @@ files:
|
|
|
303
299
|
- lib/datamappify/data/provider/sequel.rb
|
|
304
300
|
- lib/datamappify/data/record.rb
|
|
305
301
|
- lib/datamappify/entity.rb
|
|
302
|
+
- lib/datamappify/entity/active_model/compatibility.rb
|
|
303
|
+
- lib/datamappify/entity/composable.rb
|
|
306
304
|
- lib/datamappify/entity/lazy_checking.rb
|
|
305
|
+
- lib/datamappify/entity/relation.rb
|
|
307
306
|
- lib/datamappify/lazy.rb
|
|
308
307
|
- lib/datamappify/lazy/attributes_handler.rb
|
|
309
308
|
- lib/datamappify/lazy/source_attributes_walker.rb
|
|
@@ -317,6 +316,7 @@ files:
|
|
|
317
316
|
- lib/datamappify/repository/query_method/destroy.rb
|
|
318
317
|
- lib/datamappify/repository/query_method/exists.rb
|
|
319
318
|
- lib/datamappify/repository/query_method/find.rb
|
|
319
|
+
- lib/datamappify/repository/query_method/find_multiple.rb
|
|
320
320
|
- lib/datamappify/repository/query_method/method.rb
|
|
321
321
|
- lib/datamappify/repository/query_method/method/source_attributes_walker.rb
|
|
322
322
|
- lib/datamappify/repository/query_method/save.rb
|
|
@@ -327,21 +327,28 @@ files:
|
|
|
327
327
|
- lib/datamappify/repository/unit_of_work/persistent_states/object.rb
|
|
328
328
|
- lib/datamappify/repository/unit_of_work/transaction.rb
|
|
329
329
|
- lib/datamappify/version.rb
|
|
330
|
+
- spec/entity/composable_spec.rb
|
|
331
|
+
- spec/entity/relation_spec.rb
|
|
330
332
|
- spec/entity_spec.rb
|
|
331
333
|
- spec/lazy_spec.rb
|
|
332
334
|
- spec/repository/callbacks_spec.rb
|
|
333
335
|
- spec/repository/dirty_persistence_spec.rb
|
|
334
336
|
- spec/repository/dirty_tracking_spec.rb
|
|
337
|
+
- spec/repository/finders_spec.rb
|
|
335
338
|
- spec/repository/persistence_spec.rb
|
|
336
339
|
- spec/repository/transactions_spec.rb
|
|
337
340
|
- spec/repository/validation_spec.rb
|
|
338
341
|
- spec/repository_spec.rb
|
|
339
342
|
- spec/spec_helper.rb
|
|
340
343
|
- spec/support/entities/comment.rb
|
|
344
|
+
- spec/support/entities/computer.rb
|
|
345
|
+
- spec/support/entities/computer_hardware.rb
|
|
346
|
+
- spec/support/entities/computer_software.rb
|
|
341
347
|
- spec/support/entities/group.rb
|
|
342
348
|
- spec/support/entities/hero_user.rb
|
|
343
349
|
- spec/support/entities/role.rb
|
|
344
350
|
- spec/support/entities/user.rb
|
|
351
|
+
- spec/support/monkey_patches/database_cleaner.rb
|
|
345
352
|
- spec/support/repositories/active_record/comment_repository.rb
|
|
346
353
|
- spec/support/repositories/active_record/group_repository.rb
|
|
347
354
|
- spec/support/repositories/active_record/role_repository.rb
|
|
@@ -355,6 +362,8 @@ files:
|
|
|
355
362
|
- spec/support/shared/contexts.rb
|
|
356
363
|
- spec/support/tables/active_record.rb
|
|
357
364
|
- spec/support/tables/sequel.rb
|
|
365
|
+
- spec/unit/entity/composable_spec.rb
|
|
366
|
+
- spec/unit/entity/relation_spec.rb
|
|
358
367
|
- spec/unit/repository/query_method_spec.rb
|
|
359
368
|
homepage: https://github.com/fredwu/datamappify
|
|
360
369
|
licenses:
|
|
@@ -381,21 +390,28 @@ signing_key:
|
|
|
381
390
|
specification_version: 4
|
|
382
391
|
summary: Compose and manage domain logic and data persistence separately and intelligently.
|
|
383
392
|
test_files:
|
|
393
|
+
- spec/entity/composable_spec.rb
|
|
394
|
+
- spec/entity/relation_spec.rb
|
|
384
395
|
- spec/entity_spec.rb
|
|
385
396
|
- spec/lazy_spec.rb
|
|
386
397
|
- spec/repository/callbacks_spec.rb
|
|
387
398
|
- spec/repository/dirty_persistence_spec.rb
|
|
388
399
|
- spec/repository/dirty_tracking_spec.rb
|
|
400
|
+
- spec/repository/finders_spec.rb
|
|
389
401
|
- spec/repository/persistence_spec.rb
|
|
390
402
|
- spec/repository/transactions_spec.rb
|
|
391
403
|
- spec/repository/validation_spec.rb
|
|
392
404
|
- spec/repository_spec.rb
|
|
393
405
|
- spec/spec_helper.rb
|
|
394
406
|
- spec/support/entities/comment.rb
|
|
407
|
+
- spec/support/entities/computer.rb
|
|
408
|
+
- spec/support/entities/computer_hardware.rb
|
|
409
|
+
- spec/support/entities/computer_software.rb
|
|
395
410
|
- spec/support/entities/group.rb
|
|
396
411
|
- spec/support/entities/hero_user.rb
|
|
397
412
|
- spec/support/entities/role.rb
|
|
398
413
|
- spec/support/entities/user.rb
|
|
414
|
+
- spec/support/monkey_patches/database_cleaner.rb
|
|
399
415
|
- spec/support/repositories/active_record/comment_repository.rb
|
|
400
416
|
- spec/support/repositories/active_record/group_repository.rb
|
|
401
417
|
- spec/support/repositories/active_record/role_repository.rb
|
|
@@ -409,5 +425,7 @@ test_files:
|
|
|
409
425
|
- spec/support/shared/contexts.rb
|
|
410
426
|
- spec/support/tables/active_record.rb
|
|
411
427
|
- spec/support/tables/sequel.rb
|
|
428
|
+
- spec/unit/entity/composable_spec.rb
|
|
429
|
+
- spec/unit/entity/relation_spec.rb
|
|
412
430
|
- spec/unit/repository/query_method_spec.rb
|
|
413
431
|
has_rdoc:
|
data/ERD.png
DELETED
|
Binary file
|