datamappify 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
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
  - - '>='