datamappify 0.10.0 → 0.10.1
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 +5 -0
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/datamappify.gemspec +1 -1
- data/lib/datamappify/repository/persistence.rb +34 -22
- data/lib/datamappify/version.rb +1 -1
- data/spec/repository/persistence_spec.rb +47 -20
- data/spec/support/active_record_tables.rb +8 -1
- data/spec/support/entities/user.rb +6 -5
- data/spec/support/repositories/user_repository.rb +3 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef8038f0a59981b26cab34b79e9358f9333d476d
|
4
|
+
data.tar.gz: d39950946d1bafd3232ad8188242e1bb8e3b150f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d41dc6a2da7f5fa2f72e1a6c3b9a7a6d6e3c68fe741a5845bd31f1081914343916a91b4f74b63c4f678b37e2b8dcdb2870830ad92d8cb31d9b738d3bccedffd4
|
7
|
+
data.tar.gz: 14c092eda2c25e9d8b71853dd691ad7ffaf0b2fd63c3d6248654bfcc349c6e68b613d761b6732a9fcfa2b2a0edf923c8d28d1e17c91ea524c7079eab3e64b1e8
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -46,7 +46,7 @@ class User
|
|
46
46
|
attribute :last_name, String
|
47
47
|
attribute :gender, String
|
48
48
|
attribute :age, Integer
|
49
|
-
attribute :passport,
|
49
|
+
attribute :passport, String
|
50
50
|
|
51
51
|
validates :first_name, :presence => true,
|
52
52
|
:length => { :minimum => 2 }
|
@@ -107,7 +107,7 @@ Refer to [CHANGELOG](CHANGELOG.md).
|
|
107
107
|
|
108
108
|
## Todo
|
109
109
|
|
110
|
-
-
|
110
|
+
- Enforce attribute type casting.
|
111
111
|
- Hooks for persistence (`before_save` and `after_save`, etc).
|
112
112
|
- Track dirty entity attributes to avoid unnecessary DB queries.
|
113
113
|
- Support for configurable primary keys and foreign keys.
|
data/Rakefile
CHANGED
data/datamappify.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency "rake"
|
27
27
|
spec.add_development_dependency "minitest"
|
28
28
|
spec.add_development_dependency "minitest-colorize"
|
29
|
-
spec.add_development_dependency "
|
29
|
+
spec.add_development_dependency "testrbl"
|
30
30
|
spec.add_development_dependency "pry"
|
31
31
|
spec.add_development_dependency "simplecov"
|
32
32
|
spec.add_development_dependency "cane"
|
@@ -34,11 +34,11 @@ module Datamappify
|
|
34
34
|
private
|
35
35
|
|
36
36
|
def find_many(ids)
|
37
|
-
ids.map { |id| find_one(id) }
|
37
|
+
ids.map { |id| find_one(id) }.compact
|
38
38
|
end
|
39
39
|
|
40
40
|
def find_one(id)
|
41
|
-
entity_class.new
|
41
|
+
exists?(id) ? entity_class.new(data_mapping_walker(data_mapping, id)) : nil
|
42
42
|
end
|
43
43
|
|
44
44
|
def create_or_update(entity)
|
@@ -55,22 +55,27 @@ module Datamappify
|
|
55
55
|
entity_class.new data_mapping_walker(data_mapping, entity.id, entity.attributes)
|
56
56
|
end
|
57
57
|
|
58
|
-
def data_mapping_walker(data_mapping,
|
58
|
+
def data_mapping_walker(data_mapping, main_object_id, updated_attributes = nil)
|
59
59
|
composed_attributes = {}
|
60
60
|
|
61
|
-
|
62
|
-
id = find_data_object_id(data_class_name, id)
|
63
|
-
values = extract_data_field_values(data_class_name, id, updated_attributes, data_fields_mapping)
|
61
|
+
default_data_class.transaction do
|
64
62
|
|
65
|
-
|
63
|
+
data_mapping.each do |data_class_name, data_fields_mapping|
|
64
|
+
values = extract_data_field_values(
|
65
|
+
data_class_name, main_object_id, updated_attributes, data_fields_mapping
|
66
|
+
)
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
68
|
+
data_fields_with_values = {}
|
69
|
+
|
70
|
+
data_fields_mapping.each_with_index do |(data_field_name, attribute_name), index|
|
71
|
+
composed_attributes[attribute_name] = data_fields_with_values[data_field_name] = values[index]
|
72
|
+
end
|
70
73
|
|
71
|
-
|
72
|
-
|
74
|
+
if updated_attributes && data_fields_need_updating?(data_fields_with_values)
|
75
|
+
create_or_update_data_object(data_class_name, main_object_id, data_fields_with_values)
|
76
|
+
end
|
73
77
|
end
|
78
|
+
|
74
79
|
end
|
75
80
|
|
76
81
|
composed_attributes
|
@@ -84,16 +89,12 @@ module Datamappify
|
|
84
89
|
"Datamappify::Data::#{data_class_name}".constantize
|
85
90
|
end
|
86
91
|
|
87
|
-
def
|
88
|
-
|
92
|
+
def key_field_name(data_class_name)
|
93
|
+
entity_class.name == data_class_name ? :id : foreign_key_field_name
|
89
94
|
end
|
90
95
|
|
91
|
-
def
|
92
|
-
|
93
|
-
id
|
94
|
-
else
|
95
|
-
data_class(data_class_name).where(foreign_key_field_name => id).pluck(:id).first
|
96
|
-
end
|
96
|
+
def foreign_key_field_name
|
97
|
+
"#{entity_class.name.underscore}_id".to_sym
|
97
98
|
end
|
98
99
|
|
99
100
|
def extract_data_field_values(data_class_name, id, updated_attributes, data_fields_mapping)
|
@@ -112,8 +113,19 @@ module Datamappify
|
|
112
113
|
attribute_names.map { |name| attributes[name] }
|
113
114
|
end
|
114
115
|
|
115
|
-
def
|
116
|
-
|
116
|
+
def data_fields_need_updating?(data_fields_with_values)
|
117
|
+
data_fields_with_values.values.compact.any?
|
118
|
+
end
|
119
|
+
|
120
|
+
def create_or_update_data_object(data_class_name, main_object_id, data_fields_with_values)
|
121
|
+
unless entity_class.name == data_class_name
|
122
|
+
data_fields_with_values[foreign_key_field_name] = main_object_id
|
123
|
+
end
|
124
|
+
|
125
|
+
data_object = data_class(data_class_name).find_or_initialize_by(
|
126
|
+
key_field_name(data_class_name) => main_object_id
|
127
|
+
)
|
128
|
+
|
117
129
|
data_object.update_attributes data_fields_with_values
|
118
130
|
end
|
119
131
|
|
data/lib/datamappify/version.rb
CHANGED
@@ -2,12 +2,12 @@ require_relative '../spec_helper'
|
|
2
2
|
|
3
3
|
describe Datamappify::Repository do
|
4
4
|
let(:user_repository) { UserRepository.instance }
|
5
|
-
let(:user) { User.new(:id => 1, :first_name => 'Fred', :passport => 'FREDWU42') }
|
6
|
-
let(:user_valid) { User.new(:first_name => 'Batman', :passport => 'ARKHAMCITY') }
|
5
|
+
let(:user) { User.new(:id => 1, :first_name => 'Fred', :gender => 'male', :passport => 'FREDWU42') }
|
6
|
+
let(:user_valid) { User.new(:first_name => 'Batman', :gender => 'male', :passport => 'ARKHAMCITY') }
|
7
7
|
let(:user_invalid) { User.new(:first_name => 'a') }
|
8
8
|
|
9
9
|
let(:has_db_user) do
|
10
|
-
Datamappify::Data::User.create!(:first_name => 'Fred')
|
10
|
+
Datamappify::Data::User.create!(:first_name => 'Fred', :sex => 'male')
|
11
11
|
Datamappify::Data::UserPassport.create!(:number => 'FREDWU42', :user_id => 1)
|
12
12
|
end
|
13
13
|
|
@@ -15,38 +15,65 @@ describe Datamappify::Repository do
|
|
15
15
|
user_repository
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
describe "#find" do
|
19
|
+
it "found" do
|
20
|
+
has_db_user
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
user_repository.find(1).must_equal user
|
23
|
+
user_repository.find([1]).must_equal [user]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "not found" do
|
27
|
+
user_repository.find(1).must_equal nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "partial found collection" do
|
31
|
+
has_db_user
|
24
32
|
|
25
|
-
|
26
|
-
|
27
|
-
new_user.must_be_kind_of User
|
28
|
-
new_user.first_name.must_equal 'Batman'
|
33
|
+
user_repository.find([1, 2]).must_equal [user]
|
34
|
+
end
|
29
35
|
end
|
30
36
|
|
31
|
-
|
32
|
-
|
37
|
+
describe "#save" do
|
38
|
+
it "success" do
|
39
|
+
user_repository.save(user_valid)
|
40
|
+
user_repository.count.must_equal 1
|
41
|
+
|
42
|
+
new_user = user_repository.find(1)
|
43
|
+
new_user.must_be_kind_of User
|
44
|
+
new_user.first_name.must_equal 'Batman'
|
45
|
+
new_user.passport.must_equal 'ARKHAMCITY'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "failure" do
|
49
|
+
-> { user_repository.save!(user_invalid) }.must_raise Datamappify::Data::EntityNotSaved
|
50
|
+
end
|
51
|
+
|
52
|
+
it "transaction" do
|
53
|
+
user_valid.driver_license = 'DEVOPS'
|
54
|
+
-> { user_repository.save(user_valid) }.must_raise ActiveRecord::StatementInvalid
|
55
|
+
|
56
|
+
user_repository.count.must_equal 0
|
57
|
+
Datamappify::Data::UserPassport.count.must_equal 0
|
58
|
+
Datamappify::Data::UserDriverLicense.count.must_equal 0
|
59
|
+
end
|
33
60
|
end
|
34
61
|
|
35
62
|
it "updates an existing record" do
|
36
63
|
has_db_user
|
37
64
|
|
38
|
-
user.first_name = '
|
39
|
-
user.gender = '
|
65
|
+
user.first_name = 'Vivian'
|
66
|
+
user.gender = 'female'
|
40
67
|
user.passport = 'LOCOMOTE'
|
41
68
|
|
42
69
|
updated_user = user_repository.save(user)
|
43
|
-
updated_user.first_name.must_equal '
|
44
|
-
updated_user.gender.must_equal '
|
70
|
+
updated_user.first_name.must_equal 'Vivian'
|
71
|
+
updated_user.gender.must_equal 'female'
|
45
72
|
updated_user.passport.must_equal 'LOCOMOTE'
|
46
73
|
|
47
74
|
persisted_user = user_repository.find(user.id)
|
48
|
-
persisted_user.first_name.must_equal '
|
49
|
-
persisted_user.gender.must_equal '
|
75
|
+
persisted_user.first_name.must_equal 'Vivian'
|
76
|
+
persisted_user.gender.must_equal 'female'
|
50
77
|
persisted_user.passport.must_equal 'LOCOMOTE'
|
51
78
|
|
52
79
|
user_repository.count.must_equal 1
|
@@ -15,7 +15,7 @@ ActiveRecord::Migration.suppress_messages do
|
|
15
15
|
create_table :users do |t|
|
16
16
|
t.string :first_name, :null => false
|
17
17
|
t.string :last_name
|
18
|
-
t.string :sex
|
18
|
+
t.string :sex, :null => false
|
19
19
|
t.integer :age
|
20
20
|
t.references :role
|
21
21
|
t.timestamps
|
@@ -47,5 +47,12 @@ ActiveRecord::Migration.suppress_messages do
|
|
47
47
|
t.belongs_to :user
|
48
48
|
t.timestamps
|
49
49
|
end
|
50
|
+
|
51
|
+
create_table :user_driver_licenses do |t|
|
52
|
+
t.string :number
|
53
|
+
t.string :expiry, :null => false
|
54
|
+
t.belongs_to :user
|
55
|
+
t.timestamps
|
56
|
+
end
|
50
57
|
end
|
51
58
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
class User
|
2
2
|
include Datamappify::Entity
|
3
3
|
|
4
|
-
attribute :first_name,
|
5
|
-
attribute :last_name,
|
6
|
-
attribute :gender,
|
7
|
-
attribute :age,
|
8
|
-
attribute :passport,
|
4
|
+
attribute :first_name, String
|
5
|
+
attribute :last_name, String
|
6
|
+
attribute :gender, String
|
7
|
+
attribute :age, Integer
|
8
|
+
attribute :passport, String
|
9
|
+
attribute :driver_license, String
|
9
10
|
|
10
11
|
validates :first_name, :presence => true,
|
11
12
|
:length => { :minimum => 2 }
|
@@ -5,6 +5,7 @@ class UserRepository
|
|
5
5
|
|
6
6
|
for_entity User
|
7
7
|
|
8
|
-
map_attribute :gender,
|
9
|
-
map_attribute :passport,
|
8
|
+
map_attribute :gender, 'User#sex'
|
9
|
+
map_attribute :passport, 'UserPassport#number'
|
10
|
+
map_attribute :driver_license, 'UserDriverLicense#number'
|
10
11
|
end
|
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.10.
|
4
|
+
version: 0.10.1
|
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-03-
|
11
|
+
date: 2013-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: virtus
|
@@ -121,7 +121,7 @@ dependencies:
|
|
121
121
|
- !ruby/object:Gem::Version
|
122
122
|
version: '0'
|
123
123
|
- !ruby/object:Gem::Dependency
|
124
|
-
name:
|
124
|
+
name: testrbl
|
125
125
|
requirement: !ruby/object:Gem::Requirement
|
126
126
|
requirements:
|
127
127
|
- - '>='
|