reform 2.3.3 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +0 -3
  4. data/CHANGES.md +9 -0
  5. data/Gemfile +1 -1
  6. data/LICENSE.txt +1 -1
  7. data/README.md +5 -5
  8. data/Rakefile +1 -12
  9. data/lib/reform/contract/validate.rb +1 -1
  10. data/lib/reform/form/dry.rb +47 -9
  11. data/lib/reform/validation/groups.rb +0 -1
  12. data/lib/reform/version.rb +1 -1
  13. data/test/call_test.rb +23 -0
  14. data/test/changed_test.rb +6 -6
  15. data/test/coercion_test.rb +17 -17
  16. data/test/{composition_new_api.rb → composition_test.rb} +27 -28
  17. data/test/{contract_new_api.rb → contract_test.rb} +8 -8
  18. data/test/default_test.rb +2 -2
  19. data/test/deserialize_test.rb +8 -8
  20. data/test/docs/validation_test.rb +134 -0
  21. data/test/{errors_new_api.rb → errors_test.rb} +41 -41
  22. data/test/feature_test.rb +2 -2
  23. data/test/fixtures/dry_error_messages.yml +64 -54
  24. data/test/{form_option_new_api.rb → form_option_test.rb} +1 -1
  25. data/test/{form_new_api.rb → form_test.rb} +3 -3
  26. data/test/from_test.rb +10 -10
  27. data/test/{inherit_new_api.rb → inherit_test.rb} +17 -17
  28. data/test/{module_new_api.rb → module_test.rb} +10 -10
  29. data/test/parse_option_test.rb +7 -7
  30. data/test/parse_pipeline_test.rb +1 -1
  31. data/test/{populate_new_api.rb → populate_test.rb} +112 -53
  32. data/test/populator_skip_test.rb +2 -2
  33. data/test/prepopulator_test.rb +15 -15
  34. data/test/read_only_test.rb +2 -2
  35. data/test/readable_test.rb +3 -3
  36. data/test/{reform_new_api.rb → reform_test.rb} +19 -19
  37. data/test/{save_new_api.rb → save_test.rb} +4 -4
  38. data/test/setup_test.rb +9 -9
  39. data/test/{skip_if_new_api.rb → skip_if_test.rb} +12 -12
  40. data/test/skip_setter_and_getter_test.rb +6 -6
  41. data/test/test_helper.rb +5 -6
  42. data/test/{validate_new_api.rb → validate_test.rb} +65 -78
  43. data/test/validation/{dry_validation_new_api.rb → dry_validation_test.rb} +124 -123
  44. data/test/validation/result_test.rb +14 -14
  45. data/test/virtual_test.rb +7 -7
  46. data/test/writeable_test.rb +8 -8
  47. metadata +35 -68
  48. data/Appraisals +0 -8
  49. data/gemfiles/0.13.0.gemfile +0 -8
  50. data/gemfiles/1.5.0.gemfile +0 -9
  51. data/lib/reform/form/dry/new_api.rb +0 -45
  52. data/lib/reform/form/dry/old_api.rb +0 -61
  53. data/test/call_new_api.rb +0 -23
  54. data/test/call_old_api.rb +0 -23
  55. data/test/composition_old_api.rb +0 -184
  56. data/test/contract_old_api.rb +0 -77
  57. data/test/errors_old_api.rb +0 -230
  58. data/test/fixtures/dry_new_api_error_messages.yml +0 -104
  59. data/test/form_old_api.rb +0 -57
  60. data/test/form_option_old_api.rb +0 -24
  61. data/test/inherit_old_api.rb +0 -105
  62. data/test/module_old_api.rb +0 -146
  63. data/test/populate_old_api.rb +0 -304
  64. data/test/reform_old_api.rb +0 -202
  65. data/test/save_old_api.rb +0 -101
  66. data/test/skip_if_old_api.rb +0 -92
  67. data/test/validate_old_api.rb +0 -410
  68. data/test/validation/dry_validation_old_api.rb +0 -772
