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,115 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Person.has(1, :profile);" do
4
+
5
+ before(:all) do
6
+
7
+ class ::Person
8
+
9
+ include DataMapper::Resource
10
+ extend ConstraintSupport
11
+
12
+ property :id, Serial
13
+ property :name, String, :required => true
14
+
15
+ has 1, :profile, constraint(:destroy)
16
+ has 1, :address, :through => :profile
17
+
18
+ end
19
+
20
+ class ::Profile
21
+
22
+ include DataMapper::Resource
23
+
24
+ property :id, Serial
25
+ property :nick, String, :required => true
26
+
27
+ belongs_to :person
28
+ has 1, :address
29
+
30
+ end
31
+
32
+ class ::Address
33
+
34
+ include DataMapper::Resource
35
+
36
+ property :id, Serial
37
+ property :profile_id, Integer, :required => true, :unique => true, :unique_index => true, :min => 0
38
+ property :body, String, :required => true
39
+
40
+ belongs_to :profile
41
+
42
+ end
43
+
44
+ DataMapper.auto_migrate!
45
+
46
+ end
47
+
48
+ before(:each) do
49
+ Address.all.destroy!
50
+ Profile.all.destroy!
51
+ Person.all.destroy!
52
+ end
53
+
54
+
55
+ describe "Person.accepts_nested_attributes_for(:profile)" do
56
+
57
+ before(:all) do
58
+ Person.accepts_nested_attributes_for :profile
59
+ end
60
+
61
+ it_should_behave_like "every accessible one_to_one association"
62
+ it_should_behave_like "every accessible one_to_one association with no reject_if proc"
63
+ it_should_behave_like "every accessible one_to_one association with :allow_destroy => false"
64
+
65
+ end
66
+
67
+ describe "Person.accepts_nested_attributes_for(:profile, :allow_destroy => false)" do
68
+
69
+ before(:all) do
70
+ Person.accepts_nested_attributes_for :profile, :allow_destroy => false
71
+ end
72
+
73
+ it_should_behave_like "every accessible one_to_one association"
74
+ it_should_behave_like "every accessible one_to_one association with no reject_if proc"
75
+ it_should_behave_like "every accessible one_to_one association with :allow_destroy => false"
76
+
77
+ end
78
+
79
+ describe "Person.accepts_nested_attributes_for(:profile, :allow_destroy => true)" do
80
+
81
+ before(:all) do
82
+ Person.accepts_nested_attributes_for :profile, :allow_destroy => true
83
+ end
84
+
85
+ it_should_behave_like "every accessible one_to_one association"
86
+ it_should_behave_like "every accessible one_to_one association with no reject_if proc"
87
+ it_should_behave_like "every accessible one_to_one association with :allow_destroy => true"
88
+
89
+ end
90
+
91
+ describe "Person.accepts_nested_attributes_for(:profile, :reject_if => lambda { |attrs| true })" do
92
+
93
+ before(:all) do
94
+ Person.accepts_nested_attributes_for :profile, :reject_if => lambda { |attrs| true }
95
+ end
96
+
97
+ it_should_behave_like "every accessible one_to_one association"
98
+ it_should_behave_like "every accessible one_to_one association with a valid reject_if proc"
99
+ it_should_behave_like "every accessible one_to_one association with :allow_destroy => false"
100
+
101
+ end
102
+
103
+ describe "Person.accepts_nested_attributes_for(:profile, :reject_if => lambda { |attrs| false })" do
104
+
105
+ before(:all) do
106
+ Person.accepts_nested_attributes_for :profile, :reject_if => lambda { |attrs| false }
107
+ end
108
+
109
+ it_should_behave_like "every accessible one_to_one association"
110
+ it_should_behave_like "every accessible one_to_one association with no reject_if proc"
111
+ it_should_behave_like "every accessible one_to_one association with :allow_destroy => false"
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,6 @@
1
+ --exclude "spec"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --profile
6
+ --text-summary
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataMapper::NestedAttributes::Resource do
4
+
5
+ before(:all) do
6
+ class ::Project
7
+ include DataMapper::Resource
8
+ extend ConstraintSupport
9
+
10
+ property :id, Integer, :key => true, :min => 0
11
+ property :name, String, :required => true
12
+
13
+ has n, :memberships, constraint(:destroy)
14
+ has n, :people, :through => :memberships
15
+ end
16
+
17
+ class ::Person
18
+ include DataMapper::Resource
19
+ extend ConstraintSupport
20
+
21
+ property :id, Integer, :key => true, :min => 0
22
+ property :name, String, :required => true
23
+
24
+ has n, :memberships, constraint(:destroy)
25
+ has n, :projects, :through => :memberships
26
+ accepts_nested_attributes_for :memberships, :allow_destroy => true
27
+ end
28
+
29
+ class ::Membership
30
+ include DataMapper::Resource
31
+
32
+ property :person_id, Integer, :key => true, :min => 0
33
+ property :project_id, Integer, :key => true, :min => 0
34
+ property :role, String, :required => true
35
+
36
+ belongs_to :person
37
+ belongs_to :project
38
+
39
+ accepts_nested_attributes_for :person
40
+ accepts_nested_attributes_for :project
41
+ end
42
+
43
+ DataMapper.auto_migrate!
44
+ end
45
+
46
+ before(:each) do
47
+ Membership.all.destroy!
48
+ Person.all.destroy!
49
+ Project.all.destroy!
50
+ end
51
+
52
+ describe "#uncreatable_keys" do
53
+ it "includes delete marker" do
54
+ Person.new.send(:uncreatable_keys).should == [:_delete]
55
+ Membership.new.send(:uncreatable_keys).should == [:_delete]
56
+ end
57
+ end
58
+
59
+ describe "#unupdateable_keys" do
60
+ it "includes primary keys and delete marker" do
61
+ Person.new.send(:unupdatable_keys).should == [:id, :_delete]
62
+ Membership.new.send(:unupdatable_keys).should == [:person_id, :project_id, :_delete]
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,149 @@
1
+ describe "every accessible many_to_many composite association", :shared => true do
2
+
3
+ it "should allow to update an existing project via Person#projects_attributes" do
4
+ pending_if "#{DataMapper::Spec.adapter_name} doesn't support M2M", !HAS_M2M_SUPPORT do
5
+ Person.all.size.should == 0
6
+ Project.all.size.should == 0
7
+ Membership.all.size.should == 0
8
+
9
+ person = Person.create(:audit_id => 1, :name => 'snusnu')
10
+ project = Project.create(:audit_id => 2, :name => 'dm-accepts_nested_attributes')
11
+ membership = Membership.create(:person => person, :project => project, :role => 'maintainer')
12
+
13
+ Person.all.size.should == 1
14
+ Project.all.size.should == 1
15
+ Membership.all.size.should == 1
16
+
17
+ person.projects_attributes = [{
18
+ :id => project.id,
19
+ :audit_id => project.audit_id,
20
+ :name => 'still dm-accepts_nested_attributes'
21
+ }]
22
+ person.save
23
+
24
+ Person.all.size.should == 1
25
+ Project.all.size.should == 1
26
+ Membership.all.size.should == 1
27
+
28
+ Project.first.name.should == 'still dm-accepts_nested_attributes'
29
+ end
30
+ end
31
+
32
+ it "should return the attributes written to Person#projects_attributes from the Person#projects_attributes reader" do
33
+ person = Person.new(:audit_id => 1, :name => 'snusnu')
34
+ person.projects_attributes.should be_nil
35
+ person.projects_attributes = [{ :name => 'write specs' }]
36
+ person.projects_attributes.should == [{ :name => 'write specs' }]
37
+ end
38
+
39
+ end
40
+
41
+ describe "every accessible many_to_many composite association with a valid reject_if proc", :shared => true do
42
+
43
+ it "should not allow to create a new project via Person#projects_attributes" do
44
+ Person.all.size.should == 0
45
+ Project.all.size.should == 0
46
+ Membership.all.size.should == 0
47
+
48
+ person = Person.create(:audit_id => 1, :name => 'snusnu')
49
+
50
+ Person.all.size.should == 1
51
+ Project.all.size.should == 0
52
+ Membership.all.size.should == 0
53
+
54
+ person.projects_attributes = [{ :name => 'dm-accepts_nested_attributes' }]
55
+ person.save
56
+
57
+ Person.all.size.should == 1
58
+ Project.all.size.should == 0
59
+ Membership.all.size.should == 0
60
+ end
61
+
62
+ end
63
+
64
+ describe "every accessible many_to_many composite association with no reject_if proc", :shared => true do
65
+
66
+ it "should allow to create a new project via Person#projects_attributes" do
67
+ Person.all.size.should == 0
68
+ Project.all.size.should == 0
69
+ Membership.all.size.should == 0
70
+
71
+ person = Person.create(:audit_id => 1, :name => 'snusnu')
72
+
73
+ Person.all.size.should == 1
74
+ Project.all.size.should == 0
75
+ Membership.all.size.should == 0
76
+
77
+ person.projects_attributes = [{ :audit_id => 2, :name => 'dm-accepts_nested_attributes' }]
78
+
79
+ Person.all.size.should == 1
80
+ Project.all.size.should == 0
81
+ Membership.all.size.should == 0
82
+
83
+ person.save
84
+
85
+ Person.all.size.should == 1
86
+ Project.all.size.should == 1
87
+ Membership.all.size.should == 1
88
+
89
+ Project.first.name.should == 'dm-accepts_nested_attributes'
90
+ end
91
+
92
+ end
93
+
94
+ describe "every accessible many_to_many composite association with :allow_destroy => false", :shared => true do
95
+
96
+ it "should not allow to delete an existing project via Person#projects_attributes" do
97
+ person = Person.create(:audit_id => 1, :name => 'snusnu')
98
+ project = Project.create(:audit_id => 2, :name => 'dm-accepts_nested_attributes')
99
+ membership = Membership.create(:person => person, :project => project)
100
+
101
+ Person.all.size.should == 1
102
+ Project.all.size.should == 1
103
+ Membership.all.size.should == 1
104
+
105
+ person.projects_attributes = [{ :id => project.id, :audit_id => project.audit_id, :_delete => true }]
106
+
107
+ Person.all.size.should == 1
108
+ Project.all.size.should == 1
109
+ Membership.all.size.should == 1
110
+
111
+ person.save
112
+
113
+ Person.all.size.should == 1
114
+ Project.all.size.should == 1
115
+ Membership.all.size.should == 1
116
+ end
117
+
118
+ end
119
+
120
+ describe "every accessible many_to_many composite association with :allow_destroy => true", :shared => true do
121
+
122
+ it "should allow to delete an existing project via Person#projects_attributes" do
123
+ pending_if "#{DataMapper::Spec.adapter_name} doesn't support M2M", !HAS_M2M_SUPPORT do
124
+ person = Person.create(:audit_id => 1, :name => 'snusnu')
125
+
126
+ project_1 = Project.create(:audit_id => 2, :name => 'dm-accepts_nested_attributes')
127
+ project_2 = Project.create(:audit_id => 3, :name => 'dm-is-localizable')
128
+ membership_1 = Membership.create(:person => person, :project => project_1)
129
+ membership_2 = Membership.create(:person => person, :project => project_2)
130
+
131
+ Person.all.size.should == 1
132
+ Project.all.size.should == 2
133
+ Membership.all.size.should == 2
134
+
135
+ person.projects_attributes = [{ :id => project_1.id, :audit_id => project_1.audit_id, :_delete => true }]
136
+
137
+ Person.all.size.should == 1
138
+ Project.all.size.should == 2
139
+ Membership.all.size.should == 2
140
+
141
+ person.save
142
+
143
+ Person.all.size.should == 1
144
+ Project.all.size.should == 1
145
+ Membership.all.size.should == 1
146
+ end
147
+ end
148
+
149
+ end
@@ -0,0 +1,146 @@
1
+ describe "every accessible many_to_many association", :shared => true do
2
+
3
+ it "should allow to update an existing project via Person#projects_attributes" do
4
+ pending_if "#{DataMapper::Spec.adapter_name} doesn't support M2M", !HAS_M2M_SUPPORT do
5
+ Person.all.size.should == 0
6
+ Project.all.size.should == 0
7
+ ProjectMembership.all.size.should == 0
8
+
9
+ person = Person.create :name => 'snusnu'
10
+ project = Project.create(:name => 'dm-accepts_nested_attributes')
11
+ project_membership = ProjectMembership.create(:person => person, :project => project)
12
+
13
+ Person.all.size.should == 1
14
+ Project.all.size.should == 1
15
+ ProjectMembership.all.size.should == 1
16
+
17
+ person.projects_attributes = [{ :id => project.id, :name => 'still dm-accepts_nested_attributes' }]
18
+ person.save
19
+
20
+ Person.all.size.should == 1
21
+ ProjectMembership.all.size.should == 1
22
+ Project.all.size.should == 1
23
+
24
+ Project.first.name.should == 'still dm-accepts_nested_attributes'
25
+ end
26
+ end
27
+
28
+ it "should return the attributes written to Person#projects_attributes from the Person#projects_attributes reader" do
29
+ person = Person.new :name => 'snusnu'
30
+ person.projects_attributes.should be_nil
31
+ person.projects_attributes = [{ :name => 'write specs' }]
32
+ person.projects_attributes.should == [{ :name => 'write specs' }]
33
+ end
34
+
35
+ end
36
+
37
+ describe "every accessible many_to_many association with a valid reject_if proc", :shared => true do
38
+
39
+ it "should not allow to create a new project via Person#projects_attributes" do
40
+ Person.all.size.should == 0
41
+ Project.all.size.should == 0
42
+ ProjectMembership.all.size.should == 0
43
+
44
+ person = Person.create :name => 'snusnu'
45
+
46
+ Person.all.size.should == 1
47
+ ProjectMembership.all.size.should == 0
48
+ Project.all.size.should == 0
49
+
50
+ person.projects_attributes = [{ :name => 'dm-accepts_nested_attributes' }]
51
+ person.save
52
+
53
+ Person.all.size.should == 1
54
+ ProjectMembership.all.size.should == 0
55
+ Project.all.size.should == 0
56
+ end
57
+
58
+ end
59
+
60
+ describe "every accessible many_to_many association with no reject_if proc", :shared => true do
61
+
62
+ it "should allow to create a new project via Person#projects_attributes" do
63
+ Person.all.size.should == 0
64
+ Project.all.size.should == 0
65
+ ProjectMembership.all.size.should == 0
66
+
67
+ person = Person.create :name => 'snusnu'
68
+
69
+ Person.all.size.should == 1
70
+ ProjectMembership.all.size.should == 0
71
+ Project.all.size.should == 0
72
+
73
+ person.projects_attributes = [{ :name => 'dm-accepts_nested_attributes' }]
74
+
75
+ Person.all.size.should == 1
76
+ ProjectMembership.all.size.should == 0
77
+ Project.all.size.should == 0
78
+
79
+ person.save
80
+
81
+ Person.all.size.should == 1
82
+ ProjectMembership.all.size.should == 1
83
+ Project.all.size.should == 1
84
+
85
+ Project.first.name.should == 'dm-accepts_nested_attributes'
86
+ end
87
+
88
+ end
89
+
90
+ describe "every accessible many_to_many association with :allow_destroy => false", :shared => true do
91
+
92
+ it "should not allow to delete an existing project via Person#projects_attributes" do
93
+ person = Person.create :name => 'snusnu'
94
+
95
+ project = Project.create(:name => 'dm-accepts_nested_attributes')
96
+ project_membership = ProjectMembership.create(:person => person, :project => project)
97
+
98
+ Person.all.size.should == 1
99
+ ProjectMembership.all.size.should == 1
100
+ Project.all.size.should == 1
101
+
102
+ person.projects_attributes = [{ :id => project.id, :_delete => true }]
103
+
104
+ Person.all.size.should == 1
105
+ ProjectMembership.all.size.should == 1
106
+ Project.all.size.should == 1
107
+
108
+ person.save
109
+
110
+ Person.all.size.should == 1
111
+ ProjectMembership.all.size.should == 1
112
+ Project.all.size.should == 1
113
+ end
114
+
115
+ end
116
+
117
+ describe "every accessible many_to_many association with :allow_destroy => true", :shared => true do
118
+
119
+ it "should allow to delete an existing project via Person#projects_attributes" do
120
+ pending_if "#{DataMapper::Spec.adapter_name} doesn't support M2M", !HAS_M2M_SUPPORT do
121
+ person = Person.create :name => 'snusnu'
122
+
123
+ project_1 = Project.create(:name => 'dm-accepts_nested_attributes')
124
+ project_2 = Project.create(:name => 'dm-is-localizable')
125
+ project_membership_1 = ProjectMembership.create(:person => person, :project => project_1)
126
+ project_membership_2 = ProjectMembership.create(:person => person, :project => project_2)
127
+
128
+ Person.all.size.should == 1
129
+ ProjectMembership.all.size.should == 2
130
+ Project.all.size.should == 2
131
+
132
+ person.projects_attributes = [{ :id => project_1.id, :_delete => true }]
133
+
134
+ Person.all.size.should == 1
135
+ ProjectMembership.all.size.should == 2
136
+ Project.all.size.should == 2
137
+
138
+ person.save
139
+
140
+ Person.all.size.should == 1
141
+ ProjectMembership.all.size.should == 1
142
+ Project.all.size.should == 1
143
+ end
144
+ end
145
+
146
+ end