datamappify 0.10.1 → 0.20.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/.rspec +1 -0
- data/.travis.yml +2 -0
- data/CHANGELOG.md +11 -0
- data/README.md +55 -29
- data/datamappify.gemspec +4 -4
- data/lib/datamappify/data/errors.rb +3 -0
- data/lib/datamappify/data/provider/active_record/persistence.rb +31 -0
- data/lib/datamappify/data/provider/active_record.rb +16 -0
- data/lib/datamappify/data/provider/common/persistence.rb +57 -0
- data/lib/datamappify/data/provider/common/relational/persistence.rb +85 -0
- data/lib/datamappify/data/provider/common/relational/record/mapper.rb +24 -0
- data/lib/datamappify/data/provider/common/relational/record/writer.rb +67 -0
- data/lib/datamappify/data/provider/sequel/persistence.rb +31 -0
- data/lib/datamappify/data/provider/sequel.rb +18 -0
- data/lib/datamappify/data.rb +0 -1
- data/lib/datamappify/repository/attribute_source_data_class_builder.rb +16 -11
- data/lib/datamappify/repository/attributes_mapper.rb +17 -13
- data/lib/datamappify/repository/dsl.rb +9 -0
- data/lib/datamappify/repository/mapping_hash.rb +8 -0
- data/lib/datamappify/repository.rb +96 -4
- data/lib/datamappify/util.rb +13 -0
- data/lib/datamappify/version.rb +1 -1
- data/spec/entity_spec.rb +9 -8
- data/spec/repository/persistence_spec.rb +156 -56
- data/spec/repository_spec.rb +10 -33
- data/spec/spec_helper.rb +14 -8
- data/spec/support/entities/hero_user.rb +11 -0
- data/spec/support/entities/user.rb +5 -5
- data/spec/support/repositories/active_record/comment_repository.rb +6 -0
- data/spec/support/repositories/active_record/group_repository.rb +6 -0
- data/spec/support/repositories/active_record/role_repository.rb +6 -0
- data/spec/support/repositories/active_record/user_repository.rb +11 -0
- data/spec/support/repositories/hero_user_repository.rb +9 -0
- data/spec/support/repositories/sequel/comment_repository.rb +6 -0
- data/spec/support/repositories/sequel/group_repository.rb +6 -0
- data/spec/support/repositories/sequel/role_repository.rb +6 -0
- data/spec/support/repositories/sequel/user_repository.rb +11 -0
- data/spec/support/{active_record_tables.rb → tables/active_record.rb} +15 -9
- data/spec/support/tables/sequel.rb +76 -0
- metadata +64 -41
- data/lib/datamappify/data/base.rb +0 -7
- data/lib/datamappify/repository/persistence.rb +0 -137
- data/spec/support/repositories/comment_repository.rb +0 -7
- data/spec/support/repositories/group_repository.rb +0 -7
- data/spec/support/repositories/role_repository.rb +0 -7
- data/spec/support/repositories/user_repository.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 657efe5662156ed237a7ff2a7abf02304ea48053
|
4
|
+
data.tar.gz: a5a1ab8c879d4948099679cdc12276970e80f8f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d0fdeabfd8ba423d31bc70b7948c28419a10ae635e0189aa0e70be80db3c39a850532b2135c83c1df574204b0d7e48d84a67bd207e57ab7a3a150a7e0949869
|
7
|
+
data.tar.gz: b7ee5ed125413a9a5207355c018450d2440d738bc5fa9438a648c38848070eb708b28b5716b3f8f860ea21e4053a60cb803271323e430ccc9fcfa5bb3aa18476
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --order random
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## master
|
2
2
|
|
3
|
+
## 0.20.0 [2013-03-19]
|
4
|
+
|
5
|
+
- __Completely rewritten Repository__
|
6
|
+
- Repository now handles data construction from different ORM objects
|
7
|
+
- ActiveRecord has now been demoted to being a data provider, it is no longer tightly coupled with Repository, this means __we could have multiple data providers__!
|
8
|
+
- Repository is now much more robust
|
9
|
+
- As a result of robustness, it fixed an issue where updating an existing entity with new data records from mapped attributes will not persist the new data records correctly
|
10
|
+
- `#save` and `#destroy` now support accepting an array as their argument
|
11
|
+
- Added support for Sequel!
|
12
|
+
- Added support for mapping entity attributes to different ORMs!
|
13
|
+
|
3
14
|
## 0.10.1 [2013-03-16]
|
4
15
|
|
5
16
|
- Fixed `#save` for creating new objects.
|
data/README.md
CHANGED
@@ -1,24 +1,20 @@
|
|
1
|
-
# Datamappify [](http://badge.fury.io/rb/datamappify) [](http://travis-ci.org/fredwu/datamappify) [](https://codeclimate.com/github/fredwu/datamappify)
|
1
|
+
# Datamappify [](http://badge.fury.io/rb/datamappify) [](http://travis-ci.org/fredwu/datamappify) [](https://coveralls.io/r/fredwu/datamappify) [](https://codeclimate.com/github/fredwu/datamappify)
|
2
2
|
|
3
3
|
Separate domain logic from data persistence, based on the [Repository Pattern](http://martinfowler.com/eaaCatalog/repository.html).
|
4
4
|
|
5
|
-
|
5
|
+
Datamappify is NOT associated with the [Datamapper](https://github.com/datamapper/) project.
|
6
|
+
|
7
|
+
__Datamappify is current in Proof-of-Concept stage, do NOT use it for anything other than experimentation.__
|
6
8
|
|
7
9
|
## Overview
|
8
10
|
|
9
|
-
Datamappify is a thin layer on top of
|
11
|
+
Datamappify is a thin layer on top of [Virtus](https://github.com/solnic/virtus) and existing ORMs (ActiveRecord, etc). The design goal is to utilise the powerfulness of existing ORMs but separate domain logic (behaviour) from data persistence.
|
10
12
|
|
11
13
|
Datamappify consists of three components:
|
12
14
|
|
13
|
-
-
|
14
|
-
-
|
15
|
-
-
|
16
|
-
|
17
|
-
__Entity__ is your model, it is responsible for mainly storing behaviour. Some structure (i.e. model relationships) is also stored here for convenience.
|
18
|
-
|
19
|
-
__Data__ as the name suggests, holds your model data. It is an ActiveRecord object.
|
20
|
-
|
21
|
-
__Repository__ is responsible for data retrieval and persistence, e.g. `find`, `save` and `destroy`, etc.
|
15
|
+
- __Entity__ is your model, it is responsible for mainly storing behaviour.
|
16
|
+
- __Data__ as the name suggests, holds your model data. It is an ActiveRecord object.
|
17
|
+
- __Repository__ is responsible for data retrieval and persistence, e.g. `find`, `save` and `destroy`, etc.
|
22
18
|
|
23
19
|
## Installation
|
24
20
|
|
@@ -38,15 +34,18 @@ Or install it yourself as:
|
|
38
34
|
|
39
35
|
### Entity
|
40
36
|
|
37
|
+
Entity uses [Virtus](https://github.com/solnic/virtus) DSL for defining attributes and [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations.html) DSL for validations.
|
38
|
+
|
41
39
|
```ruby
|
42
40
|
class User
|
43
41
|
include Datamappify::Entity
|
44
42
|
|
45
|
-
attribute :first_name,
|
46
|
-
attribute :last_name,
|
47
|
-
attribute :
|
48
|
-
attribute :
|
49
|
-
attribute :
|
43
|
+
attribute :first_name, String
|
44
|
+
attribute :last_name, String
|
45
|
+
attribute :age, Integer
|
46
|
+
attribute :passport, String
|
47
|
+
attribute :driver_license, String
|
48
|
+
attribute :health_care, String
|
50
49
|
|
51
50
|
validates :first_name, :presence => true,
|
52
51
|
:length => { :minimum => 2 }
|
@@ -61,6 +60,8 @@ end
|
|
61
60
|
|
62
61
|
### Repository
|
63
62
|
|
63
|
+
Map entity attributes to DB columns - better yet, you can even map attributes to __different ORMs__!
|
64
|
+
|
64
65
|
```ruby
|
65
66
|
class UserRepository
|
66
67
|
include Datamappify::Repository
|
@@ -68,39 +69,63 @@ class UserRepository
|
|
68
69
|
# specify the entity class
|
69
70
|
for_entity User
|
70
71
|
|
72
|
+
# specify the default data provider for unmapped attributes
|
73
|
+
default_provider :ActiveRecord
|
74
|
+
|
71
75
|
# specify any attributes that need to be mapped
|
72
76
|
#
|
73
77
|
# for example:
|
74
|
-
# - '
|
75
|
-
# - '
|
76
|
-
# -
|
77
|
-
|
78
|
-
map_attribute :
|
78
|
+
# - 'last_name' is mapped to the 'User' ActiveRecord class and its 'surname' attribute
|
79
|
+
# - 'driver_license' is mapped to the 'UserDriverLicense' ActiveRecord class and its 'number' attribute
|
80
|
+
# - 'passport' is mapped to the 'UserPassport' Sequel class and its 'number' attribute
|
81
|
+
# - attributes not specified here are mapped automatically to 'ActiveRecord::User'
|
82
|
+
map_attribute :last_name, 'ActiveRecord::User#surname'
|
83
|
+
map_attribute :driver_license, 'ActiveRecord::UserDriverLicense#number'
|
84
|
+
map_attribute :passport, 'Sequel::UserPassport#number'
|
85
|
+
map_attribute :health_care, 'Sequel::UserHealthCare#number'
|
79
86
|
end
|
80
|
-
|
81
|
-
user_repository = UserRepository.instance
|
82
87
|
```
|
83
88
|
|
84
|
-
#### Retrieving
|
89
|
+
#### Retrieving entities
|
90
|
+
|
91
|
+
Pass in an id or an array of ids.
|
85
92
|
|
86
93
|
```ruby
|
87
|
-
user
|
94
|
+
user = UserRepository.instance.find(1)
|
95
|
+
users = UserRepository.instance.find([1, 2, 3])
|
88
96
|
```
|
89
97
|
|
90
|
-
#### Saving/updating
|
98
|
+
#### Saving/updating entities
|
99
|
+
|
100
|
+
Pass in an entity or an array of entities.
|
101
|
+
|
102
|
+
There is also `save!` that raises `Datamappify::Data::EntityNotSaved`.
|
91
103
|
|
92
104
|
```ruby
|
93
|
-
|
105
|
+
UserRepository.instance.save(user)
|
106
|
+
UserRepository.instance.save([user, user2, user3])
|
94
107
|
```
|
95
108
|
|
96
109
|
#### Destroying an entity
|
97
110
|
|
111
|
+
Pass in an entity, an id, an array of entities or an array of ids.
|
112
|
+
|
113
|
+
There is also `destroy!` that raises `Datamappify::Data::EntityNotDestroyed`.
|
114
|
+
|
98
115
|
Note that due to the attributes mapping, any data found in mapped ActiveRecord objects are not touched.
|
99
116
|
|
100
117
|
```ruby
|
101
|
-
|
118
|
+
UserRepository.instance.destroy(1)
|
119
|
+
UserRepository.instance.destroy([1, 2, 3])
|
120
|
+
UserRepository.instance.destroy(user)
|
121
|
+
UserRepository.instance.destroy([user, user2, user3])
|
102
122
|
```
|
103
123
|
|
124
|
+
## Supported ORMs
|
125
|
+
|
126
|
+
- ActiveRecord
|
127
|
+
- Sequel
|
128
|
+
|
104
129
|
## Changelog
|
105
130
|
|
106
131
|
Refer to [CHANGELOG](CHANGELOG.md).
|
@@ -117,6 +142,7 @@ Refer to [CHANGELOG](CHANGELOG.md).
|
|
117
142
|
|
118
143
|
- [Curator](https://github.com/braintree/curator)
|
119
144
|
- [Edr](https://github.com/nulogy/edr)
|
145
|
+
- [Minimapper](https://github.com/joakimk/minimapper)
|
120
146
|
|
121
147
|
## Author
|
122
148
|
|
data/datamappify.gemspec
CHANGED
@@ -20,16 +20,16 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_dependency "virtus", "~> 0.5"
|
22
22
|
spec.add_dependency "activesupport", ">= 4.0.0.beta1", "< 5"
|
23
|
-
spec.add_dependency "activerecord", ">= 4.0.0.beta1", "< 5"
|
24
23
|
|
25
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
26
25
|
spec.add_development_dependency "rake"
|
27
|
-
spec.add_development_dependency "
|
28
|
-
spec.add_development_dependency "minitest-colorize"
|
29
|
-
spec.add_development_dependency "testrbl"
|
26
|
+
spec.add_development_dependency "rspec"
|
30
27
|
spec.add_development_dependency "pry"
|
31
28
|
spec.add_development_dependency "simplecov"
|
32
29
|
spec.add_development_dependency "cane"
|
30
|
+
spec.add_development_dependency "coveralls"
|
33
31
|
spec.add_development_dependency "sqlite3"
|
32
|
+
spec.add_development_dependency "sequel"
|
33
|
+
spec.add_development_dependency "activerecord", ">= 4.0.0.beta1", "< 5"
|
34
34
|
spec.add_development_dependency "database_cleaner", ">= 1.0.0.RC1", "< 2"
|
35
35
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'datamappify/data/provider/common/relational/persistence'
|
2
|
+
require 'datamappify/data/provider/common/relational/record/mapper'
|
3
|
+
require 'datamappify/data/provider/common/relational/record/writer'
|
4
|
+
|
5
|
+
module Datamappify
|
6
|
+
module Data
|
7
|
+
module Provider
|
8
|
+
module ActiveRecord
|
9
|
+
class Persistence < Data::Provider::Common::Relational::Persistence
|
10
|
+
def destroy(ids)
|
11
|
+
data_class.destroy(ids)
|
12
|
+
end
|
13
|
+
|
14
|
+
def exists?(id)
|
15
|
+
data_class.exists?(id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def transaction(&block)
|
19
|
+
data_class.transaction(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def record_attributes_method
|
25
|
+
:attributes
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'datamappify/data/provider/active_record/persistence'
|
2
|
+
|
3
|
+
module Datamappify
|
4
|
+
module Data
|
5
|
+
module ActiveRecord
|
6
|
+
end
|
7
|
+
|
8
|
+
module Provider
|
9
|
+
module ActiveRecord
|
10
|
+
def self.build_data_class(data_class_name)
|
11
|
+
Datamappify::Data::ActiveRecord.const_set(data_class_name, Class.new(::ActiveRecord::Base))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Datamappify
|
2
|
+
module Data
|
3
|
+
module Provider
|
4
|
+
module Common
|
5
|
+
class Persistence
|
6
|
+
def initialize(provider_class_name, entities, data_class_name)
|
7
|
+
@provider_class_name = provider_class_name
|
8
|
+
@entities = entities
|
9
|
+
@data_class_name = data_class_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(data_fields_mapping)
|
13
|
+
raise Data::MethodNotImplemented
|
14
|
+
end
|
15
|
+
|
16
|
+
def create(data_fields_mapping)
|
17
|
+
raise Data::MethodNotImplemented
|
18
|
+
end
|
19
|
+
|
20
|
+
def update(data_fields_mapping)
|
21
|
+
raise Data::MethodNotImplemented
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy(id_or_entity)
|
25
|
+
raise Data::MethodNotImplemented
|
26
|
+
end
|
27
|
+
|
28
|
+
def exists?(id)
|
29
|
+
raise Data::MethodNotImplemented
|
30
|
+
end
|
31
|
+
|
32
|
+
def transaction(&block)
|
33
|
+
raise Data::MethodNotImplemented
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(symbol, *args)
|
37
|
+
data_class.send symbol, *args
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def data_class
|
43
|
+
"Datamappify::Data::#{@provider_class_name}::#{@data_class_name}".constantize
|
44
|
+
end
|
45
|
+
|
46
|
+
def entity_class_name
|
47
|
+
@entities[0].class.name
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_entity_class?
|
51
|
+
@data_class_name == entity_class_name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'datamappify/data/provider/common/persistence'
|
2
|
+
|
3
|
+
module Datamappify
|
4
|
+
module Data
|
5
|
+
module Provider
|
6
|
+
module Common
|
7
|
+
module Relational
|
8
|
+
class Persistence < Data::Provider::Common::Persistence
|
9
|
+
def find(data_fields_mapping)
|
10
|
+
records = find_records(data_fields_mapping)
|
11
|
+
|
12
|
+
entities_walker do |entity|
|
13
|
+
if record = find_record_for_entity(entity, records)
|
14
|
+
Common::Relational::RecordMapper.new(
|
15
|
+
entity, record.send(record_attributes_method)
|
16
|
+
).map_attributes(data_fields_mapping)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def create(data_fields_mapping)
|
22
|
+
entities_walker do |entity|
|
23
|
+
if has_data_to_insert?(entity, data_fields_mapping)
|
24
|
+
Common::Relational::RecordWriter.new(
|
25
|
+
entity, data_class, key_field_name
|
26
|
+
).insert_record(data_fields_mapping)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def update(data_fields_mapping)
|
32
|
+
records = find_records(data_fields_mapping)
|
33
|
+
|
34
|
+
entities_walker do |entity|
|
35
|
+
record_writer = Common::Relational::RecordWriter.new(entity, data_class, key_field_name)
|
36
|
+
|
37
|
+
if record = find_record_for_entity(entity, records)
|
38
|
+
record_writer.update_record(record, data_fields_mapping)
|
39
|
+
elsif has_data_to_insert?(entity, data_fields_mapping)
|
40
|
+
record_writer.insert_record(data_fields_mapping)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def find_record_for_entity(entity, records)
|
48
|
+
records.find { |r| r.send(key_field_name) == entity.id }
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_records(data_fields_mapping)
|
52
|
+
data_class.select(
|
53
|
+
*field_names(data_fields_mapping)
|
54
|
+
).where(
|
55
|
+
key_field_name => @entities.map(&:id)
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def entities_walker
|
60
|
+
walker_method = is_entity_class? ? :keep_if : :each
|
61
|
+
|
62
|
+
@entities.send(walker_method) do |entity|
|
63
|
+
yield(entity)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def key_field_name
|
68
|
+
is_entity_class? ? :id : "#{entity_class_name.underscore}_id".to_sym
|
69
|
+
end
|
70
|
+
|
71
|
+
def field_names(data_fields_mapping)
|
72
|
+
(data_fields_mapping.field_names << key_field_name << :id).uniq
|
73
|
+
end
|
74
|
+
|
75
|
+
def has_data_to_insert?(entity, data_fields_mapping)
|
76
|
+
attribute_names = entity.attributes.keys & data_fields_mapping.attribute_names
|
77
|
+
|
78
|
+
attribute_names.any? && Util.attributes_filtered_by(entity, attribute_names).values.compact.any?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Datamappify
|
2
|
+
module Data
|
3
|
+
module Provider
|
4
|
+
module Common
|
5
|
+
module Relational
|
6
|
+
class RecordMapper
|
7
|
+
def initialize(entity, record_attributes)
|
8
|
+
@entity = entity
|
9
|
+
@record_attributes = record_attributes
|
10
|
+
end
|
11
|
+
|
12
|
+
def map_attributes(data_fields_mapping)
|
13
|
+
@record_attributes.each do |name, value|
|
14
|
+
return unless data_fields_mapping.has_key?(name.to_sym)
|
15
|
+
|
16
|
+
@entity.send(:"#{data_fields_mapping[name.to_sym]}=", value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Datamappify
|
2
|
+
module Data
|
3
|
+
module Provider
|
4
|
+
module Common
|
5
|
+
module Relational
|
6
|
+
class RecordWriter
|
7
|
+
def initialize(entity, data_class, key_field_name)
|
8
|
+
@entity = entity
|
9
|
+
@data_class = data_class
|
10
|
+
@key_field_name = key_field_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def insert_record(data_fields_mapping)
|
14
|
+
if is_foreign_record?
|
15
|
+
insert_foreign_record(data_fields_mapping)
|
16
|
+
else
|
17
|
+
new_record = insert_primary_record(data_fields_mapping)
|
18
|
+
update_entity_with_new_record_id(new_record.id)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def update_record(record, data_fields_mapping)
|
23
|
+
update_record_with_fields(record, data_fields_mapping)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def is_foreign_record?
|
29
|
+
@key_field_name != :id
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_an_empty_primary_key?(attribute_name)
|
33
|
+
(attribute_name == :id) && @entity.attributes[attribute_name].nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
def insert_foreign_record(data_fields_mapping)
|
37
|
+
new_record = @data_class.new
|
38
|
+
new_record.send "#{@key_field_name}=", @entity.id
|
39
|
+
update_record_with_fields(new_record, data_fields_mapping)
|
40
|
+
end
|
41
|
+
|
42
|
+
def insert_primary_record(data_fields_mapping)
|
43
|
+
update_record_with_fields(@data_class.new, data_fields_mapping)
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_record_with_fields(record, data_fields_mapping)
|
47
|
+
data_fields_mapping.field_names.each do |field_name|
|
48
|
+
attribute_name = data_fields_mapping[field_name]
|
49
|
+
|
50
|
+
unless is_an_empty_primary_key?(attribute_name)
|
51
|
+
record.send "#{field_name}=", @entity.attributes[attribute_name]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
record.save
|
56
|
+
record
|
57
|
+
end
|
58
|
+
|
59
|
+
def update_entity_with_new_record_id(id)
|
60
|
+
@entity.id = id
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'datamappify/data/provider/common/relational/persistence'
|
2
|
+
require 'datamappify/data/provider/common/relational/record/mapper'
|
3
|
+
require 'datamappify/data/provider/common/relational/record/writer'
|
4
|
+
|
5
|
+
module Datamappify
|
6
|
+
module Data
|
7
|
+
module Provider
|
8
|
+
module Sequel
|
9
|
+
class Persistence < Data::Provider::Common::Relational::Persistence
|
10
|
+
def destroy(ids)
|
11
|
+
data_class.where(:id => ids).destroy
|
12
|
+
end
|
13
|
+
|
14
|
+
def exists?(id)
|
15
|
+
data_class.where(:id => id).any?
|
16
|
+
end
|
17
|
+
|
18
|
+
def transaction(&block)
|
19
|
+
data_class.db.transaction(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def record_attributes_method
|
25
|
+
:values
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'datamappify/data/provider/sequel/persistence'
|
2
|
+
|
3
|
+
module Datamappify
|
4
|
+
module Data
|
5
|
+
module Sequel
|
6
|
+
end
|
7
|
+
|
8
|
+
module Provider
|
9
|
+
module Sequel
|
10
|
+
def self.build_data_class(data_class_name)
|
11
|
+
Datamappify::Data::Sequel.const_set(
|
12
|
+
data_class_name, Class.new(::Sequel::Model(data_class_name.pluralize.underscore.to_sym))
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/datamappify/data.rb
CHANGED
@@ -1,22 +1,27 @@
|
|
1
1
|
module Datamappify
|
2
2
|
module Repository
|
3
3
|
class AttributeSourceDataClassBuilder
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def initialize(provider_class_name, data_class_name)
|
5
|
+
@provider_class_name = provider_class_name
|
6
|
+
@data_class_name = data_class_name
|
7
|
+
end
|
8
|
+
|
9
|
+
def build(data_fields_mapping)
|
10
|
+
require "datamappify/data/provider/#{@provider_class_name.underscore}"
|
7
11
|
|
8
|
-
|
12
|
+
unless data_class_is_defined?
|
13
|
+
provider_module.build_data_class(@data_class_name)
|
9
14
|
end
|
15
|
+
end
|
10
16
|
|
11
|
-
|
17
|
+
private
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
19
|
+
def provider_module
|
20
|
+
@provider_module ||= "Datamappify::Data::Provider::#{@provider_class_name}".constantize
|
21
|
+
end
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
23
|
+
def data_class_is_defined?
|
24
|
+
provider_module.const_defined?(@data_class_name, false)
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
@@ -6,27 +6,29 @@ module Datamappify
|
|
6
6
|
def initialize(repository)
|
7
7
|
@repository = repository
|
8
8
|
|
9
|
-
|
9
|
+
map_non_custom_entity_attributes
|
10
|
+
map_custom_entity_attributes
|
10
11
|
end
|
11
12
|
|
12
13
|
def build_data_classes
|
13
|
-
@repository.data_mapping.each do |
|
14
|
-
|
14
|
+
@repository.data_mapping.each do |provider_class_name, data_class_mapping|
|
15
|
+
data_class_mapping.each do |data_class_name, data_fields_mapping|
|
16
|
+
AttributeSourceDataClassBuilder.new(provider_class_name, data_class_name).build(data_fields_mapping)
|
17
|
+
end
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
18
21
|
private
|
19
22
|
|
20
|
-
def map_entity_attributes
|
21
|
-
map_non_custom_entity_attributes
|
22
|
-
map_custom_entity_attributes
|
23
|
-
end
|
24
|
-
|
25
23
|
def map_non_custom_entity_attributes
|
26
|
-
@repository.
|
24
|
+
provider_name = @repository.default_provider_class_name
|
25
|
+
data_class_name = @repository.entity_class.name
|
26
|
+
|
27
|
+
@repository.data_mapping[provider_name] ||= {}
|
28
|
+
@repository.data_mapping[provider_name][data_class_name] ||= MappingHash.new
|
27
29
|
|
28
30
|
non_custom_attributes.each do |attribute_name|
|
29
|
-
@repository.data_mapping[
|
31
|
+
@repository.data_mapping[provider_name][data_class_name][attribute_name] = attribute_name
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
@@ -41,10 +43,12 @@ module Datamappify
|
|
41
43
|
end
|
42
44
|
|
43
45
|
def map_custom_entity_attribute(attribute_name, source)
|
44
|
-
|
46
|
+
namespaced_data_class_name, data_field_name = source.split('#')
|
47
|
+
provider_name, data_class_name = namespaced_data_class_name.split('::')
|
45
48
|
|
46
|
-
@repository.data_mapping[
|
47
|
-
@repository.data_mapping[
|
49
|
+
@repository.data_mapping[provider_name] ||= {}
|
50
|
+
@repository.data_mapping[provider_name][data_class_name] ||= MappingHash.new
|
51
|
+
@repository.data_mapping[provider_name][data_class_name][data_field_name.to_sym] = attribute_name
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|