@@ -1,202 +0,0 @@
1
- require "test_helper"
2
-
3
- class ReformTest < Minitest::Spec
4
- let(:comp) { OpenStruct.new(name: "Duran Duran", title: "Rio") }
5
-
6
- let(:form) { SongForm.new(comp) }
7
-
8
- class SongForm < TestForm
9
- property :name
10
- property :title
11
-
12
- validation do
13
- required(:name).filled
14
- end
15
- end
16
-
17
- describe "(new) form with empty models" do
18
- let(:comp) { OpenStruct.new }
19
-
20
- it "returns empty fields" do
21
- assert_nil form.title
22
- _(form.name).must_be_nil
23
- end
24
-
25
- describe "and submitted values" do
26
- it "returns filled-out fields" do
27
- form.validate("name" => "Duran Duran")
28
-
29
- assert_nil form.title
30
- _(form.name).must_equal "Duran Duran"
31
- end
32
- end
33
- end
34
-
35
- describe "(edit) form with existing models" do
36
- it "returns filled-out fields" do
37
- _(form.name).must_equal "Duran Duran"
38
- _(form.title).must_equal "Rio"
39
- end
40
- end
41
-
42
- describe "#validate" do
43
- let(:comp) { OpenStruct.new }
44
-
45
- it "ignores unmapped fields in input" do
46
- form.validate("name" => "Duran Duran", :genre => "80s")
47
- assert_raises NoMethodError do
48
- form.genre
49
- end
50
- end
51
-
52
- it "returns true when valid" do
53
- _(form.validate("name" => "Duran Duran")).must_equal true
54
- end
55
-
56
- it "exposes input via property accessors" do
57
- form.validate("name" => "Duran Duran")
58
-
59
- _(form.name).must_equal "Duran Duran"
60
- end
61
-
62
- it "doesn't change model properties" do
63
- form.validate("name" => "Duran Duran")
64
-
65
- assert_nil comp.name # don't touch model, yet.
66
- end
67
-
68
- # TODO: test errors. test valid.
69
- describe "invalid input" do
70
- class ValidatingForm < TestForm
71
- property :name
72
- property :title
73
-
74
- validation do
75
- required(:name).filled
76
- required(:title).filled
77
- end
78
- end
79
- let(:form) { ValidatingForm.new(comp) }
80
-
81
- it "returns false when invalid" do
82
- _(form.validate({})).must_equal false
83
- end
84
-
85
- it "populates errors" do
86
- form.validate({})
87
- _(form.errors.messages).must_equal({name: ["must be filled"], title: ["must be filled"]})
88
- end
89
- end
90
- end
91
-
92
- describe "#save" do
93
- let(:comp) { OpenStruct.new }
94
- let(:form) { SongForm.new(comp) }
95
-
96
- before { form.validate("name" => "Diesel Boy") }
97
-
98
- it "xxpushes data to models" do
99
- form.save
100
-
101
- _(comp.name).must_equal "Diesel Boy"
102
- assert_nil comp.title
103
- end
104
-
105
- describe "#save with block" do
106
- it do
107
- hash = {}
108
-
109
- form.save do |map|
110
- hash = map
111
- end
112
-
113
- _(hash).must_equal({"name" => "Diesel Boy", "title" => nil})
114
- end
115
- end
116
- end
117
-
118
- describe "#model" do
119
- it { _(form.model).must_equal comp }
120
- end
121
-
122
- describe "inheritance" do
123
- class HitForm < SongForm
124
- property :position
125
- validation do
126
- required(:position).filled
127
- end
128
- end
129
-
130
- let(:form) { HitForm.new(OpenStruct.new()) }
131
- it do
132
- form.validate({"title" => "The Body"})
133
- _(form.title).must_equal "The Body"
134
- assert_nil form.position
135
- _(form.errors.messages).must_equal({name: ["must be filled"], position: ["must be filled"]})
136
- end
137
- end
138
- end
139
-
140
- class OverridingAccessorsTest < BaseTest
141
- class SongForm < TestForm
142
- property :title
143
-
144
- def title=(v) # used in #validate.
145
- super v * 2
146
- end
147
-
148
- def title # used in #sync.
149
- super.downcase
150
- end
151
- end
152
-
153
- let(:song) { Song.new("Pray") }
154
- subject { SongForm.new(song) }
155
-
156
- # override reader for presentation.
157
- it { _(subject.title).must_equal "pray" }
158
-
159
- describe "#save" do
160
- before { subject.validate("title" => "Hey Little World") }
161
-
162
- # reader always used
163
- it { _(subject.title).must_equal "hey little worldhey little world" }
164
-
165
- # the reader is not used when saving/syncing.
166
- it do
167
- subject.save do |hash|
168
- _(hash["title"]).must_equal "Hey Little WorldHey Little World"
169
- end
170
- end
171
-
172
- # no reader or writer used when saving/syncing.
173
- it do
174
- song.extend(Saveable)
175
- subject.save
176
- _(song.title).must_equal "Hey Little WorldHey Little World"
177
- end
178
- end
179
- end
180
-
181
- class MethodInFormTest < MiniTest::Spec
182
- class AlbumForm < TestForm
183
- property :title
184
-
185
- def title
186
- "The Suffer And The Witness"
187
- end
188
-
189
- property :hit do
190
- property :title
191
-
192
- def title
193
- "Drones"
194
- end
195
- end
196
- end
197
-
198
- # methods can be used instead of created accessors.
199
- subject { AlbumForm.new(OpenStruct.new(hit: OpenStruct.new)) }
200
- it { _(subject.title).must_equal "The Suffer And The Witness" }
201
- it { _(subject.hit.title).must_equal "Drones" }
202
- end
data/test/save_old_api.rb DELETED
@@ -1,101 +0,0 @@
1
- require "test_helper"
2
-
3
- class SaveTest < BaseTest
4
- Song = Struct.new(:title, :album, :composer)
5
- Album = Struct.new(:name, :songs, :artist)
6
- Artist = Struct.new(:name)
7
-
8
- class AlbumForm < TestForm
9
- property :name
10
- validation do
11
- required(:name).filled
12
- end
13
-
14
- collection :songs do
15
- property :title
16
- validation do
17
- required(:title).filled
18
- end
19
-
20
- property :composer do
21
- property :name
22
- validation do
23
- required(:name).filled
24
- end
25
- end
26
- end
27
-
28
- property :artist, save: false do
29
- property :name
30
- end
31
- end
32
-
33
- module Saveable
34
- def save
35
- @saved = true
36
- end
37
-
38
- def saved?
39
- defined?(@saved) && @saved
40
- end
41
- end
42
-
43
- let(:song) { Song.new("Broken").extend(Saveable) }
44
- # let(:song_with_composer) { Song.new("Resist Stance", nil, composer).extend(Saveable) }
45
- let(:composer) { Artist.new("Greg Graffin").extend(Saveable) }
46
- let(:artist) { Artist.new("Bad Religion").extend(Saveable).extend(Saveable) }
47
- let(:album) { Album.new("The Dissent Of Man", [song], artist).extend(Saveable) }
48
-
49
- let(:form) { AlbumForm.new(album) }
50
-
51
- it do
52
- form.validate("songs" => [{"title" => "Fixed"}])
53
-
54
- form.save
55
-
56
- _(album.saved?).must_equal true
57
- _(album.songs[0].title).must_equal "Fixed"
58
- _(album.songs[0].saved?).must_equal true
59
- assert_nil album.artist.saved?
60
- end
61
-
62
- describe "#sync with block" do
63
- it do
64
- form = AlbumForm.new(Album.new("Greatest Hits"))
65
-
66
- form.validate(name: nil) # nil-out the title.
67
-
68
- nested_hash = nil
69
- form.sync do |hash|
70
- nested_hash = hash
71
- end
72
-
73
- _(nested_hash).must_equal({"name" => nil, "artist" => nil})
74
- end
75
- end
76
- end
77
-
78
- # class SaveWithDynamicOptionsTest < MiniTest::Spec
79
- # Song = Struct.new(:id, :title, :length) do
80
- # include Saveable
81
- # end
82
-
83
- # class SongForm < TestForm
84
- # property :title#, save: false
85
- # property :length, virtual: true
86
- # end
87
-
88
- # let(:song) { Song.new }
89
- # let(:form) { SongForm.new(song) }
90
-
91
- # # we have access to original input value and outside parameters.
92
- # it "xxx" do
93
- # form.validate("title" => "A Poor Man's Memory", "length" => 10)
94
- # length_seconds = 120
95
- # form.save(length: lambda { |value, options| form.model.id = "#{value}: #{length_seconds}" })
96
-
97
- # song.title.must_equal "A Poor Man's Memory"
98
- # assert_nil song.length
99
- # song.id.must_equal "10: 120"
100
- # end
101
- # end
@@ -1,92 +0,0 @@
1
- require "test_helper"
2
-
3
- class SkipIfTest < BaseTest
4
- let(:hit) { Song.new }
5
- let(:album) { Album.new(nil, hit, [], nil) }
6
-
7
- class AlbumForm < TestForm
8
- property :title
9
-
10
- property :hit, skip_if: ->(options) { options[:fragment]["title"] == "" } do
11
- property :title
12
- validation do
13
- required(:title).filled
14
- end
15
- end
16
-
17
- collection :songs, skip_if: :skip_song?, populate_if_empty: BaseTest::Song do
18
- property :title
19
- end
20
-
21
- def skip_song?(options)
22
- options[:fragment]["title"].nil?
23
- end
24
- end
25
-
26
- # deserializes when present.
27
- it do
28
- form = AlbumForm.new(album)
29
- _(form.validate("hit" => {"title" => "Altar Of Sacrifice"})).must_equal true
30
- _(form.hit.title).must_equal "Altar Of Sacrifice"
31
- end
32
-
33
- # skips deserialization when not present.
34
- it do
35
- form = AlbumForm.new(Album.new)
36
- _(form.validate("hit" => {"title" => ""})).must_equal true
37
- assert_nil form.hit # hit hasn't been deserialised.
38
- end
39
-
40
- # skips deserialization when not present.
41
- it do
42
- form = AlbumForm.new(Album.new(nil, nil, []))
43
- _(form.validate("songs" => [{"title" => "Waste Of Breath"}, {"title" => nil}])).must_equal true
44
- _(form.songs.size).must_equal 1
45
- _(form.songs[0].title).must_equal "Waste Of Breath"
46
- end
47
- end
48
-
49
- class SkipIfAllBlankTest < BaseTest
50
- # skip_if: :all_blank"
51
- class AlbumForm < TestForm
52
- collection :songs, skip_if: :all_blank, populate_if_empty: BaseTest::Song do
53
- property :title
54
- property :length
55
- end
56
- end
57
-
58
- # create only one object.
59
- it do
60
- form = AlbumForm.new(OpenStruct.new(songs: []))
61
- _(form.validate("songs" => [{"title" => "Apathy"}, {"title" => "", "length" => ""}])).must_equal true
62
- _(form.songs.size).must_equal 1
63
- _(form.songs[0].title).must_equal "Apathy"
64
- end
65
-
66
- it do
67
- form = AlbumForm.new(OpenStruct.new(songs: []))
68
- _(form.validate("songs" => [{"title" => "", "length" => ""}, {"title" => "Apathy"}])).must_equal true
69
- _(form.songs.size).must_equal 1
70
- _(form.songs[0].title).must_equal "Apathy"
71
- end
72
-
73
- it do
74
- form = AlbumForm.new(OpenStruct.new(songs: []))
75
- _(form.validate(:songs => [{:title=>"", :length => ""}, {:title=>"Apathy"}])).must_equal true
76
- _(form.songs.size).must_equal 1
77
- _(form.songs[0].title).must_equal "Apathy"
78
- end
79
- end
80
-
81
- class InvalidOptionsCombinationTest < BaseTest
82
- it do
83
- assert_raises(Reform::Form::InvalidOptionsCombinationError) do
84
- class AlbumForm < TestForm
85
- collection :songs, skip_if: :all_blank, populator: -> {} do
86
- property :title
87
- property :length
88
- end
89
- end
90
- end
91
- end
92
- end
@@ -1,410 +0,0 @@
1
- require "test_helper"
2
-
3
- class ContractValidateTest < MiniTest::Spec
4
- Song = Struct.new(:title, :album, :composer)
5
- Album = Struct.new(:name, :songs, :artist)
6
- Artist = Struct.new(:name)
7
-
8
- class AlbumForm < TestContract
9
- property :name
10
- validation do
11
- required(:name).filled
12
- end
13
-
14
- collection :songs do
15
- property :title
16
- validation do
17
- required(:title).filled
18
- end
19
-
20
- property :composer do
21
- validation do
22
- required(:name).filled
23
- end
24
- property :name
25
- end
26
- end
27
-
28
- property :artist do
29
- property :name
30
- end
31
- end
32
-
33
- let(:song) { Song.new("Broken") }
34
- let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
35
- let(:composer) { Artist.new("Greg Graffin") }
36
- let(:artist) { Artist.new("Bad Religion") }
37
- let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
38
-
39
- let(:form) { AlbumForm.new(album) }
40
-
41
- # valid
42
- it do
43
- _(form.validate).must_equal true
44
- _(form.errors.messages.inspect).must_equal "{}"
45
- end
46
-
47
- # invalid
48
- it do
49
- album.songs[1].composer.name = nil
50
- album.name = nil
51
-
52
- _(form.validate).must_equal false
53
- _(form.errors.messages.inspect).must_equal "{:name=>[\"must be filled\"], :\"songs.composer.name\"=>[\"must be filled\"]}"
54
- end
55
- end
56
-
57
- # no configuration results in "sync" (formerly known as parse_strategy: :sync).
58
- class ValidateWithoutConfigurationTest < MiniTest::Spec
59
- Song = Struct.new(:title, :album, :composer)
60
- Album = Struct.new(:name, :songs, :artist)
61
- Artist = Struct.new(:name)
62
-
63
- class AlbumForm < TestForm
64
- property :name
65
- validation do
66
- required(:name).filled
67
- end
68
-
69
- collection :songs do
70
- property :title
71
- validation do
72
- required(:title).filled
73
- end
74
-
75
- property :composer do
76
- property :name
77
- validation do
78
- required(:name).filled
79
- end
80
- end
81
- end
82
-
83
- property :artist do
84
- property :name
85
- end
86
- end
87
-
88
- let(:song) { Song.new("Broken") }
89
- let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
90
- let(:composer) { Artist.new("Greg Graffin") }
91
- let(:artist) { Artist.new("Bad Religion") }
92
- let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
93
-
94
- let(:form) { AlbumForm.new(album) }
95
-
96
- # valid.
97
- it do
98
- object_ids = {
99
- song: form.songs[0].object_id, song_with_composer: form.songs[1].object_id,
100
- artist: form.artist.object_id, composer: form.songs[1].composer.object_id
101
- }
102
-
103
- _(form.validate(
104
- "name" => "Best Of",
105
- "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne", "composer" => {"name" => "Sting"}}],
106
- "artist" => {"name" => "The Police"}
107
- )).must_equal true
108
-
109
- _(form.errors.messages.inspect).must_equal "{}"
110
-
111
- # form has updated.
112
- _(form.name).must_equal "Best Of"
113
- _(form.songs[0].title).must_equal "Fallout"
114
- _(form.songs[1].title).must_equal "Roxanne"
115
- _(form.songs[1].composer.name).must_equal "Sting"
116
- _(form.artist.name).must_equal "The Police"
117
-
118
- # objects are still the same.
119
- _(form.songs[0].object_id).must_equal object_ids[:song]
120
- _(form.songs[1].object_id).must_equal object_ids[:song_with_composer]
121
- _(form.songs[1].composer.object_id).must_equal object_ids[:composer]
122
- _(form.artist.object_id).must_equal object_ids[:artist]
123
-
124
- # model has not changed, yet.
125
- _(album.name).must_equal "The Dissent Of Man"
126
- _(album.songs[0].title).must_equal "Broken"
127
- _(album.songs[1].title).must_equal "Resist Stance"
128
- _(album.songs[1].composer.name).must_equal "Greg Graffin"
129
- _(album.artist.name).must_equal "Bad Religion"
130
- end
131
-
132
- # with symbols.
133
- it do
134
- _(form.validate(
135
- name: "Best Of",
136
- songs: [{title: "The X-Creep"}, {title: "Trudging", composer: {name: "SNFU"}}],
137
- artist: {name: "The Police"}
138
- )).must_equal true
139
-
140
- _(form.name).must_equal "Best Of"
141
- _(form.songs[0].title).must_equal "The X-Creep"
142
- _(form.songs[1].title).must_equal "Trudging"
143
- _(form.songs[1].composer.name).must_equal "SNFU"
144
- _(form.artist.name).must_equal "The Police"
145
- end
146
-
147
- # throws exception when no populators.
148
- it do
149
- album = Album.new("The Dissent Of Man", [])
150
-
151
- assert_raises RuntimeError do
152
- AlbumForm.new(album).validate(songs: {title: "Resist-Stance"})
153
- end
154
- end
155
- end
156
-
157
- class ValidateWithInternalPopulatorOptionTest < MiniTest::Spec
158
- Song = Struct.new(:title, :album, :composer)
159
- Album = Struct.new(:name, :songs, :artist)
160
- Artist = Struct.new(:name)
161
-
162
- class AlbumForm < TestForm
163
- property :name
164
- validation do
165
- required(:name).filled
166
- end
167
-
168
- collection :songs,
169
- internal_populator: ->(input, options) {
170
- collection = options[:represented].songs
171
- (item = collection[options[:index]]) ? item : collection.insert(options[:index], Song.new)
172
- } do
173
- property :title
174
- validation do
175
- required(:title).filled
176
- end
177
-
178
- property :composer, internal_populator: ->(input, options) { (item = options[:represented].composer) ? item : Artist.new } do
179
- property :name
180
- validation do
181
- required(:name).filled
182
- end
183
- end
184
- end
185
-
186
- property :artist, internal_populator: ->(input, options) { (item = options[:represented].artist) ? item : Artist.new } do
187
- property :name
188
- validation do
189
- required(:name).filled
190
- end
191
- end
192
- end
193
-
194
- let(:song) { Song.new("Broken") }
195
- let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
196
- let(:composer) { Artist.new("Greg Graffin") }
197
- let(:artist) { Artist.new("Bad Religion") }
198
- let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
199
-
200
- let(:form) { AlbumForm.new(album) }
201
-
202
- # valid.
203
- it("xxx") do
204
- _(form.validate(
205
- "name" => "Best Of",
206
- "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne", "composer" => {"name" => "Sting"}}],
207
- "artist" => {"name" => "The Police"},
208
- )).must_equal true
209
- _(form.valid?).must_equal true
210
-
211
- _(form.errors.messages.inspect).must_equal "{}"
212
-
213
- # form has updated.
214
- _(form.name).must_equal "Best Of"
215
- _(form.songs[0].title).must_equal "Fallout"
216
- _(form.songs[1].title).must_equal "Roxanne"
217
- _(form.songs[1].composer.name).must_equal "Sting"
218
- _(form.artist.name).must_equal "The Police"
219
-
220
- # model has not changed, yet.
221
- _(album.name).must_equal "The Dissent Of Man"
222
- _(album.songs[0].title).must_equal "Broken"
223
- _(album.songs[1].title).must_equal "Resist Stance"
224
- _(album.songs[1].composer.name).must_equal "Greg Graffin"
225
- _(album.artist.name).must_equal "Bad Religion"
226
- end
227
-
228
- # invalid.
229
- it do
230
- _(form.validate(
231
- "name" => "",
232
- "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne", "composer" => {"name" => ""}}],
233
- "artist" => {"name" => ""},
234
- )).must_equal false
235
- _(form.valid?).must_equal false
236
-
237
- _(form.errors.messages.inspect).must_equal "{:name=>[\"must be filled\"], :\"songs.composer.name\"=>[\"must be filled\"], :\"artist.name\"=>[\"must be filled\"]}"
238
- end
239
-
240
- # adding to collection via :instance.
241
- # valid.
242
- it do
243
- _(form.validate(
244
- "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"}, {"title" => "Rime Of The Ancient Mariner"}],
245
- )).must_equal true
246
-
247
- _(form.errors.messages.inspect).must_equal "{}"
248
-
249
- # form has updated.
250
- _(form.name).must_equal "The Dissent Of Man"
251
- _(form.songs[0].title).must_equal "Fallout"
252
- _(form.songs[1].title).must_equal "Roxanne"
253
- _(form.songs[1].composer.name).must_equal "Greg Graffin"
254
- _(form.songs[1].title).must_equal "Roxanne"
255
- _(form.songs[2].title).must_equal "Rime Of The Ancient Mariner" # new song added.
256
- _(form.songs.size).must_equal 3
257
- _(form.artist.name).must_equal "Bad Religion"
258
-
259
- # model has not changed, yet.
260
- _(album.name).must_equal "The Dissent Of Man"
261
- _(album.songs[0].title).must_equal "Broken"
262
- _(album.songs[1].title).must_equal "Resist Stance"
263
- _(album.songs[1].composer.name).must_equal "Greg Graffin"
264
- _(album.songs.size).must_equal 2
265
- _(album.artist.name).must_equal "Bad Religion"
266
- end
267
-
268
- # allow writeable: false even in the deserializer.
269
- class SongForm < TestForm
270
- property :title, deserializer: {writeable: false}
271
- end
272
-
273
- it do
274
- form = SongForm.new(song = Song.new)
275
- form.validate("title" => "Ignore me!")
276
- assert_nil form.title
277
- form.title = "Unopened"
278
- form.sync # only the deserializer is marked as not-writeable.
279
- _(song.title).must_equal "Unopened"
280
- end
281
- end
282
-
283
- # # not sure if we should catch that in Reform or rather do that in disposable. this is https://github.com/trailblazer/reform/pull/104
284
- # # describe ":populator with :empty" do
285
- # # let(:form) {
286
- # # Class.new(Reform::Form) do
287
- # # collection :songs, :empty => true, :populator => lambda { |fragment, index, args|
288
- # # songs[index] = args.binding[:form].new(Song.new)
289
- # # } do
290
- # # property :title
291
- # # end
292
- # # end
293
- # # }
294
-
295
- # # let(:params) {
296
- # # {
297
- # # "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"}]
298
- # # }
299
- # # }
300
-
301
- # # subject { form.new(Album.new("Hits", [], [])) }
302
-
303
- # # before { subject.validate(params) }
304
-
305
- # # it { subject.songs[0].title.must_equal "Fallout" }
306
- # # it { subject.songs[1].title.must_equal "Roxanne" }
307
- # # end
308
-
309
- # # test cardinalities.
310
- # describe "with empty collection and cardinality" do
311
- # let(:album) { Album.new }
312
-
313
- # subject { Class.new(Reform::Form) do
314
- # include Reform::Form::ActiveModel
315
- # model :album
316
-
317
- # collection :songs do
318
- # property :title
319
- # end
320
-
321
- # property :hit do
322
- # property :title
323
- # end
324
-
325
- # validates :songs, :length => {:minimum => 1}
326
- # validates :hit, :presence => true
327
- # end.new(album) }
328
-
329
- # describe "invalid" do
330
- # before { subject.validate({}).must_equal false }
331
-
332
- # it do
333
- # # ensure that only hit and songs keys are present
334
- # subject.errors.messages.keys.sort.must_equal([:hit, :songs])
335
- # # validate content of hit and songs keys
336
- # subject.errors.messages[:hit].must_equal(["must be filled"])
337
- # subject.errors.messages[:songs].first.must_match(/\Ais too short \(minimum is 1 characters?\)\z/)
338
- # end
339
- # end
340
-
341
- # describe "valid" do
342
- # let(:album) { Album.new(nil, Song.new, [Song.new("Urban Myth")]) }
343
-
344
- # before {
345
- # subject.validate({"songs" => [{"title"=>"Daddy, Brother, Lover, Little Boy"}], "hit" => {"title"=>"The Horse"}}).
346
- # must_equal true
347
- # }
348
-
349
- # it { subject.errors.messages.must_equal({}) }
350
- # end
351
- # end
352
-
353
- # # providing manual validator method allows accessing form's API.
354
- # describe "with ::validate" do
355
- # let(:form) {
356
- # Class.new(Reform::Form) do
357
- # property :title
358
-
359
- # validate :title?
360
-
361
- # def title?
362
- # errors.add :title, "not lowercase" if title == "Fallout"
363
- # end
364
- # end
365
- # }
366
-
367
- # let(:params) { {"title" => "Fallout"} }
368
- # let(:song) { Song.new("Englishman") }
369
-
370
- # subject { form.new(song) }
371
-
372
- # before { @res = subject.validate(params) }
373
-
374
- # it { @res.must_equal false }
375
- # it { subject.errors.messages.must_equal({:title=>["not lowercase"]}) }
376
- # end
377
-
378
- # # overriding the reader for a nested form should only be considered when rendering.
379
- # describe "with overridden reader for nested form" do
380
- # let(:form) {
381
- # Class.new(Reform::Form) do
382
- # property :band, :populate_if_empty => lambda { |*| Band.new } do
383
- # property :label
384
- # end
385
-
386
- # collection :songs, :populate_if_empty => lambda { |*| Song.new } do
387
- # property :title
388
- # end
389
-
390
- # def band
391
- # raise "only call me when rendering the form!"
392
- # end
393
-
394
- # def songs
395
- # raise "only call me when rendering the form!"
396
- # end
397
- # end.new(album)
398
- # }
399
-
400
- # let(:album) { Album.new }
401
-
402
- # # don't use #artist when validating!
403
- # it do
404
- # form.validate("band" => {"label" => "Hellcat"}, "songs" => [{"title" => "Stand Your Ground"}, {"title" => "Otherside"}])
405
- # form.sync
406
- # album.band.label.must_equal "Hellcat"
407
- # album.songs.first.title.must_equal "Stand Your Ground"
408
- # end
409
- # end
410
- # end