reform 2.2.4 → 2.3.0.rc1
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/.travis.yml +13 -7
- data/CHANGES.md +26 -4
- data/CONTRIBUTING.md +31 -0
- data/Gemfile +1 -12
- data/ISSUE_TEMPLATE.md +25 -0
- data/LICENSE.txt +1 -1
- data/README.md +3 -3
- data/lib/reform.rb +1 -0
- data/lib/reform/contract.rb +1 -11
- data/lib/reform/contract/validate.rb +49 -23
- data/lib/reform/errors.rb +49 -0
- data/lib/reform/form.rb +20 -5
- data/lib/reform/form/dry.rb +57 -29
- data/lib/reform/form/populator.rb +2 -16
- data/lib/reform/form/prepopulate.rb +1 -1
- data/lib/reform/form/validate.rb +10 -2
- data/lib/reform/result.rb +63 -0
- data/lib/reform/validation.rb +19 -13
- data/lib/reform/validation/groups.rb +11 -25
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +7 -6
- data/test/benchmarking.rb +39 -5
- data/test/call_test.rb +1 -1
- data/test/changed_test.rb +1 -1
- data/test/coercion_test.rb +2 -2
- data/test/composition_test.rb +47 -9
- data/test/contract_test.rb +5 -5
- data/test/default_test.rb +1 -1
- data/test/deserialize_test.rb +3 -3
- data/test/errors_test.rb +36 -21
- data/test/feature_test.rb +1 -1
- data/test/fixtures/dry_error_messages.yml +70 -23
- data/test/form_option_test.rb +3 -3
- data/test/form_test.rb +3 -3
- data/test/from_test.rb +2 -2
- data/test/inherit_test.rb +44 -51
- data/test/module_test.rb +12 -12
- data/test/parse_option_test.rb +40 -0
- data/test/parse_pipeline_test.rb +2 -2
- data/test/populate_test.rb +59 -19
- data/test/populator_skip_test.rb +9 -8
- data/test/prepopulator_test.rb +3 -3
- data/test/readable_test.rb +2 -2
- data/test/readonly_test.rb +1 -1
- data/test/reform_test.rb +16 -31
- data/test/save_test.rb +23 -8
- data/test/setup_test.rb +2 -2
- data/test/skip_if_test.rb +4 -4
- data/test/skip_setter_and_getter_test.rb +1 -1
- data/test/test_helper.rb +13 -10
- data/test/validate_test.rb +18 -18
- data/test/validation/dry_validation_test.rb +430 -117
- data/test/validation/result_test.rb +79 -0
- data/test/validation_library_provided_test.rb +16 -0
- data/test/virtual_test.rb +1 -1
- data/test/writeable_test.rb +31 -2
- metadata +42 -23
- data/gemfiles/Gemfile.disposable-0.3 +0 -6
- data/lib/reform/contract/errors.rb +0 -43
- data/lib/reform/form/mongoid.rb +0 -37
- data/lib/reform/form/orm.rb +0 -26
- data/lib/reform/mongoid.rb +0 -4
- data/test/deprecation_test.rb +0 -27
- data/test/validation/dry_test.rb +0 -60
- data/test/validation/errors.yml +0 -4
data/test/module_test.rb
CHANGED
@@ -9,7 +9,7 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
9
9
|
property :title
|
10
10
|
|
11
11
|
validation do
|
12
|
-
|
12
|
+
required(:title).filled
|
13
13
|
end
|
14
14
|
|
15
15
|
def id # gets mixed into Form, too.
|
@@ -22,7 +22,7 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
22
22
|
end
|
23
23
|
|
24
24
|
validation do
|
25
|
-
|
25
|
+
required(:band).filled
|
26
26
|
end
|
27
27
|
|
28
28
|
include Dry::Types.module # allows using Types::* in module.
|
@@ -36,22 +36,22 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
36
36
|
collection :airplays do
|
37
37
|
property :station
|
38
38
|
validation do
|
39
|
-
|
39
|
+
required(:station).filled
|
40
40
|
end
|
41
41
|
end
|
42
42
|
validation do
|
43
|
-
|
43
|
+
required(:airplays).filled
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
|
48
48
|
# test:
|
49
49
|
# by including BandPropertyForm into multiple classes we assure that options hashes don't get messed up by AM:V.
|
50
|
-
class HitForm <
|
50
|
+
class HitForm < TestForm
|
51
51
|
include BandPropertyForm
|
52
52
|
end
|
53
53
|
|
54
|
-
class SongForm <
|
54
|
+
class SongForm < TestForm
|
55
55
|
include Coercion
|
56
56
|
property :title
|
57
57
|
|
@@ -72,7 +72,7 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
72
72
|
it do
|
73
73
|
form = SongForm.new(OpenStruct.new)
|
74
74
|
form.validate({})
|
75
|
-
form.errors.messages.must_equal({:band=>["
|
75
|
+
form.errors.messages.must_equal({:band=>["must be filled"]})
|
76
76
|
end
|
77
77
|
|
78
78
|
# coercion works
|
@@ -90,18 +90,18 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
90
90
|
|
91
91
|
property :name
|
92
92
|
validation do
|
93
|
-
|
93
|
+
required(:name).filled
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
class AlbumForm <
|
97
|
+
class AlbumForm < TestForm
|
98
98
|
include AlbumFormModule
|
99
99
|
|
100
100
|
# pp heritage
|
101
101
|
property :band, :inherit => true do
|
102
102
|
property :label
|
103
103
|
validation do
|
104
|
-
|
104
|
+
required(:label).filled
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|
@@ -109,7 +109,7 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
109
109
|
it do
|
110
110
|
form = AlbumForm.new(OpenStruct.new(:band => OpenStruct.new))
|
111
111
|
form.validate({"band" => {}})
|
112
|
-
form.errors.messages.must_equal({:band=>["must be filled"], :"band.
|
112
|
+
form.errors.messages.must_equal({:"band.title"=>["must be filled"], :"band.label"=>["must be filled"], :name=>["must be filled"]})
|
113
113
|
end
|
114
114
|
|
115
115
|
|
@@ -127,7 +127,7 @@ class ModuleInclusionTest < MiniTest::Spec
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
-
class IncludingSongForm <
|
130
|
+
class IncludingSongForm < TestForm
|
131
131
|
include SongModule
|
132
132
|
end
|
133
133
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ParseOptionTest < MiniTest::Spec
|
4
|
+
Comment = Struct.new(:content, :user)
|
5
|
+
User = Struct.new(:name)
|
6
|
+
|
7
|
+
class CommentForm < TestForm
|
8
|
+
property :content
|
9
|
+
property :user, parse: false
|
10
|
+
end
|
11
|
+
|
12
|
+
let (:current_user) { User.new("Peter") }
|
13
|
+
let (:form) { CommentForm.new(Comment.new, user: current_user) }
|
14
|
+
|
15
|
+
it do
|
16
|
+
form.user.must_equal current_user
|
17
|
+
|
18
|
+
lorem = "Lorem ipsum dolor sit amet..."
|
19
|
+
form.validate("content" => lorem, "user" => "not the current user")
|
20
|
+
|
21
|
+
form.content.must_equal lorem
|
22
|
+
form.user.must_equal current_user
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "using ':parse' option doesn't override other ':deserialize' options" do
|
26
|
+
class ArticleCommentForm < TestForm
|
27
|
+
property :content
|
28
|
+
property :article, deserializer: { instance: "Instance" }
|
29
|
+
property :user, parse: false, deserializer: { instance: "Instance" }
|
30
|
+
end
|
31
|
+
|
32
|
+
it do
|
33
|
+
ArticleCommentForm.definitions.get(:user)[:deserializer][:writeable].must_equal false
|
34
|
+
ArticleCommentForm.definitions.get(:user)[:deserializer][:instance].must_equal "Instance"
|
35
|
+
|
36
|
+
ArticleCommentForm.definitions.get(:article)[:deserializer][:writeable].must_equal true
|
37
|
+
ArticleCommentForm.definitions.get(:article)[:deserializer][:instance].must_equal "Instance"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/test/parse_pipeline_test.rb
CHANGED
@@ -3,8 +3,8 @@ require "test_helper"
|
|
3
3
|
class ParsePipelineTest < MiniTest::Spec
|
4
4
|
Album = Struct.new(:name)
|
5
5
|
|
6
|
-
class AlbumForm <
|
7
|
-
property :name, deserializer: { parse_pipeline: ->(input, options) { Representable::Pipeline[->(
|
6
|
+
class AlbumForm < TestForm
|
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
|
data/test/populate_test.rb
CHANGED
@@ -5,27 +5,25 @@ class PopulatorTest < MiniTest::Spec
|
|
5
5
|
Album = Struct.new(:name, :songs, :artist)
|
6
6
|
Artist = Struct.new(:name)
|
7
7
|
|
8
|
-
class AlbumForm <
|
8
|
+
class AlbumForm < TestForm
|
9
9
|
property :name, populator: ->(options) { self.name = options[:fragment].reverse }
|
10
10
|
validation do
|
11
|
-
|
11
|
+
required(:name).filled
|
12
12
|
end
|
13
13
|
|
14
14
|
collection :songs,
|
15
|
-
populator: ->(
|
16
|
-
|
17
|
-
|
18
|
-
(item = collection[index]) ? item : collection.insert(index, Song.new) } do
|
15
|
+
populator: ->(fragment:, model:, index:, **) {
|
16
|
+
(item = model[index]) ? item : model.insert(index, Song.new) } do
|
19
17
|
|
20
18
|
property :title
|
21
19
|
validation do
|
22
|
-
|
20
|
+
required(:title).filled
|
23
21
|
end
|
24
22
|
|
25
23
|
property :composer, populator: ->(options) { options[:model] || self.composer= Artist.new } do
|
26
24
|
property :name
|
27
25
|
validation do
|
28
|
-
|
26
|
+
required(:name).filled
|
29
27
|
end
|
30
28
|
end
|
31
29
|
end
|
@@ -107,7 +105,7 @@ end
|
|
107
105
|
class PopulateWithMethodTest < Minitest::Spec
|
108
106
|
Album = Struct.new(:title)
|
109
107
|
|
110
|
-
class AlbumForm <
|
108
|
+
class AlbumForm < TestForm
|
111
109
|
property :title, populator: :title!
|
112
110
|
|
113
111
|
def title!(options)
|
@@ -118,9 +116,51 @@ class PopulateWithMethodTest < Minitest::Spec
|
|
118
116
|
let (:form) { AlbumForm.new(Album.new) }
|
119
117
|
|
120
118
|
it "runs populator method" do
|
121
|
-
form.validate(
|
122
|
-
|
123
|
-
|
119
|
+
form.validate("title" => "override me!")
|
120
|
+
|
121
|
+
form.title.must_equal "!em edirrevo"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class PopulateWithCallableTest < Minitest::Spec
|
126
|
+
Album = Struct.new(:title)
|
127
|
+
|
128
|
+
class TitlePopulator
|
129
|
+
include Uber::Callable
|
130
|
+
|
131
|
+
def call(form, options)
|
132
|
+
form.title = options[:fragment].reverse
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class AlbumForm < TestForm
|
137
|
+
property :title, populator: TitlePopulator.new
|
138
|
+
end
|
139
|
+
|
140
|
+
let (:form) { AlbumForm.new(Album.new) }
|
141
|
+
|
142
|
+
it "runs populator method" do
|
143
|
+
form.validate("title" => "override me!")
|
144
|
+
|
145
|
+
form.title.must_equal "!em edirrevo"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class PopulateWithProcTest < Minitest::Spec
|
150
|
+
Album = Struct.new(:title)
|
151
|
+
|
152
|
+
TitlePopulator = ->(options) do
|
153
|
+
options[:represented].title = options[:fragment].reverse
|
154
|
+
end
|
155
|
+
|
156
|
+
class AlbumForm < TestForm
|
157
|
+
property :title, populator: TitlePopulator
|
158
|
+
end
|
159
|
+
|
160
|
+
let (:form) { AlbumForm.new(Album.new) }
|
161
|
+
|
162
|
+
it "runs populator method" do
|
163
|
+
form.validate("title" => "override me!")
|
124
164
|
|
125
165
|
form.title.must_equal "!em edirrevo"
|
126
166
|
end
|
@@ -139,7 +179,7 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
139
179
|
|
140
180
|
|
141
181
|
|
142
|
-
class AlbumForm <
|
182
|
+
class AlbumForm < TestForm
|
143
183
|
property :name
|
144
184
|
|
145
185
|
collection :songs,
|
@@ -147,18 +187,18 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
147
187
|
|
148
188
|
property :title
|
149
189
|
validation do
|
150
|
-
|
190
|
+
required(:title).filled
|
151
191
|
end
|
152
192
|
|
153
193
|
property :composer, populate_if_empty: :populate_composer! do # lambda works, too. in form context.
|
154
194
|
property :name
|
155
195
|
validation do
|
156
|
-
|
196
|
+
required(:name).filled
|
157
197
|
end
|
158
198
|
end
|
159
199
|
|
160
200
|
private
|
161
|
-
def populate_composer!(
|
201
|
+
def populate_composer!(options)
|
162
202
|
Artist.new
|
163
203
|
end
|
164
204
|
end
|
@@ -222,7 +262,7 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
222
262
|
# test lambda block arguments.
|
223
263
|
form.artist.model.args.to_s.must_equal "[{\"name\"=>\"From Autumn To Ashes\"}, nil]"
|
224
264
|
|
225
|
-
album.artist
|
265
|
+
assert_nil album.artist
|
226
266
|
end
|
227
267
|
end
|
228
268
|
|
@@ -237,7 +277,7 @@ class PopulateIfEmptyWithDeletionTest < MiniTest::Spec
|
|
237
277
|
let (:album) { Album.new("The Dissent Of Man", [song, song2]) }
|
238
278
|
|
239
279
|
|
240
|
-
class AlbumForm <
|
280
|
+
class AlbumForm < TestForm
|
241
281
|
property :name
|
242
282
|
|
243
283
|
collection :songs,
|
@@ -245,7 +285,7 @@ class PopulateIfEmptyWithDeletionTest < MiniTest::Spec
|
|
245
285
|
|
246
286
|
property :title
|
247
287
|
validation do
|
248
|
-
|
288
|
+
required(:title).filled
|
249
289
|
end
|
250
290
|
end
|
251
291
|
|
data/test/populator_skip_test.rb
CHANGED
@@ -5,13 +5,14 @@ class PopulatorSkipTest < MiniTest::Spec
|
|
5
5
|
Song = Struct.new(:title)
|
6
6
|
|
7
7
|
|
8
|
-
class AlbumForm <
|
9
|
-
collection :songs,
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
class AlbumForm < TestForm
|
9
|
+
collection :songs, populator: :my_populator do
|
10
|
+
property :title
|
11
|
+
end
|
12
|
+
|
13
|
+
def my_populator(options)
|
14
|
+
return skip! if options[:fragment][:title] == "Good"
|
15
|
+
songs[options[:index]]
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
@@ -22,7 +23,7 @@ class PopulatorSkipTest < MiniTest::Spec
|
|
22
23
|
form.validate(hash)
|
23
24
|
|
24
25
|
form.songs.size.must_equal 2
|
25
|
-
form.songs[0].title
|
26
|
+
assert_nil form.songs[0].title
|
26
27
|
form.songs[1].title.must_equal "Bad"
|
27
28
|
end
|
28
29
|
end
|
data/test/prepopulator_test.rb
CHANGED
@@ -4,7 +4,7 @@ class PrepopulatorTest < MiniTest::Spec
|
|
4
4
|
Song = Struct.new(:title, :band, :length)
|
5
5
|
Band = Struct.new(:name)
|
6
6
|
|
7
|
-
class AlbumForm <
|
7
|
+
class AlbumForm < TestForm
|
8
8
|
property :title, prepopulator: ->(*){ self.title = "Another Day At Work" } # normal assignment.
|
9
9
|
property :length
|
10
10
|
|
@@ -63,7 +63,7 @@ end
|
|
63
63
|
class PrepopulateWithoutConfiguration < MiniTest::Spec
|
64
64
|
Song = Struct.new(:title)
|
65
65
|
|
66
|
-
class AlbumForm <
|
66
|
+
class AlbumForm < TestForm
|
67
67
|
collection :songs do
|
68
68
|
property :title
|
69
69
|
end
|
@@ -83,7 +83,7 @@ class ManualPrepopulatorOverridingTest < MiniTest::Spec
|
|
83
83
|
Song = Struct.new(:title, :band, :length)
|
84
84
|
Band = Struct.new(:name)
|
85
85
|
|
86
|
-
class AlbumForm <
|
86
|
+
class AlbumForm < TestForm
|
87
87
|
property :title
|
88
88
|
property :length
|
89
89
|
|
data/test/readable_test.rb
CHANGED
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
class ReadableTest < MiniTest::Spec
|
4
4
|
Credentials = Struct.new(:password)
|
5
5
|
|
6
|
-
class PasswordForm <
|
6
|
+
class PasswordForm < TestForm
|
7
7
|
property :password, readable: false
|
8
8
|
end
|
9
9
|
|
@@ -11,7 +11,7 @@ class ReadableTest < MiniTest::Spec
|
|
11
11
|
let (:form) { PasswordForm.new(cred) }
|
12
12
|
|
13
13
|
it {
|
14
|
-
form.password
|
14
|
+
assert_nil form.password # password not read.
|
15
15
|
|
16
16
|
form.validate("password" => "123")
|
17
17
|
|
data/test/readonly_test.rb
CHANGED
data/test/reform_test.rb
CHANGED
@@ -6,12 +6,12 @@ class ReformTest < Minitest::Spec
|
|
6
6
|
|
7
7
|
let (:form) { SongForm.new(comp) }
|
8
8
|
|
9
|
-
class SongForm <
|
9
|
+
class SongForm < TestForm
|
10
10
|
property :name
|
11
11
|
property :title
|
12
12
|
|
13
13
|
validation do
|
14
|
-
|
14
|
+
required(:name).filled
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -19,7 +19,7 @@ class ReformTest < Minitest::Spec
|
|
19
19
|
let (:comp) { OpenStruct.new }
|
20
20
|
|
21
21
|
it "returns empty fields" do
|
22
|
-
form.title
|
22
|
+
assert_nil form.title
|
23
23
|
form.name.must_equal nil
|
24
24
|
end
|
25
25
|
|
@@ -27,7 +27,7 @@ class ReformTest < Minitest::Spec
|
|
27
27
|
it "returns filled-out fields" do
|
28
28
|
form.validate("name" => "Duran Duran")
|
29
29
|
|
30
|
-
form.title
|
30
|
+
assert_nil form.title
|
31
31
|
form.name.must_equal "Duran Duran"
|
32
32
|
end
|
33
33
|
end
|
@@ -63,18 +63,18 @@ class ReformTest < Minitest::Spec
|
|
63
63
|
it "doesn't change model properties" do
|
64
64
|
form.validate("name" => "Duran Duran")
|
65
65
|
|
66
|
-
comp.name
|
66
|
+
assert_nil comp.name # don't touch model, yet.
|
67
67
|
end
|
68
68
|
|
69
69
|
# TODO: test errors. test valid.
|
70
70
|
describe "invalid input" do
|
71
|
-
class ValidatingForm <
|
71
|
+
class ValidatingForm < TestForm
|
72
72
|
property :name
|
73
73
|
property :title
|
74
74
|
|
75
75
|
validation do
|
76
|
-
|
77
|
-
|
76
|
+
required(:name).filled
|
77
|
+
required(:title).filled
|
78
78
|
end
|
79
79
|
end
|
80
80
|
let (:form) { ValidatingForm.new(comp) }
|
@@ -85,26 +85,11 @@ class ReformTest < Minitest::Spec
|
|
85
85
|
|
86
86
|
it "populates errors" do
|
87
87
|
form.validate({})
|
88
|
-
form.errors.messages.must_equal({:name=>["
|
88
|
+
form.errors.messages.must_equal({:name=>["must be filled"], :title=>["must be filled"]})
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
# FIXME: add this test to reform-rails.
|
94
|
-
describe "#errors" do
|
95
|
-
before { form.validate({})}
|
96
|
-
|
97
|
-
it { form.errors.must_be_kind_of Reform::Contract::Errors }
|
98
|
-
|
99
|
-
it { form.errors.messages.must_equal({}) }
|
100
|
-
|
101
|
-
it do
|
102
|
-
form.validate({"name"=>""})
|
103
|
-
form.errors.messages.must_equal({:name=>["must be filled"]})
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
|
108
93
|
describe "#save" do
|
109
94
|
let (:comp) { OpenStruct.new }
|
110
95
|
let (:form) { SongForm.new(comp) }
|
@@ -115,7 +100,7 @@ class ReformTest < Minitest::Spec
|
|
115
100
|
form.save
|
116
101
|
|
117
102
|
comp.name.must_equal "Diesel Boy"
|
118
|
-
comp.title
|
103
|
+
assert_nil comp.title
|
119
104
|
end
|
120
105
|
|
121
106
|
describe "#save with block" do
|
@@ -126,7 +111,7 @@ class ReformTest < Minitest::Spec
|
|
126
111
|
hash = map
|
127
112
|
end
|
128
113
|
|
129
|
-
hash.must_equal({"name"=>"Diesel Boy"})
|
114
|
+
hash.must_equal({"name"=>"Diesel Boy", "title" => nil})
|
130
115
|
end
|
131
116
|
end
|
132
117
|
end
|
@@ -141,7 +126,7 @@ class ReformTest < Minitest::Spec
|
|
141
126
|
class HitForm < SongForm
|
142
127
|
property :position
|
143
128
|
validation do
|
144
|
-
|
129
|
+
required(:position).filled
|
145
130
|
end
|
146
131
|
end
|
147
132
|
|
@@ -149,15 +134,15 @@ class ReformTest < Minitest::Spec
|
|
149
134
|
it do
|
150
135
|
form.validate({"title" => "The Body"})
|
151
136
|
form.title.must_equal "The Body"
|
152
|
-
form.position
|
153
|
-
form.errors.messages.must_equal({:name=>["
|
137
|
+
assert_nil form.position
|
138
|
+
form.errors.messages.must_equal({:name=>["must be filled"], :position=>["must be filled"]})
|
154
139
|
end
|
155
140
|
end
|
156
141
|
end
|
157
142
|
|
158
143
|
|
159
144
|
class OverridingAccessorsTest < BaseTest
|
160
|
-
class SongForm <
|
145
|
+
class SongForm < TestForm
|
161
146
|
property :title
|
162
147
|
|
163
148
|
def title=(v) # used in #validate.
|
@@ -200,7 +185,7 @@ end
|
|
200
185
|
|
201
186
|
|
202
187
|
class MethodInFormTest < MiniTest::Spec
|
203
|
-
class AlbumForm <
|
188
|
+
class AlbumForm < TestForm
|
204
189
|
property :title
|
205
190
|
|
206
191
|
def title
|