reform 2.3.3 → 2.5.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +0 -3
- data/CHANGES.md +9 -0
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +5 -5
- data/Rakefile +1 -12
- data/lib/reform/contract/validate.rb +1 -1
- data/lib/reform/form/dry.rb +47 -9
- data/lib/reform/validation/groups.rb +0 -1
- data/lib/reform/version.rb +1 -1
- data/test/call_test.rb +23 -0
- data/test/changed_test.rb +6 -6
- data/test/coercion_test.rb +17 -17
- data/test/{composition_new_api.rb → composition_test.rb} +27 -28
- data/test/{contract_new_api.rb → contract_test.rb} +8 -8
- data/test/default_test.rb +2 -2
- data/test/deserialize_test.rb +8 -8
- data/test/docs/validation_test.rb +134 -0
- data/test/{errors_new_api.rb → errors_test.rb} +41 -41
- data/test/feature_test.rb +2 -2
- data/test/fixtures/dry_error_messages.yml +64 -54
- data/test/{form_option_new_api.rb → form_option_test.rb} +1 -1
- data/test/{form_new_api.rb → form_test.rb} +3 -3
- data/test/from_test.rb +10 -10
- data/test/{inherit_new_api.rb → inherit_test.rb} +17 -17
- data/test/{module_new_api.rb → module_test.rb} +10 -10
- data/test/parse_option_test.rb +7 -7
- data/test/parse_pipeline_test.rb +1 -1
- data/test/{populate_new_api.rb → populate_test.rb} +112 -53
- data/test/populator_skip_test.rb +2 -2
- data/test/prepopulator_test.rb +15 -15
- data/test/read_only_test.rb +2 -2
- data/test/readable_test.rb +3 -3
- data/test/{reform_new_api.rb → reform_test.rb} +19 -19
- data/test/{save_new_api.rb → save_test.rb} +4 -4
- data/test/setup_test.rb +9 -9
- data/test/{skip_if_new_api.rb → skip_if_test.rb} +12 -12
- data/test/skip_setter_and_getter_test.rb +6 -6
- data/test/test_helper.rb +5 -6
- data/test/{validate_new_api.rb → validate_test.rb} +65 -78
- data/test/validation/{dry_validation_new_api.rb → dry_validation_test.rb} +124 -123
- data/test/validation/result_test.rb +14 -14
- data/test/virtual_test.rb +7 -7
- data/test/writeable_test.rb +8 -8
- metadata +35 -68
- data/Appraisals +0 -8
- data/gemfiles/0.13.0.gemfile +0 -8
- data/gemfiles/1.5.0.gemfile +0 -9
- data/lib/reform/form/dry/new_api.rb +0 -45
- data/lib/reform/form/dry/old_api.rb +0 -61
- data/test/call_new_api.rb +0 -23
- data/test/call_old_api.rb +0 -23
- data/test/composition_old_api.rb +0 -184
- data/test/contract_old_api.rb +0 -77
- data/test/errors_old_api.rb +0 -230
- data/test/fixtures/dry_new_api_error_messages.yml +0 -104
- data/test/form_old_api.rb +0 -57
- data/test/form_option_old_api.rb +0 -24
- data/test/inherit_old_api.rb +0 -105
- data/test/module_old_api.rb +0 -146
- data/test/populate_old_api.rb +0 -304
- data/test/reform_old_api.rb +0 -202
- data/test/save_old_api.rb +0 -101
- data/test/skip_if_old_api.rb +0 -92
- data/test/validate_old_api.rb +0 -410
- data/test/validation/dry_validation_old_api.rb +0 -772
@@ -17,7 +17,7 @@ class FormOptionTest < MiniTest::Spec
|
|
17
17
|
|
18
18
|
it do
|
19
19
|
form = AlbumForm.new(Album.new(Song.new("When It Comes To You")))
|
20
|
-
|
20
|
+
assert_equal "When It Comes To You", form.song.title
|
21
21
|
|
22
22
|
form.validate(song: {title: "Run For Cover"})
|
23
23
|
end
|
@@ -25,8 +25,8 @@ class FormTest < MiniTest::Spec
|
|
25
25
|
let(:cloned) { AlbumForm.clone }
|
26
26
|
|
27
27
|
# #dup is called in Op.inheritable_attr(:contract_class), it must be subclass of the original one.
|
28
|
-
it {
|
29
|
-
it {
|
28
|
+
it { refute_equal cloned, AlbumForm }
|
29
|
+
it { refute_equal AlbumForm.definitions, cloned.definitions }
|
30
30
|
|
31
31
|
it do
|
32
32
|
# currently, forms need a name for validation, even without AM.
|
@@ -51,7 +51,7 @@ class FormTest < MiniTest::Spec
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it "allows injecting :virtual options" do
|
54
|
-
|
54
|
+
assert_equal ArtistForm.new(Artist.new, current_user: Object).current_user, Object
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
data/test/from_test.rb
CHANGED
@@ -31,19 +31,19 @@ class AsTest < BaseTest
|
|
31
31
|
|
32
32
|
subject { AlbumForm.new(Album.new("Best Of", hit, [Song.new("Fallout"), song2])) }
|
33
33
|
|
34
|
-
it {
|
35
|
-
it {
|
36
|
-
it {
|
37
|
-
it {
|
34
|
+
it { assert_equal subject.name, "Best Of" }
|
35
|
+
it { assert_equal subject.single.title, "Roxanne" }
|
36
|
+
it { assert_equal subject.tracks[0].name, "Fallout" }
|
37
|
+
it { assert_equal subject.tracks[1].name, "Roxanne" }
|
38
38
|
|
39
39
|
describe "#validate" do
|
40
40
|
|
41
41
|
before { subject.validate(params) }
|
42
42
|
|
43
|
-
it {
|
44
|
-
it {
|
45
|
-
it {
|
46
|
-
it {
|
43
|
+
it { assert_equal subject.name, "Best Of The Police" }
|
44
|
+
it { assert_equal subject.single.title, "So Lonely" }
|
45
|
+
it { assert_equal subject.tracks[0].name, "Message In A Bottle" }
|
46
|
+
it { assert_equal subject.tracks[1].name, "Roxanne" }
|
47
47
|
end
|
48
48
|
|
49
49
|
describe "#sync" do
|
@@ -52,7 +52,7 @@ class AsTest < BaseTest
|
|
52
52
|
subject.sync
|
53
53
|
end
|
54
54
|
|
55
|
-
it {
|
55
|
+
it { assert_equal song2.title, "Livin' Ain't No Crime" }
|
56
56
|
end
|
57
57
|
|
58
58
|
describe "#save (nested hash)" do
|
@@ -65,7 +65,7 @@ class AsTest < BaseTest
|
|
65
65
|
hash = nested_hash
|
66
66
|
end
|
67
67
|
|
68
|
-
|
68
|
+
assert_equal hash, "title" => "Best Of The Police", "hit" => {"title" => "So Lonely"}, "songs" => [{"title" => "Message In A Bottle"}, {"title" => "Roxanne"}], "band" => nil
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -52,46 +52,46 @@ class InheritTest < BaseTest
|
|
52
52
|
|
53
53
|
it do
|
54
54
|
subject.validate("hit" => {"title" => "LA Drone", "rating" => 10})
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
assert_equal subject.hit.title, "LA Drone"
|
56
|
+
assert_equal subject.hit.rating, 10
|
57
|
+
assert_equal subject.errors.messages, {}
|
58
58
|
end
|
59
59
|
|
60
60
|
it do
|
61
61
|
subject.validate({})
|
62
62
|
assert_nil subject.model.hit.title
|
63
63
|
assert_nil subject.model.hit.rating
|
64
|
-
|
64
|
+
assert_equal subject.errors.messages, "hit.title": ["must be filled"], "hit.rating": ["must be filled"]
|
65
65
|
end
|
66
66
|
|
67
67
|
it "xxx" do
|
68
68
|
# sub hashes like :deserializer must be properly cloned when inheriting.
|
69
|
-
|
69
|
+
refute_equal AlbumForm.options_for(:title)[:deserializer].object_id, CompilationForm.options_for(:title)[:deserializer].object_id
|
70
70
|
|
71
71
|
# don't overwrite direct deserializer: {} configuration.
|
72
|
-
|
73
|
-
|
72
|
+
assert AlbumForm.options_for(:title)[:internal_populator].is_a? Reform::Form::Populator::Sync
|
73
|
+
assert_equal AlbumForm.options_for(:title)[:deserializer][:skip_parse], "skip_if in AlbumForm"
|
74
74
|
|
75
75
|
# AlbumForm.options_for(:hit)[:internal_populator].inspect.must_match /Reform::Form::Populator:.+ @user_proc="Populator"/
|
76
76
|
# AlbumForm.options_for(:hit)[:deserializer][:instance].inspect.must_be_instance_with Reform::Form::Populator, user_proc: "Populator"
|
77
77
|
|
78
|
-
|
79
|
-
|
78
|
+
assert AlbumForm.options_for(:songs)[:internal_populator].is_a? Reform::Form::Populator::IfEmpty
|
79
|
+
assert AlbumForm.options_for(:songs)[:deserializer][:skip_parse].is_a? Reform::Form::Validate::Skip::AllBlank
|
80
80
|
|
81
|
-
|
81
|
+
assert AlbumForm.options_for(:band)[:internal_populator].is_a? Reform::Form::Populator::IfEmpty
|
82
82
|
|
83
|
-
|
83
|
+
assert_equal CompilationForm.options_for(:title)[:deserializer][:skip_parse], "skip_if from CompilationForm"
|
84
84
|
# pp CompilationForm.options_for(:songs)
|
85
|
-
|
85
|
+
assert CompilationForm.options_for(:songs)[:internal_populator].is_a? Reform::Form::Populator::IfEmpty
|
86
86
|
|
87
|
-
|
87
|
+
assert CompilationForm.options_for(:band)[:internal_populator].is_a? Reform::Form::Populator::IfEmpty
|
88
88
|
|
89
89
|
# completely overwrite inherited.
|
90
|
-
|
90
|
+
assert CompilationForm.options_for(:hit)[:deserializer][:skip_parse].is_a? SkipParse
|
91
91
|
|
92
92
|
# inherit: true with block will still inherit the original class.
|
93
|
-
|
94
|
-
|
93
|
+
assert_equal AlbumForm.new(OpenStruct.new(band: OpenStruct.new)).band.band_id, 1
|
94
|
+
assert_equal CompilationForm.new(OpenStruct.new(band: OpenStruct.new)).band.band_id, 1
|
95
95
|
end
|
96
96
|
|
97
97
|
class CDForm < AlbumForm
|
@@ -101,5 +101,5 @@ class InheritTest < BaseTest
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
it {
|
104
|
+
it { assert_equal CDForm.options_for(:band)[:internal_populator].instance_variable_get(:@user_proc), "CD Populator" }
|
105
105
|
end
|
@@ -25,8 +25,8 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
25
25
|
params { required(:band).filled }
|
26
26
|
end
|
27
27
|
|
28
|
-
include Dry
|
29
|
-
property :cool, type:
|
28
|
+
include Dry.Types(default: :nominal) # allows using Types::* in module.
|
29
|
+
property :cool, type: Types::Params::Bool # test coercion.
|
30
30
|
end
|
31
31
|
|
32
32
|
# TODO: test if works, move stuff into inherit_schema!
|
@@ -60,24 +60,24 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
60
60
|
let(:song) { OpenStruct.new(band: OpenStruct.new(title: "Time Again")) }
|
61
61
|
|
62
62
|
# nested form from module is present and creates accessor.
|
63
|
-
it {
|
63
|
+
it { assert_equal SongForm.new(song).band.title, "Time Again" }
|
64
64
|
|
65
65
|
# methods from module get included.
|
66
|
-
it {
|
67
|
-
it {
|
66
|
+
it { assert_equal SongForm.new(song).id, 1 }
|
67
|
+
it { assert_equal SongForm.new(song).band.id, 2 }
|
68
68
|
|
69
69
|
# validators get inherited.
|
70
70
|
it do
|
71
71
|
form = SongForm.new(OpenStruct.new)
|
72
72
|
form.validate({})
|
73
|
-
|
73
|
+
assert_equal form.errors.messages, band: ["must be filled"]
|
74
74
|
end
|
75
75
|
|
76
76
|
# coercion works
|
77
77
|
it do
|
78
78
|
form = SongForm.new(OpenStruct.new)
|
79
79
|
form.validate(cool: "1")
|
80
|
-
|
80
|
+
assert form.cool
|
81
81
|
end
|
82
82
|
|
83
83
|
# include a module into a module into a class :)
|
@@ -106,7 +106,7 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
106
106
|
it do
|
107
107
|
form = AlbumForm.new(OpenStruct.new(band: OpenStruct.new))
|
108
108
|
form.validate("band" => {})
|
109
|
-
|
109
|
+
assert_equal form.errors.messages, "band.title": ["must be filled"], "band.label": ["must be filled"], name: ["must be filled"]
|
110
110
|
end
|
111
111
|
|
112
112
|
describe "module with custom accessors" do
|
@@ -130,8 +130,8 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
130
130
|
let(:song) { OpenStruct.new(id: 1, title: "Instant Mash") }
|
131
131
|
|
132
132
|
it do
|
133
|
-
|
134
|
-
|
133
|
+
assert_equal IncludingSongForm.new(song).id, 1
|
134
|
+
assert_equal IncludingSongForm.new(song).title, "INSTANT MASH"
|
135
135
|
end
|
136
136
|
end
|
137
137
|
end
|
data/test/parse_option_test.rb
CHANGED
@@ -13,13 +13,13 @@ class ParseOptionTest < MiniTest::Spec
|
|
13
13
|
let(:form) { CommentForm.new(Comment.new, user: current_user) }
|
14
14
|
|
15
15
|
it do
|
16
|
-
|
16
|
+
assert_equal form.user, current_user
|
17
17
|
|
18
18
|
lorem = "Lorem ipsum dolor sit amet..."
|
19
19
|
form.validate("content" => lorem, "user" => "not the current user")
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
assert_equal form.content, lorem
|
22
|
+
assert_equal form.user, current_user
|
23
23
|
end
|
24
24
|
|
25
25
|
describe "using ':parse' option doesn't override other ':deserialize' options" do
|
@@ -30,11 +30,11 @@ class ParseOptionTest < MiniTest::Spec
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it do
|
33
|
-
|
34
|
-
|
33
|
+
assert_equal ArticleCommentForm.definitions.get(:user)[:deserializer][:writeable], false
|
34
|
+
assert_equal ArticleCommentForm.definitions.get(:user)[:deserializer][:instance], "Instance"
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
assert ArticleCommentForm.definitions.get(:article)[:deserializer][:writeable]
|
37
|
+
assert_equal ArticleCommentForm.definitions.get(:article)[:deserializer][:instance], "Instance"
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
data/test/parse_pipeline_test.rb
CHANGED
@@ -10,6 +10,6 @@ class ParsePipelineTest < MiniTest::Spec
|
|
10
10
|
it "allows passing :parse_pipeline directly" do
|
11
11
|
form = AlbumForm.new(Album.new)
|
12
12
|
form.validate("name" => "Greatest Hits")
|
13
|
-
|
13
|
+
assert_equal form.name, "{\"name\"=>\"Greatest Hits\"}"
|
14
14
|
end
|
15
15
|
end
|
@@ -48,7 +48,7 @@ class PopulatorTest < MiniTest::Spec
|
|
48
48
|
"name" => "override me!"
|
49
49
|
)
|
50
50
|
|
51
|
-
|
51
|
+
assert_equal form.name, "!em edirrevo"
|
52
52
|
end
|
53
53
|
|
54
54
|
# changing existing property :artist.
|
@@ -60,7 +60,7 @@ class PopulatorTest < MiniTest::Spec
|
|
60
60
|
"artist" => {"name" => "Marcus Miller"}
|
61
61
|
)
|
62
62
|
|
63
|
-
|
63
|
+
assert_equal form.artist.model.object_id, old_id
|
64
64
|
end
|
65
65
|
|
66
66
|
# use populator for default value on scalars?
|
@@ -68,36 +68,36 @@ class PopulatorTest < MiniTest::Spec
|
|
68
68
|
# adding to collection via :populator.
|
69
69
|
# valid.
|
70
70
|
it "yyy" do
|
71
|
-
|
71
|
+
assert form.validate(
|
72
72
|
"songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"},
|
73
73
|
{"title" => "Rime Of The Ancient Mariner"}, # new song.
|
74
74
|
{"title" => "Re-Education", "composer" => {"name" => "Rise Against"}}], # new song with new composer.
|
75
|
-
)
|
75
|
+
)
|
76
76
|
|
77
|
-
|
77
|
+
assert_equal form.errors.messages.inspect, "{}"
|
78
78
|
|
79
79
|
# form has updated.
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
assert_equal form.name, "The Dissent Of Man"
|
81
|
+
assert_equal form.songs[0].title, "Fallout"
|
82
|
+
assert_equal form.songs[1].title, "Roxanne"
|
83
|
+
assert_equal form.songs[1].composer.name, "Greg Graffin"
|
84
84
|
|
85
|
-
|
85
|
+
form.songs[1].composer.model.is_a? Artist
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
assert_equal form.songs[1].title, "Roxanne"
|
88
|
+
assert_equal form.songs[2].title, "Rime Of The Ancient Mariner" # new song added.
|
89
|
+
assert_equal form.songs[3].title, "Re-Education"
|
90
|
+
assert_equal form.songs[3].composer.name, "Rise Against"
|
91
|
+
assert_equal form.songs.size, 4
|
92
|
+
assert_equal form.artist.name, "Bad Religion"
|
93
93
|
|
94
94
|
# model has not changed, yet.
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
95
|
+
assert_equal album.name, "The Dissent Of Man"
|
96
|
+
assert_equal album.songs[0].title, "Broken"
|
97
|
+
assert_equal album.songs[1].title, "Resist Stance"
|
98
|
+
assert_equal album.songs[1].composer.name, "Greg Graffin"
|
99
|
+
assert_equal album.songs.size, 2
|
100
|
+
assert_equal album.artist.name, "Bad Religion"
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
@@ -117,7 +117,7 @@ class PopulateWithMethodTest < Minitest::Spec
|
|
117
117
|
it "runs populator method" do
|
118
118
|
form.validate("title" => "override me!")
|
119
119
|
|
120
|
-
|
120
|
+
assert_equal form.title, "!em edirrevo"
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -141,7 +141,7 @@ class PopulateWithCallableTest < Minitest::Spec
|
|
141
141
|
it "runs populator method" do
|
142
142
|
form.validate("title" => "override me!")
|
143
143
|
|
144
|
-
|
144
|
+
assert_equal form.title, "!em edirrevo"
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
@@ -161,7 +161,7 @@ class PopulateWithProcTest < Minitest::Spec
|
|
161
161
|
it "runs populator method" do
|
162
162
|
form.validate("title" => "override me!")
|
163
163
|
|
164
|
-
|
164
|
+
assert_equal form.title, "!em edirrevo"
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
@@ -216,35 +216,35 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
216
216
|
let(:form) { AlbumForm.new(album) }
|
217
217
|
|
218
218
|
it do
|
219
|
-
|
219
|
+
assert_equal form.songs.size, 2
|
220
220
|
|
221
|
-
|
221
|
+
assert form.validate(
|
222
222
|
"songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"},
|
223
223
|
{"title" => "Rime Of The Ancient Mariner"}, # new song.
|
224
224
|
{"title" => "Re-Education", "composer" => {"name" => "Rise Against"}}], # new song with new composer.
|
225
|
-
)
|
225
|
+
)
|
226
226
|
|
227
|
-
|
227
|
+
assert_equal form.errors.messages.inspect, "{}"
|
228
228
|
|
229
229
|
# form has updated.
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
230
|
+
assert_equal form.name, "The Dissent Of Man"
|
231
|
+
assert_equal form.songs[0].title, "Fallout"
|
232
|
+
assert_equal form.songs[1].title, "Roxanne"
|
233
|
+
assert_equal form.songs[1].composer.name, "Greg Graffin"
|
234
|
+
assert_equal form.songs[1].title, "Roxanne"
|
235
|
+
assert_equal form.songs[2].title, "Rime Of The Ancient Mariner" # new song added.
|
236
|
+
assert_equal form.songs[3].title, "Re-Education"
|
237
|
+
assert_equal form.songs[3].composer.name, "Rise Against"
|
238
|
+
assert_equal form.songs.size, 4
|
239
|
+
assert_equal form.artist.name, "Bad Religion"
|
240
240
|
|
241
241
|
# model has not changed, yet.
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
242
|
+
assert_equal album.name, "The Dissent Of Man"
|
243
|
+
assert_equal album.songs[0].title, "Broken"
|
244
|
+
assert_equal album.songs[1].title, "Resist Stance"
|
245
|
+
assert_equal album.songs[1].composer.name, "Greg Graffin"
|
246
|
+
assert_equal album.songs.size, 2
|
247
|
+
assert_equal album.artist.name, "Bad Religion"
|
248
248
|
end
|
249
249
|
|
250
250
|
# trigger artist populator. lambda calling form instance method.
|
@@ -252,11 +252,11 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
252
252
|
form = AlbumForm.new(album = Album.new)
|
253
253
|
form.validate("artist" => {"name" => "From Autumn To Ashes"})
|
254
254
|
|
255
|
-
|
255
|
+
assert_equal form.artist.name, "From Autumn To Ashes"
|
256
256
|
# test lambda was executed in form context.
|
257
|
-
|
257
|
+
assert form.artist.model.is_a? AlbumForm::Sting
|
258
258
|
# test lambda block arguments.
|
259
|
-
|
259
|
+
assert_equal form.artist.model.args.to_s, "[{\"name\"=>\"From Autumn To Ashes\"}, nil]"
|
260
260
|
|
261
261
|
assert_nil album.artist
|
262
262
|
end
|
@@ -292,13 +292,72 @@ class PopulateIfEmptyWithDeletionTest < MiniTest::Spec
|
|
292
292
|
let(:form) { AlbumForm.new(album) }
|
293
293
|
|
294
294
|
it do
|
295
|
-
|
295
|
+
assert form.validate(
|
296
296
|
"songs" => [{"title" => "Broken, delete me!"}, {"title" => "Roxanne"}]
|
297
|
-
)
|
297
|
+
)
|
298
|
+
|
299
|
+
assert_equal form.errors.messages.inspect, "{}"
|
300
|
+
|
301
|
+
assert_equal form.songs.size, 1
|
302
|
+
assert_equal form.songs[0].title, "Roxanne"
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
class PopulateWithFormKeyTest < MiniTest::Spec
|
307
|
+
Song = Struct.new(:title, :album, :composer)
|
308
|
+
Album = Struct.new(:name, :songs, :artist)
|
309
|
+
|
310
|
+
let(:song) { Song.new('Broken') }
|
311
|
+
let(:song2) { Song.new('Resist Stance') }
|
312
|
+
let(:album) { Album.new('The Dissent Of Man', [song, song2]) }
|
313
|
+
|
314
|
+
class SongForm < TestForm
|
315
|
+
property :title
|
316
|
+
|
317
|
+
validation do
|
318
|
+
params { required(:title).filled }
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
class AlbumForm < TestForm
|
323
|
+
property :name
|
298
324
|
|
299
|
-
|
325
|
+
collection :songs, form: SongForm, populator: :populator!, model_identifier: :title
|
326
|
+
|
327
|
+
def populator!(fragment:, **)
|
328
|
+
item = songs.find { |song| song.title == fragment['title'] }
|
329
|
+
if item && fragment['delete'] == '1'
|
330
|
+
songs.delete(item)
|
331
|
+
return skip!
|
332
|
+
end
|
333
|
+
item || songs.append(Song.new)
|
334
|
+
end
|
335
|
+
end
|
300
336
|
|
301
|
-
|
302
|
-
|
337
|
+
let(:form) { AlbumForm.new(album) }
|
338
|
+
|
339
|
+
it do
|
340
|
+
assert_equal 2, form.songs.size
|
341
|
+
|
342
|
+
assert form.validate(
|
343
|
+
'songs' => [
|
344
|
+
{ 'title' => 'Broken' },
|
345
|
+
{ 'title' => 'Resist Stance' },
|
346
|
+
{ 'title' => 'Rime Of The Ancient Mariner' }
|
347
|
+
]
|
348
|
+
)
|
349
|
+
|
350
|
+
assert_equal 3, form.songs.size
|
351
|
+
|
352
|
+
assert form.validate(
|
353
|
+
'songs' => [
|
354
|
+
{ 'title' => 'Broken', 'delete' => '1' },
|
355
|
+
{ 'title' => 'Resist Stance' },
|
356
|
+
{ 'title' => 'Rime Of The Ancient Mariner' }
|
357
|
+
]
|
358
|
+
)
|
359
|
+
assert_equal 2, form.songs.size
|
360
|
+
assert_equal 'Resist Stance', form.songs.first.title
|
361
|
+
assert_equal 'Rime Of The Ancient Mariner', form.songs.last.title
|
303
362
|
end
|
304
363
|
end
|