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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc8a8e06dc185a6fe88c046e23a6fb1a43c6cfbb
4
- data.tar.gz: 9f54cf6189cf5f4fcf91d2bc4a3c71bfea2df191
3
+ metadata.gz: ef8038f0a59981b26cab34b79e9358f9333d476d
4
+ data.tar.gz: d39950946d1bafd3232ad8188242e1bb8e3b150f
5
5
  SHA512:
6
- metadata.gz: 04f4bc8a8219f3d2c7c51dba054c374bf8045e6f8bf7a59713d0ff3a5e023e25135ad8696e7be16c3336203f6fa8721aabd529cd67088245fb4f712581472e83
7
- data.tar.gz: 8f22447c5b5b7fd54b900e064a25cee0c320eecd9396a1339fd3179127697d6cf8d387426937d42f41a5fd3f2044ef7a92e7532c37d2e4914624f95c811b87a5
6
+ metadata.gz: d41dc6a2da7f5fa2f72e1a6c3b9a7a6d6e3c68fe741a5845bd31f1081914343916a91b4f74b63c4f678b37e2b8dcdb2870830ad92d8cb31d9b738d3bccedffd4
7
+ data.tar.gz: 14c092eda2c25e9d8b71853dd691ad7ffaf0b2fd63c3d6248654bfcc349c6e68b613d761b6732a9fcfa2b2a0edf923c8d28d1e17c91ea524c7079eab3e64b1e8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## master
2
2
 
3
+ ## 0.10.1 [2013-03-16]
4
+
5
+ - Fixed `#save` for creating new objects.
6
+ - `#save` now performs in a transaction.
7
+
3
8
  ## 0.10.0 [2013-03-16]
4
9
 
5
10
  - Refactored `Repository`. `Entity` can now have attributes sourced from different `Data` objects.
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, Integer
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
- - Perform `save` in a transaction.
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
@@ -12,7 +12,7 @@ begin
12
12
 
13
13
  desc "Run cane to check quality metrics"
14
14
  Cane::RakeTask.new(:quality) do |cane|
15
- cane.abc_max = 10
15
+ cane.abc_max = 12
16
16
  cane.no_doc = true
17
17
  cane.style_glob = './lib/**/*.rb'
18
18
  cane.style_measure = 120
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 "m"
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 data_mapping_walker(data_mapping, id)
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, id, updated_attributes = nil)
58
+ def data_mapping_walker(data_mapping, main_object_id, updated_attributes = nil)
59
59
  composed_attributes = {}
60
60
 
61
- data_mapping.each do |data_class_name, data_fields_mapping|
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
- data_fields_with_values = {}
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
- data_fields_mapping.each_with_index do |(data_field_name, attribute_name), index|
68
- composed_attributes[attribute_name] = data_fields_with_values[data_field_name] = values[index]
69
- end
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
- if id && updated_attributes
72
- update_data_object(data_class_name, id, data_fields_with_values)
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 foreign_key_field_name
88
- "#{entity_class.name.underscore}_id"
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 find_data_object_id(data_class_name, id)
92
- if entity_class.name == data_class_name
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 update_data_object(data_class_name, id, data_fields_with_values)
116
- data_object = data_class(data_class_name).find_or_initialize_by(:id => id)
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
 
@@ -1,3 +1,3 @@
1
1
  module Datamappify
2
- VERSION = '0.10.0'
2
+ VERSION = '0.10.1'
3
3
  end
@@ -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
- it "#find" do
19
- has_db_user
18
+ describe "#find" do
19
+ it "found" do
20
+ has_db_user
20
21
 
21
- user_repository.find(1).must_equal user
22
- user_repository.find([1]).must_equal [user]
23
- end
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
- it "#save success" do
26
- new_user = user_repository.save(user_valid)
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
- it "#save! failure" do
32
- -> { user_repository.save!(user_invalid) }.must_raise Datamappify::Data::EntityNotSaved
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 = 'Steve'
39
- user.gender = 'male'
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 'Steve'
44
- updated_user.gender.must_equal 'male'
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 'Steve'
49
- persisted_user.gender.must_equal 'male'
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, String
5
- attribute :last_name, String
6
- attribute :gender, String
7
- attribute :age, Integer
8
- attribute :passport, Integer
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, 'User#sex'
9
- map_attribute :passport, 'UserPassport#number'
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.0
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-15 00:00:00.000000000 Z
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: m
124
+ name: testrbl
125
125
  requirement: !ruby/object:Gem::Requirement
126
126
  requirements:
127
127
  - - '>='