dm-accepts_nested_attributes_for 1.2.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.
Files changed (58) hide show
  1. data/CHANGELOG +970 -0
  2. data/Gemfile +84 -0
  3. data/LICENSE +20 -0
  4. data/README.textile +94 -0
  5. data/Rakefile +25 -0
  6. data/TODO +6 -0
  7. data/VERSION +1 -0
  8. data/dm-accepts_nested_attributes.gemspec +114 -0
  9. data/lib/dm-accepts_nested_attributes.rb +13 -0
  10. data/lib/dm-accepts_nested_attributes/model.rb +144 -0
  11. data/lib/dm-accepts_nested_attributes/relationship.rb +82 -0
  12. data/lib/dm-accepts_nested_attributes/resource.rb +382 -0
  13. data/lib/dm-accepts_nested_attributes/version.rb +7 -0
  14. data/spec/accepts_nested_attributes_for_spec.rb +408 -0
  15. data/spec/assign_nested_attributes_for_spec.rb +101 -0
  16. data/spec/comb/1-1_disjoint_spec.rb +67 -0
  17. data/spec/comb/1-1_overlapping_spec.rb +66 -0
  18. data/spec/comb/1-1_subset_spec.rb +65 -0
  19. data/spec/comb/1-1_superset_spec.rb +67 -0
  20. data/spec/comb/1-m_disjoint_spec.rb +71 -0
  21. data/spec/comb/1-m_overlapping_spec.rb +70 -0
  22. data/spec/comb/1-m_subset_spec.rb +65 -0
  23. data/spec/comb/1-m_superset_spec.rb +71 -0
  24. data/spec/comb/m-1_disjoint_spec.rb +71 -0
  25. data/spec/comb/m-1_overlapping_spec.rb +70 -0
  26. data/spec/comb/m-1_subset_spec.rb +65 -0
  27. data/spec/comb/m-1_superset_spec.rb +71 -0
  28. data/spec/comb/n-m_composite_spec.rb +141 -0
  29. data/spec/comb/n-m_surrogate_spec.rb +154 -0
  30. data/spec/many_to_many_composite_spec.rb +120 -0
  31. data/spec/many_to_many_spec.rb +129 -0
  32. data/spec/many_to_one_composite_spec.rb +120 -0
  33. data/spec/many_to_one_spec.rb +101 -0
  34. data/spec/one_to_many_composite_spec.rb +120 -0
  35. data/spec/one_to_many_spec.rb +100 -0
  36. data/spec/one_to_one_composite_spec.rb +150 -0
  37. data/spec/one_to_one_spec.rb +115 -0
  38. data/spec/rcov.opts +6 -0
  39. data/spec/resource_spec.rb +65 -0
  40. data/spec/shared/many_to_many_composite_spec.rb +149 -0
  41. data/spec/shared/many_to_many_spec.rb +146 -0
  42. data/spec/shared/many_to_one_composite_spec.rb +160 -0
  43. data/spec/shared/many_to_one_spec.rb +130 -0
  44. data/spec/shared/one_to_many_composite_spec.rb +159 -0
  45. data/spec/shared/one_to_many_spec.rb +107 -0
  46. data/spec/shared/one_to_one_composite_spec.rb +114 -0
  47. data/spec/shared/one_to_one_spec.rb +111 -0
  48. data/spec/spec.opts +4 -0
  49. data/spec/spec_helper.rb +50 -0
  50. data/spec/update_dirty_spec.rb +113 -0
  51. data/spec/update_multiple_spec.rb +79 -0
  52. data/tasks/changelog.rake +20 -0
  53. data/tasks/ci.rake +1 -0
  54. data/tasks/local_gemfile.rake +18 -0
  55. data/tasks/spec.rake +22 -0
  56. data/tasks/yard.rake +9 -0
  57. data/tasks/yardstick.rake +19 -0
  58. metadata +216 -0
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe "1:M (PK superset FK)" do
4
+ before(:all) do
5
+ class ::Person
6
+ include DataMapper::Resource
7
+ extend ConstraintSupport
8
+
9
+ property :id, Serial, :key => true
10
+ property :audit_id, Integer, :key => true, :min => 0
11
+ property :name, String, :required => true
12
+
13
+ has n, :memberships, constraint(:destroy)
14
+ end
15
+
16
+ class ::Membership
17
+ include DataMapper::Resource
18
+
19
+ # keep properties unordered
20
+ property :project_audit_id, Integer, :key => true, :min => 0
21
+ property :person_audit_id, Integer, :key => true, :min => 0
22
+ property :person_id, Integer, :key => true, :min => 0
23
+ property :project_id, Integer, :key => true, :min => 0
24
+ property :role, String, :required => true
25
+
26
+ belongs_to :person
27
+ end
28
+
29
+ DataMapper.auto_migrate!
30
+ end
31
+
32
+ before(:each) do
33
+ Membership.all.destroy!
34
+ Person.all.destroy!
35
+ end
36
+
37
+ describe "Person.accepts_nested_attributes_for(:memberships)" do
38
+ before(:all) do
39
+ Person.accepts_nested_attributes_for :memberships
40
+ end
41
+
42
+ it "should allow to update an existing membership via Person#memberships_attributes" do
43
+ person1 = Person.create(:id => 1, :audit_id => 10, :name => 'Martin')
44
+ Membership.create(:project_id => 100, :project_audit_id => 1000, :person => person1, :role => 'maintainer')
45
+ Membership.create(:project_id => 101, :project_audit_id => 1001, :person => person1, :role => 'user')
46
+ person1.reload
47
+
48
+ person2 = Person.create(:id => 2, :audit_id => 20, :name => 'John')
49
+ Membership.create(:project_id => 200, :project_audit_id => 2000, :person => person2, :role => 'contributor')
50
+ Membership.create(:project_id => 201, :project_audit_id => 2001, :person => person2, :role => 'release-manager')
51
+ person2.reload
52
+
53
+ Person.all.size.should == 2
54
+ Membership.all.size.should == 4
55
+
56
+ person1.memberships_attributes = [{ :project_id => 100, :project_audit_id => 1000, :role => 'tester' }]
57
+ person1.save.should be_true
58
+
59
+ Person.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
60
+ [1, 10, 'Martin'],
61
+ [2, 20, 'John'],
62
+ ]
63
+ Membership.all.map { |m| [m.person_id, m.person_audit_id, m.project_id, m.project_audit_id, m.role] }.should == [
64
+ [1, 10, 100, 1000, 'tester'],
65
+ [1, 10, 101, 1001, 'user'],
66
+ [2, 20, 200, 2000, 'contributor'],
67
+ [2, 20, 201, 2001, 'release-manager'],
68
+ ]
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe "M:1 (PK disjoint FK)" do
4
+ before(:all) do
5
+ class ::Person
6
+ include DataMapper::Resource
7
+ extend ConstraintSupport
8
+
9
+ property :id, Serial, :key => true
10
+ property :audit_id, Integer, :key => true, :min => 0
11
+ property :name, String, :required => true
12
+
13
+ has n, :memberships, constraint(:destroy)
14
+ end
15
+
16
+ class ::Membership
17
+ include DataMapper::Resource
18
+
19
+ # keep properties unordered
20
+ property :person_audit_id, Integer, :min => 0
21
+ property :audit_id, Integer, :key => true, :min => 0
22
+ property :id, Integer, :key => true, :min => 0
23
+ property :person_id, Integer, :min => 0
24
+ property :role, String, :required => true
25
+
26
+ belongs_to :person
27
+ end
28
+
29
+ DataMapper.auto_migrate!
30
+ end
31
+
32
+ before(:each) do
33
+ Membership.all.destroy!
34
+ Person.all.destroy!
35
+ end
36
+
37
+ describe "Membership.accepts_nested_attributes_for(:person)" do
38
+ before(:all) do
39
+ Membership.accepts_nested_attributes_for :person
40
+ end
41
+
42
+ it "should allow to update an existing person via Membership#person_attributes" do
43
+ person1 = Person.create(:id => 1, :audit_id => 10, :name => 'Martin')
44
+ membership = Membership.create(:id => 100, :audit_id => 1000, :person => person1, :role => 'maintainer')
45
+ Membership.create(:id => 101, :audit_id => 1001, :person => person1, :role => 'user')
46
+ person1.reload
47
+
48
+ person2 = Person.create(:id => 2, :audit_id => 20, :name => 'John')
49
+ Membership.create(:id => 200, :audit_id => 2000, :person => person2, :role => 'contributor')
50
+ Membership.create(:id => 201, :audit_id => 2001, :person => person2, :role => 'release-manager')
51
+ person2.reload
52
+
53
+ Person.all.size.should == 2
54
+ Membership.all.size.should == 4
55
+
56
+ membership.person_attributes = { :name => 'Martin Gamsjaeger' }
57
+ membership.save.should be_true
58
+
59
+ Person.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
60
+ [1, 10, 'Martin Gamsjaeger'],
61
+ [2, 20, 'John'],
62
+ ]
63
+ Membership.all.map { |m| [m.person_id, m.person_audit_id, m.id, m.audit_id, m.role] }.should == [
64
+ [1, 10, 100, 1000, 'maintainer'],
65
+ [1, 10, 101, 1001, 'user'],
66
+ [2, 20, 200, 2000, 'contributor'],
67
+ [2, 20, 201, 2001, 'release-manager'],
68
+ ]
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe "M:1 (PK overlapping FK)" do
4
+ before(:all) do
5
+ class ::Person
6
+ include DataMapper::Resource
7
+ extend ConstraintSupport
8
+
9
+ property :id, Serial, :key => true
10
+ property :audit_id, Integer, :key => true, :min => 0
11
+ property :name, String, :required => true
12
+
13
+ has n, :memberships, constraint(:destroy)
14
+ end
15
+
16
+ class ::Membership
17
+ include DataMapper::Resource
18
+
19
+ # keep properties unordered
20
+ property :rank, Integer, :key => true
21
+ property :person_audit_id, Integer, :min => 0
22
+ property :person_id, Integer, :key => true, :min => 0
23
+ property :role, String, :required => true
24
+
25
+ belongs_to :person
26
+ end
27
+
28
+ DataMapper.auto_migrate!
29
+ end
30
+
31
+ before(:each) do
32
+ Membership.all.destroy!
33
+ Person.all.destroy!
34
+ end
35
+
36
+ describe "Membership.accepts_nested_attributes_for(:person)" do
37
+ before(:all) do
38
+ Membership.accepts_nested_attributes_for :person
39
+ end
40
+
41
+ it "should allow to update an existing person via Membership#person_attributes" do
42
+ person1 = Person.create(:id => 1, :audit_id => 10, :name => 'Martin')
43
+ membership = Membership.create(:person => person1, :rank => 100, :role => 'maintainer')
44
+ Membership.create(:person => person1, :rank => 101, :role => 'user')
45
+ person1.reload
46
+
47
+ person2 = Person.create(:id => 2, :audit_id => 20, :name => 'John')
48
+ Membership.create(:person => person2, :rank => 200, :role => 'contributor')
49
+ Membership.create(:person => person2, :rank => 201, :role => 'release-manager')
50
+ person2.reload
51
+
52
+ Person.all.size.should == 2
53
+ Membership.all.size.should == 4
54
+
55
+ membership.person_attributes = { :name => 'Martin Gamsjaeger' }
56
+ membership.save.should be_true
57
+
58
+ Person.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
59
+ [1, 10, 'Martin Gamsjaeger'],
60
+ [2, 20, 'John'],
61
+ ]
62
+ Membership.all.map { |m| [m.person_id, m.person_audit_id, m.rank, m.role] }.should == [
63
+ [1, 10, 100, 'maintainer'],
64
+ [1, 10, 101, 'user'],
65
+ [2, 20, 200, 'contributor'],
66
+ [2, 20, 201, 'release-manager'],
67
+ ]
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe "M:1 (PK subset FK)" do
4
+ before(:all) do
5
+ class ::Person
6
+ include DataMapper::Resource
7
+ extend ConstraintSupport
8
+
9
+ property :id, Serial, :key => true
10
+ property :audit_id, Integer, :key => true, :min => 0
11
+ property :name, String, :required => true
12
+
13
+ has n, :memberships, constraint(:destroy)
14
+ end
15
+
16
+ class ::Membership
17
+ include DataMapper::Resource
18
+
19
+ # keep properties unordered
20
+ property :person_audit_id, Integer, :key => false, :min => 0
21
+ property :person_id, Integer, :key => true, :min => 0
22
+ property :role, String, :required => true
23
+
24
+ belongs_to :person
25
+ end
26
+
27
+ DataMapper.auto_migrate!
28
+ end
29
+
30
+ before(:each) do
31
+ Membership.all.destroy!
32
+ Person.all.destroy!
33
+ end
34
+
35
+ describe "Membership.accepts_nested_attributes_for(:person)" do
36
+ before(:all) do
37
+ Membership.accepts_nested_attributes_for :person
38
+ end
39
+
40
+ it "should allow to update an existing person via Membership#person_attributes" do
41
+ person1 = Person.create(:id => 1, :audit_id => 10, :name => 'Martin')
42
+ membership = Membership.create(:person => person1, :role => 'maintainer')
43
+ person1.reload
44
+
45
+ person2 = Person.create(:id => 2, :audit_id => 20, :name => 'John')
46
+ Membership.create(:person => person2, :role => 'contributor')
47
+ person2.reload
48
+
49
+ Person.all.size.should == 2
50
+ Membership.all.size.should == 2
51
+
52
+ membership.person_attributes = { :name => 'Martin Gamsjaeger' }
53
+ membership.save.should be_true
54
+
55
+ Person.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
56
+ [1, 10, 'Martin Gamsjaeger'],
57
+ [2, 20, 'John'],
58
+ ]
59
+ Membership.all.map { |m| [m.person_id, m.person_audit_id, m.role] }.should == [
60
+ [1, 10, 'maintainer'],
61
+ [2, 20, 'contributor'],
62
+ ]
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe "M:1 (PK superset FK)" do
4
+ before(:all) do
5
+ class ::Person
6
+ include DataMapper::Resource
7
+ extend ConstraintSupport
8
+
9
+ property :id, Serial, :key => true
10
+ property :audit_id, Integer, :key => true, :min => 0
11
+ property :name, String, :required => true
12
+
13
+ has n, :memberships, constraint(:destroy)
14
+ end
15
+
16
+ class ::Membership
17
+ include DataMapper::Resource
18
+
19
+ # keep properties unordered
20
+ property :project_audit_id, Integer, :key => true, :min => 0
21
+ property :person_audit_id, Integer, :key => true, :min => 0
22
+ property :person_id, Integer, :key => true, :min => 0
23
+ property :project_id, Integer, :key => true, :min => 0
24
+ property :role, String, :required => true
25
+
26
+ belongs_to :person
27
+ end
28
+
29
+ DataMapper.auto_migrate!
30
+ end
31
+
32
+ before(:each) do
33
+ Membership.all.destroy!
34
+ Person.all.destroy!
35
+ end
36
+
37
+ describe "Membership.accepts_nested_attributes_for(:person)" do
38
+ before(:all) do
39
+ Membership.accepts_nested_attributes_for :person
40
+ end
41
+
42
+ it "should allow to update an existing person via Membership#person_attributes" do
43
+ person1 = Person.create(:id => 1, :audit_id => 10, :name => 'Martin')
44
+ membership = Membership.create(:project_id => 100, :project_audit_id => 1000, :person => person1, :role => 'maintainer')
45
+ Membership.create(:project_id => 101, :project_audit_id => 1001, :person => person1, :role => 'user')
46
+ person1.reload
47
+
48
+ person2 = Person.create(:id => 2, :audit_id => 20, :name => 'John')
49
+ Membership.create(:project_id => 200, :project_audit_id => 2000, :person => person2, :role => 'contributor')
50
+ Membership.create(:project_id => 201, :project_audit_id => 2001, :person => person2, :role => 'release-manager')
51
+ person2.reload
52
+
53
+ Person.all.size.should == 2
54
+ Membership.all.size.should == 4
55
+
56
+ membership.person_attributes = { :name => 'Martin Gamsjaeger' }
57
+ membership.save.should be_true
58
+
59
+ Person.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
60
+ [1, 10, 'Martin Gamsjaeger'],
61
+ [2, 20, 'John'],
62
+ ]
63
+ Membership.all.map { |m| [m.person_id, m.person_audit_id, m.project_id, m.project_audit_id, m.role] }.should == [
64
+ [1, 10, 100, 1000, 'maintainer'],
65
+ [1, 10, 101, 1001, 'user'],
66
+ [2, 20, 200, 2000, 'contributor'],
67
+ [2, 20, 201, 2001, 'release-manager'],
68
+ ]
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+
3
+ describe "N:M (composite PK)" do
4
+ before(:all) do
5
+ class ::Person
6
+ include DataMapper::Resource
7
+ extend ConstraintSupport
8
+
9
+ property :id, Serial, :key => true
10
+ property :audit_id, Integer, :key => true, :min => 0
11
+ property :name, String, :required => true
12
+
13
+ has n, :memberships, constraint(:destroy)
14
+ has n, :projects, :through => :memberships
15
+ end
16
+
17
+ class ::Project
18
+ include DataMapper::Resource
19
+ extend ConstraintSupport
20
+
21
+ property :id, Serial, :key => true
22
+ property :audit_id, Integer, :key => true, :min => 0
23
+ property :name, String, :required => true
24
+
25
+ has n, :memberships, constraint(:destroy)
26
+ has n, :people, :through => :memberships
27
+ end
28
+
29
+ class ::Membership
30
+ include DataMapper::Resource
31
+
32
+ # keep properties unordered
33
+ property :person_audit_id, Integer, :key => true, :min => 0
34
+ property :project_audit_id, Integer, :key => true, :min => 0
35
+ property :project_id, Integer, :key => true, :min => 0
36
+ property :person_id, Integer, :key => true, :min => 0
37
+ property :role, String
38
+
39
+ belongs_to :person
40
+ belongs_to :project
41
+ end
42
+
43
+ DataMapper.auto_migrate!
44
+ end
45
+
46
+ before(:each) do
47
+ Membership.all.destroy!
48
+ Project.all.destroy!
49
+ Person.all.destroy!
50
+ end
51
+
52
+ describe "Person.accepts_nested_attributes_for(:projects)" do
53
+ before(:all) do
54
+ Person.accepts_nested_attributes_for :projects
55
+ end
56
+
57
+ it "should allow to update an existing project via Person#projects_attributes" do
58
+ pending_if "#{DataMapper::Spec.adapter_name} doesn't support M2M", !HAS_M2M_SUPPORT do
59
+ person1 = Person.create(:id => 1, :audit_id => 10, :name => 'Martin')
60
+ project1 = Project.create(:id => 100, :audit_id => 1000, :name => 'foo')
61
+ project2 = Project.create(:id => 200, :audit_id => 2000, :name => 'bar')
62
+ Membership.create(:person => person1, :project => project1, :role => 'foo-maintainer')
63
+ Membership.create(:person => person1, :project => project2, :role => 'bar-contributor')
64
+ person1.reload
65
+
66
+ person2 = Person.create(:id => 2, :audit_id => 20, :name => 'John')
67
+ project3 = Project.create(:id => 300, :audit_id => 3000, :name => 'qux')
68
+ project4 = Project.create(:id => 400, :audit_id => 4000, :name => 'baz')
69
+ Membership.create(:person => person2, :project => project3, :role => 'qux-maintainer')
70
+ Membership.create(:person => person2, :project => project4, :role => 'baz-contributor')
71
+ person2.reload
72
+
73
+ Person.all.size.should == 2
74
+ Project.all.size.should == 4
75
+ Membership.all.size.should == 4
76
+
77
+ person1.projects_attributes = [{ :id => 100, :audit_id => 1000, :name => 'still foo' }]
78
+ person1.save.should be_true
79
+
80
+ Person.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
81
+ [1, 10, 'Martin'],
82
+ [2, 20, 'John'],
83
+ ]
84
+ Project.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
85
+ [100, 1000, 'still foo'],
86
+ [200, 2000, 'bar'],
87
+ [300, 3000, 'qux'],
88
+ [400, 4000, 'baz'],
89
+ ]
90
+ Membership.all.map { |m| [m.person_id, m.person_audit_id, m.project_id, m.project_audit_id, m.role] }.should == [
91
+ [1, 10, 100, 1000, 'foo-maintainer'],
92
+ [1, 10, 200, 2000, 'bar-contributor'],
93
+ [2, 20, 300, 3000, 'qux-maintainer'],
94
+ [2, 20, 400, 4000, 'baz-contributor'],
95
+ ]
96
+ end
97
+ end
98
+
99
+ it "should allow to create a new project via Person#projects_attributes" do
100
+ person1 = Person.create(:id => 1, :audit_id => 10, :name => 'Martin')
101
+ project1 = Project.create(:id => 100, :audit_id => 1000, :name => 'foo')
102
+ project2 = Project.create(:id => 200, :audit_id => 2000, :name => 'bar')
103
+ Membership.create(:person => person1, :project => project1, :role => 'foo-maintainer')
104
+ Membership.create(:person => person1, :project => project2, :role => 'bar-contributor')
105
+ person1.reload
106
+
107
+ person2 = Person.create(:id => 2, :audit_id => 20, :name => 'John')
108
+ project3 = Project.create(:id => 300, :audit_id => 3000, :name => 'qux')
109
+ project4 = Project.create(:id => 400, :audit_id => 4000, :name => 'baz')
110
+ Membership.create(:person => person2, :project => project3, :role => 'qux-maintainer')
111
+ Membership.create(:person => person2, :project => project4, :role => 'baz-contributor')
112
+ person2.reload
113
+
114
+ Person.all.size.should == 2
115
+ Project.all.size.should == 4
116
+ Membership.all.size.should == 4
117
+
118
+ person1.projects_attributes = [{ :id => 500, :audit_id => 5000, :name => 'fibble' }]
119
+ person1.save.should be_true
120
+
121
+ Person.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
122
+ [1, 10, 'Martin'],
123
+ [2, 20, 'John'],
124
+ ]
125
+ Project.all.map { |p| [p.id, p.audit_id, p.name] }.should == [
126
+ [100, 1000, 'foo'],
127
+ [200, 2000, 'bar'],
128
+ [300, 3000, 'qux'],
129
+ [400, 4000, 'baz'],
130
+ [500, 5000, 'fibble'],
131
+ ]
132
+ Membership.all.map { |m| [m.person_id, m.person_audit_id, m.project_id, m.project_audit_id, m.role] }.should == [
133
+ [1, 10, 100, 1000, 'foo-maintainer'],
134
+ [1, 10, 200, 2000, 'bar-contributor'],
135
+ [1, 10, 500, 5000, nil],
136
+ [2, 20, 300, 3000, 'qux-maintainer'],
137
+ [2, 20, 400, 4000, 'baz-contributor'],
138
+ ]
139
+ end
140
+ end
141
+ end