reform 2.3.0.rc1 → 2.3.0.rc2
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 +2 -0
- data/.rubocop.yml +30 -0
- data/.rubocop_todo.yml +460 -0
- data/.travis.yml +26 -11
- data/CHANGES.md +25 -2
- data/Gemfile +6 -3
- data/ISSUE_TEMPLATE.md +1 -1
- data/README.md +2 -4
- data/Rakefile +18 -9
- data/lib/reform/contract.rb +7 -7
- data/lib/reform/contract/custom_error.rb +41 -0
- data/lib/reform/contract/validate.rb +9 -5
- data/lib/reform/errors.rb +27 -15
- data/lib/reform/form.rb +22 -11
- data/lib/reform/form/call.rb +1 -1
- data/lib/reform/form/composition.rb +2 -2
- data/lib/reform/form/dry.rb +10 -86
- data/lib/reform/form/dry/input_hash.rb +37 -0
- data/lib/reform/form/dry/new_api.rb +58 -0
- data/lib/reform/form/dry/old_api.rb +61 -0
- data/lib/reform/form/populator.rb +9 -11
- data/lib/reform/form/prepopulate.rb +3 -2
- data/lib/reform/form/validate.rb +19 -12
- data/lib/reform/result.rb +36 -9
- data/lib/reform/validation.rb +10 -8
- data/lib/reform/validation/groups.rb +2 -3
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +10 -9
- data/test/benchmarking.rb +10 -11
- data/test/call_new_api.rb +23 -0
- data/test/{call_test.rb → call_old_api.rb} +3 -3
- data/test/changed_test.rb +7 -7
- data/test/coercion_test.rb +50 -18
- data/test/composition_new_api.rb +186 -0
- data/test/{composition_test.rb → composition_old_api.rb} +23 -26
- data/test/contract/custom_error_test.rb +55 -0
- data/test/contract_new_api.rb +77 -0
- data/test/{contract_test.rb → contract_old_api.rb} +8 -8
- data/test/default_test.rb +1 -1
- data/test/deserialize_test.rb +8 -11
- data/test/errors_new_api.rb +225 -0
- data/test/errors_old_api.rb +230 -0
- data/test/feature_test.rb +7 -9
- data/test/fixtures/dry_error_messages.yml +5 -2
- data/test/fixtures/dry_new_api_error_messages.yml +104 -0
- data/test/form_new_api.rb +57 -0
- data/test/{form_test.rb → form_old_api.rb} +2 -2
- data/test/form_option_new_api.rb +24 -0
- data/test/{form_option_test.rb → form_option_old_api.rb} +1 -1
- data/test/from_test.rb +8 -12
- data/test/inherit_new_api.rb +105 -0
- data/test/{inherit_test.rb → inherit_old_api.rb} +10 -17
- data/test/module_new_api.rb +137 -0
- data/test/{module_test.rb → module_old_api.rb} +19 -15
- data/test/parse_option_test.rb +5 -5
- data/test/parse_pipeline_test.rb +2 -2
- data/test/populate_new_api.rb +304 -0
- data/test/{populate_test.rb → populate_old_api.rb} +28 -34
- data/test/populator_skip_test.rb +1 -2
- data/test/prepopulator_test.rb +5 -6
- data/test/read_only_test.rb +12 -1
- data/test/readable_test.rb +5 -5
- data/test/reform_new_api.rb +204 -0
- data/test/{reform_test.rb → reform_old_api.rb} +17 -23
- data/test/save_new_api.rb +101 -0
- data/test/{save_test.rb → save_old_api.rb} +10 -13
- data/test/setup_test.rb +6 -6
- data/test/{skip_if_test.rb → skip_if_new_api.rb} +20 -9
- data/test/skip_if_old_api.rb +92 -0
- data/test/skip_setter_and_getter_test.rb +2 -3
- data/test/test_helper.rb +13 -5
- data/test/validate_new_api.rb +408 -0
- data/test/{validate_test.rb → validate_old_api.rb} +43 -53
- data/test/validation/dry_validation_new_api.rb +826 -0
- data/test/validation/{dry_validation_test.rb → dry_validation_old_api.rb} +223 -116
- data/test/validation/result_test.rb +20 -22
- data/test/validation_library_provided_test.rb +3 -3
- data/test/virtual_test.rb +46 -6
- data/test/writeable_test.rb +7 -7
- metadata +101 -51
- data/test/errors_test.rb +0 -180
- data/test/readonly_test.rb +0 -14
data/test/parse_option_test.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "test_helper"
|
|
2
2
|
|
|
3
3
|
class ParseOptionTest < MiniTest::Spec
|
|
4
4
|
Comment = Struct.new(:content, :user)
|
|
@@ -9,8 +9,8 @@ class ParseOptionTest < MiniTest::Spec
|
|
|
9
9
|
property :user, parse: false
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
let
|
|
13
|
-
let
|
|
12
|
+
let(:current_user) { User.new("Peter") }
|
|
13
|
+
let(:form) { CommentForm.new(Comment.new, user: current_user) }
|
|
14
14
|
|
|
15
15
|
it do
|
|
16
16
|
form.user.must_equal current_user
|
|
@@ -25,8 +25,8 @@ class ParseOptionTest < MiniTest::Spec
|
|
|
25
25
|
describe "using ':parse' option doesn't override other ':deserialize' options" do
|
|
26
26
|
class ArticleCommentForm < TestForm
|
|
27
27
|
property :content
|
|
28
|
-
property :article, deserializer: {
|
|
29
|
-
property :user, parse: false, deserializer: {
|
|
28
|
+
property :article, deserializer: {instance: "Instance"}
|
|
29
|
+
property :user, parse: false, deserializer: {instance: "Instance"}
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it do
|
data/test/parse_pipeline_test.rb
CHANGED
|
@@ -4,7 +4,7 @@ class ParsePipelineTest < MiniTest::Spec
|
|
|
4
4
|
Album = Struct.new(:name)
|
|
5
5
|
|
|
6
6
|
class AlbumForm < TestForm
|
|
7
|
-
property :name, deserializer: {
|
|
7
|
+
property :name, deserializer: {parse_pipeline: ->(input, options) { Representable::Pipeline[->(ipt, opts) { opts[:represented].name = ipt.inspect }] }}
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
it "allows passing :parse_pipeline directly" do
|
|
@@ -12,4 +12,4 @@ class ParsePipelineTest < MiniTest::Spec
|
|
|
12
12
|
form.validate("name" => "Greatest Hits")
|
|
13
13
|
form.name.must_equal "{\"name\"=>\"Greatest Hits\"}"
|
|
14
14
|
end
|
|
15
|
-
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class PopulatorTest < 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 < TestForm
|
|
9
|
+
property :name, populator: ->(options) { self.name = options[:fragment].reverse }
|
|
10
|
+
validation do
|
|
11
|
+
params { required(:name).filled }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
collection :songs,
|
|
15
|
+
populator: ->(fragment:, model:, index:, **) {
|
|
16
|
+
(item = model[index]) ? item : model.insert(index, Song.new)
|
|
17
|
+
} do
|
|
18
|
+
property :title
|
|
19
|
+
validation do
|
|
20
|
+
params { required(:title).filled }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
property :composer, populator: ->(options) { options[:model] || self.composer = Artist.new } do
|
|
24
|
+
property :name
|
|
25
|
+
validation do
|
|
26
|
+
params { required(:name).filled }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# property :artist, populator: lambda { |fragment, options| (item = options.binding.get) ? item : Artist.new } do
|
|
32
|
+
# NOTE: we have to document that model here is the twin!
|
|
33
|
+
property :artist, populator: ->(options) { options[:model] || self.artist = Artist.new } do
|
|
34
|
+
property :name
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
let(:song) { Song.new("Broken") }
|
|
39
|
+
let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
|
|
40
|
+
let(:composer) { Artist.new("Greg Graffin") }
|
|
41
|
+
let(:artist) { Artist.new("Bad Religion") }
|
|
42
|
+
let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
|
|
43
|
+
|
|
44
|
+
let(:form) { AlbumForm.new(album) }
|
|
45
|
+
|
|
46
|
+
it "runs populator on scalar" do
|
|
47
|
+
form.validate(
|
|
48
|
+
"name" => "override me!"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
form.name.must_equal "!em edirrevo"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# changing existing property :artist.
|
|
55
|
+
# TODO: check with artist==nil
|
|
56
|
+
it do
|
|
57
|
+
old_id = artist.object_id
|
|
58
|
+
|
|
59
|
+
form.validate(
|
|
60
|
+
"artist" => {"name" => "Marcus Miller"}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
form.artist.model.object_id.must_equal old_id
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# use populator for default value on scalars?
|
|
67
|
+
|
|
68
|
+
# adding to collection via :populator.
|
|
69
|
+
# valid.
|
|
70
|
+
it "yyy" do
|
|
71
|
+
form.validate(
|
|
72
|
+
"songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"},
|
|
73
|
+
{"title" => "Rime Of The Ancient Mariner"}, # new song.
|
|
74
|
+
{"title" => "Re-Education", "composer" => {"name" => "Rise Against"}}], # new song with new composer.
|
|
75
|
+
).must_equal true
|
|
76
|
+
|
|
77
|
+
form.errors.messages.inspect.must_equal "{}"
|
|
78
|
+
|
|
79
|
+
# form has updated.
|
|
80
|
+
form.name.must_equal "The Dissent Of Man"
|
|
81
|
+
form.songs[0].title.must_equal "Fallout"
|
|
82
|
+
form.songs[1].title.must_equal "Roxanne"
|
|
83
|
+
form.songs[1].composer.name.must_equal "Greg Graffin"
|
|
84
|
+
|
|
85
|
+
form.songs[1].composer.model.must_be_instance_of Artist
|
|
86
|
+
|
|
87
|
+
form.songs[1].title.must_equal "Roxanne"
|
|
88
|
+
form.songs[2].title.must_equal "Rime Of The Ancient Mariner" # new song added.
|
|
89
|
+
form.songs[3].title.must_equal "Re-Education"
|
|
90
|
+
form.songs[3].composer.name.must_equal "Rise Against"
|
|
91
|
+
form.songs.size.must_equal 4
|
|
92
|
+
form.artist.name.must_equal "Bad Religion"
|
|
93
|
+
|
|
94
|
+
# model has not changed, yet.
|
|
95
|
+
album.name.must_equal "The Dissent Of Man"
|
|
96
|
+
album.songs[0].title.must_equal "Broken"
|
|
97
|
+
album.songs[1].title.must_equal "Resist Stance"
|
|
98
|
+
album.songs[1].composer.name.must_equal "Greg Graffin"
|
|
99
|
+
album.songs.size.must_equal 2
|
|
100
|
+
album.artist.name.must_equal "Bad Religion"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class PopulateWithMethodTest < Minitest::Spec
|
|
105
|
+
Album = Struct.new(:title)
|
|
106
|
+
|
|
107
|
+
class AlbumForm < TestForm
|
|
108
|
+
property :title, populator: :title!
|
|
109
|
+
|
|
110
|
+
def title!(options)
|
|
111
|
+
self.title = options[:fragment].reverse
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
let(:form) { AlbumForm.new(Album.new) }
|
|
116
|
+
|
|
117
|
+
it "runs populator method" do
|
|
118
|
+
form.validate("title" => "override me!")
|
|
119
|
+
|
|
120
|
+
form.title.must_equal "!em edirrevo"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class PopulateWithCallableTest < Minitest::Spec
|
|
125
|
+
Album = Struct.new(:title)
|
|
126
|
+
|
|
127
|
+
class TitlePopulator
|
|
128
|
+
include Uber::Callable
|
|
129
|
+
|
|
130
|
+
def call(form, options)
|
|
131
|
+
form.title = options[:fragment].reverse
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
class AlbumForm < TestForm
|
|
136
|
+
property :title, populator: TitlePopulator.new
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
let(:form) { AlbumForm.new(Album.new) }
|
|
140
|
+
|
|
141
|
+
it "runs populator method" do
|
|
142
|
+
form.validate("title" => "override me!")
|
|
143
|
+
|
|
144
|
+
form.title.must_equal "!em edirrevo"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
class PopulateWithProcTest < Minitest::Spec
|
|
149
|
+
Album = Struct.new(:title)
|
|
150
|
+
|
|
151
|
+
TitlePopulator = ->(options) do
|
|
152
|
+
options[:represented].title = options[:fragment].reverse
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
class AlbumForm < TestForm
|
|
156
|
+
property :title, populator: TitlePopulator
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
let(:form) { AlbumForm.new(Album.new) }
|
|
160
|
+
|
|
161
|
+
it "runs populator method" do
|
|
162
|
+
form.validate("title" => "override me!")
|
|
163
|
+
|
|
164
|
+
form.title.must_equal "!em edirrevo"
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
class PopulateIfEmptyTest < MiniTest::Spec
|
|
169
|
+
Song = Struct.new(:title, :album, :composer)
|
|
170
|
+
Album = Struct.new(:name, :songs, :artist)
|
|
171
|
+
Artist = Struct.new(:name)
|
|
172
|
+
|
|
173
|
+
let(:song) { Song.new("Broken") }
|
|
174
|
+
let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
|
|
175
|
+
let(:composer) { Artist.new("Greg Graffin") }
|
|
176
|
+
let(:artist) { Artist.new("Bad Religion") }
|
|
177
|
+
let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
|
|
178
|
+
|
|
179
|
+
class AlbumForm < TestForm
|
|
180
|
+
property :name
|
|
181
|
+
|
|
182
|
+
collection :songs,
|
|
183
|
+
populate_if_empty: Song do # class name works.
|
|
184
|
+
|
|
185
|
+
property :title
|
|
186
|
+
validation do
|
|
187
|
+
params { required(:title).filled }
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
property :composer, populate_if_empty: :populate_composer! do # lambda works, too. in form context.
|
|
191
|
+
property :name
|
|
192
|
+
validation do
|
|
193
|
+
params { required(:name).filled }
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
private
|
|
198
|
+
def populate_composer!(options)
|
|
199
|
+
Artist.new
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
property :artist, populate_if_empty: ->(args) { create_artist(args[:fragment], args[:user_options]) } do # methods work, too.
|
|
204
|
+
property :name
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
private
|
|
208
|
+
class Sting < Artist
|
|
209
|
+
attr_accessor :args
|
|
210
|
+
end
|
|
211
|
+
def create_artist(input, user_options)
|
|
212
|
+
Sting.new.tap { |artist| artist.args = ([input, user_options].to_s) }
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
let(:form) { AlbumForm.new(album) }
|
|
217
|
+
|
|
218
|
+
it do
|
|
219
|
+
form.songs.size.must_equal 2
|
|
220
|
+
|
|
221
|
+
form.validate(
|
|
222
|
+
"songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"},
|
|
223
|
+
{"title" => "Rime Of The Ancient Mariner"}, # new song.
|
|
224
|
+
{"title" => "Re-Education", "composer" => {"name" => "Rise Against"}}], # new song with new composer.
|
|
225
|
+
).must_equal true
|
|
226
|
+
|
|
227
|
+
form.errors.messages.inspect.must_equal "{}"
|
|
228
|
+
|
|
229
|
+
# form has updated.
|
|
230
|
+
form.name.must_equal "The Dissent Of Man"
|
|
231
|
+
form.songs[0].title.must_equal "Fallout"
|
|
232
|
+
form.songs[1].title.must_equal "Roxanne"
|
|
233
|
+
form.songs[1].composer.name.must_equal "Greg Graffin"
|
|
234
|
+
form.songs[1].title.must_equal "Roxanne"
|
|
235
|
+
form.songs[2].title.must_equal "Rime Of The Ancient Mariner" # new song added.
|
|
236
|
+
form.songs[3].title.must_equal "Re-Education"
|
|
237
|
+
form.songs[3].composer.name.must_equal "Rise Against"
|
|
238
|
+
form.songs.size.must_equal 4
|
|
239
|
+
form.artist.name.must_equal "Bad Religion"
|
|
240
|
+
|
|
241
|
+
# model has not changed, yet.
|
|
242
|
+
album.name.must_equal "The Dissent Of Man"
|
|
243
|
+
album.songs[0].title.must_equal "Broken"
|
|
244
|
+
album.songs[1].title.must_equal "Resist Stance"
|
|
245
|
+
album.songs[1].composer.name.must_equal "Greg Graffin"
|
|
246
|
+
album.songs.size.must_equal 2
|
|
247
|
+
album.artist.name.must_equal "Bad Religion"
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# trigger artist populator. lambda calling form instance method.
|
|
251
|
+
it "xxxx" do
|
|
252
|
+
form = AlbumForm.new(album = Album.new)
|
|
253
|
+
form.validate("artist" => {"name" => "From Autumn To Ashes"})
|
|
254
|
+
|
|
255
|
+
form.artist.name.must_equal "From Autumn To Ashes"
|
|
256
|
+
# test lambda was executed in form context.
|
|
257
|
+
form.artist.model.must_be_instance_of AlbumForm::Sting
|
|
258
|
+
# test lambda block arguments.
|
|
259
|
+
form.artist.model.args.to_s.must_equal "[{\"name\"=>\"From Autumn To Ashes\"}, nil]"
|
|
260
|
+
|
|
261
|
+
assert_nil album.artist
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# delete songs while deserializing.
|
|
266
|
+
class PopulateIfEmptyWithDeletionTest < MiniTest::Spec
|
|
267
|
+
Song = Struct.new(:title, :album, :composer)
|
|
268
|
+
Album = Struct.new(:name, :songs, :artist)
|
|
269
|
+
|
|
270
|
+
let(:song) { Song.new("Broken") }
|
|
271
|
+
let(:song2) { Song.new("Resist Stance") }
|
|
272
|
+
let(:album) { Album.new("The Dissent Of Man", [song, song2]) }
|
|
273
|
+
|
|
274
|
+
class AlbumForm < TestForm
|
|
275
|
+
property :name
|
|
276
|
+
|
|
277
|
+
collection :songs,
|
|
278
|
+
populate_if_empty: Song, skip_if: :delete_song! do
|
|
279
|
+
|
|
280
|
+
property :title
|
|
281
|
+
validation do
|
|
282
|
+
params { required(:title).filled }
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def delete_song!(options)
|
|
287
|
+
songs.delete(songs[0]) and return true if options[:fragment]["title"] == "Broken, delete me!"
|
|
288
|
+
false
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
let(:form) { AlbumForm.new(album) }
|
|
293
|
+
|
|
294
|
+
it do
|
|
295
|
+
form.validate(
|
|
296
|
+
"songs" => [{"title" => "Broken, delete me!"}, {"title" => "Roxanne"}]
|
|
297
|
+
).must_equal true
|
|
298
|
+
|
|
299
|
+
form.errors.messages.inspect.must_equal "{}"
|
|
300
|
+
|
|
301
|
+
form.songs.size.must_equal 1
|
|
302
|
+
form.songs[0].title.must_equal "Roxanne"
|
|
303
|
+
end
|
|
304
|
+
end
|
|
@@ -12,15 +12,15 @@ class PopulatorTest < MiniTest::Spec
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
collection :songs,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
populator: ->(fragment:, model:, index:, **) {
|
|
16
|
+
(item = model[index]) ? item : model.insert(index, Song.new)
|
|
17
|
+
} do
|
|
18
18
|
property :title
|
|
19
19
|
validation do
|
|
20
20
|
required(:title).filled
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
property :composer, populator: ->(options) { options[:model] || self.composer= Artist.new } do
|
|
23
|
+
property :composer, populator: ->(options) { options[:model] || self.composer = Artist.new } do
|
|
24
24
|
property :name
|
|
25
25
|
validation do
|
|
26
26
|
required(:name).filled
|
|
@@ -35,13 +35,13 @@ class PopulatorTest < MiniTest::Spec
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
let
|
|
39
|
-
let
|
|
40
|
-
let
|
|
41
|
-
let
|
|
42
|
-
let
|
|
38
|
+
let(:song) { Song.new("Broken") }
|
|
39
|
+
let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
|
|
40
|
+
let(:composer) { Artist.new("Greg Graffin") }
|
|
41
|
+
let(:artist) { Artist.new("Bad Religion") }
|
|
42
|
+
let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
|
|
43
43
|
|
|
44
|
-
let
|
|
44
|
+
let(:form) { AlbumForm.new(album) }
|
|
45
45
|
|
|
46
46
|
it "runs populator on scalar" do
|
|
47
47
|
form.validate(
|
|
@@ -91,7 +91,6 @@ class PopulatorTest < MiniTest::Spec
|
|
|
91
91
|
form.songs.size.must_equal 4
|
|
92
92
|
form.artist.name.must_equal "Bad Religion"
|
|
93
93
|
|
|
94
|
-
|
|
95
94
|
# model has not changed, yet.
|
|
96
95
|
album.name.must_equal "The Dissent Of Man"
|
|
97
96
|
album.songs[0].title.must_equal "Broken"
|
|
@@ -113,7 +112,7 @@ class PopulateWithMethodTest < Minitest::Spec
|
|
|
113
112
|
end
|
|
114
113
|
end
|
|
115
114
|
|
|
116
|
-
let
|
|
115
|
+
let(:form) { AlbumForm.new(Album.new) }
|
|
117
116
|
|
|
118
117
|
it "runs populator method" do
|
|
119
118
|
form.validate("title" => "override me!")
|
|
@@ -137,7 +136,7 @@ class PopulateWithCallableTest < Minitest::Spec
|
|
|
137
136
|
property :title, populator: TitlePopulator.new
|
|
138
137
|
end
|
|
139
138
|
|
|
140
|
-
let
|
|
139
|
+
let(:form) { AlbumForm.new(Album.new) }
|
|
141
140
|
|
|
142
141
|
it "runs populator method" do
|
|
143
142
|
form.validate("title" => "override me!")
|
|
@@ -157,7 +156,7 @@ class PopulateWithProcTest < Minitest::Spec
|
|
|
157
156
|
property :title, populator: TitlePopulator
|
|
158
157
|
end
|
|
159
158
|
|
|
160
|
-
let
|
|
159
|
+
let(:form) { AlbumForm.new(Album.new) }
|
|
161
160
|
|
|
162
161
|
it "runs populator method" do
|
|
163
162
|
form.validate("title" => "override me!")
|
|
@@ -171,13 +170,11 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
|
171
170
|
Album = Struct.new(:name, :songs, :artist)
|
|
172
171
|
Artist = Struct.new(:name)
|
|
173
172
|
|
|
174
|
-
let
|
|
175
|
-
let
|
|
176
|
-
let
|
|
177
|
-
let
|
|
178
|
-
let
|
|
179
|
-
|
|
180
|
-
|
|
173
|
+
let(:song) { Song.new("Broken") }
|
|
174
|
+
let(:song_with_composer) { Song.new("Resist Stance", nil, composer) }
|
|
175
|
+
let(:composer) { Artist.new("Greg Graffin") }
|
|
176
|
+
let(:artist) { Artist.new("Bad Religion") }
|
|
177
|
+
let(:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
|
|
181
178
|
|
|
182
179
|
class AlbumForm < TestForm
|
|
183
180
|
property :name
|
|
@@ -203,26 +200,26 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
|
203
200
|
end
|
|
204
201
|
end
|
|
205
202
|
|
|
206
|
-
property :artist, populate_if_empty:
|
|
203
|
+
property :artist, populate_if_empty: ->(args) { create_artist(args[:fragment], args[:user_options]) } do # methods work, too.
|
|
207
204
|
property :name
|
|
208
205
|
end
|
|
209
206
|
|
|
210
|
-
|
|
207
|
+
private
|
|
211
208
|
class Sting < Artist
|
|
212
209
|
attr_accessor :args
|
|
213
210
|
end
|
|
214
211
|
def create_artist(input, user_options)
|
|
215
|
-
Sting.new.tap { |artist| artist.args=([input, user_options].to_s) }
|
|
212
|
+
Sting.new.tap { |artist| artist.args = ([input, user_options].to_s) }
|
|
216
213
|
end
|
|
217
214
|
end
|
|
218
215
|
|
|
219
|
-
let
|
|
216
|
+
let(:form) { AlbumForm.new(album) }
|
|
220
217
|
|
|
221
218
|
it do
|
|
222
219
|
form.songs.size.must_equal 2
|
|
223
220
|
|
|
224
221
|
form.validate(
|
|
225
|
-
"songs"
|
|
222
|
+
"songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"},
|
|
226
223
|
{"title" => "Rime Of The Ancient Mariner"}, # new song.
|
|
227
224
|
{"title" => "Re-Education", "composer" => {"name" => "Rise Against"}}], # new song with new composer.
|
|
228
225
|
).must_equal true
|
|
@@ -241,7 +238,6 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
|
241
238
|
form.songs.size.must_equal 4
|
|
242
239
|
form.artist.name.must_equal "Bad Religion"
|
|
243
240
|
|
|
244
|
-
|
|
245
241
|
# model has not changed, yet.
|
|
246
242
|
album.name.must_equal "The Dissent Of Man"
|
|
247
243
|
album.songs[0].title.must_equal "Broken"
|
|
@@ -266,16 +262,14 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
|
266
262
|
end
|
|
267
263
|
end
|
|
268
264
|
|
|
269
|
-
|
|
270
265
|
# delete songs while deserializing.
|
|
271
266
|
class PopulateIfEmptyWithDeletionTest < MiniTest::Spec
|
|
272
267
|
Song = Struct.new(:title, :album, :composer)
|
|
273
268
|
Album = Struct.new(:name, :songs, :artist)
|
|
274
269
|
|
|
275
|
-
let
|
|
276
|
-
let
|
|
277
|
-
let
|
|
278
|
-
|
|
270
|
+
let(:song) { Song.new("Broken") }
|
|
271
|
+
let(:song2) { Song.new("Resist Stance") }
|
|
272
|
+
let(:album) { Album.new("The Dissent Of Man", [song, song2]) }
|
|
279
273
|
|
|
280
274
|
class AlbumForm < TestForm
|
|
281
275
|
property :name
|
|
@@ -295,11 +289,11 @@ class PopulateIfEmptyWithDeletionTest < MiniTest::Spec
|
|
|
295
289
|
end
|
|
296
290
|
end
|
|
297
291
|
|
|
298
|
-
let
|
|
292
|
+
let(:form) { AlbumForm.new(album) }
|
|
299
293
|
|
|
300
294
|
it do
|
|
301
295
|
form.validate(
|
|
302
|
-
"songs"
|
|
296
|
+
"songs" => [{"title" => "Broken, delete me!"}, {"title" => "Roxanne"}]
|
|
303
297
|
).must_equal true
|
|
304
298
|
|
|
305
299
|
form.errors.messages.inspect.must_equal "{}"
|