reform 2.2.4
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 +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +11 -0
- data/CHANGES.md +415 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +339 -0
- data/Rakefile +15 -0
- data/TODO.md +45 -0
- data/gemfiles/Gemfile.disposable-0.3 +6 -0
- data/lib/reform.rb +8 -0
- data/lib/reform/contract.rb +77 -0
- data/lib/reform/contract/errors.rb +43 -0
- data/lib/reform/contract/validate.rb +33 -0
- data/lib/reform/form.rb +94 -0
- data/lib/reform/form/call.rb +23 -0
- data/lib/reform/form/coercion.rb +3 -0
- data/lib/reform/form/composition.rb +34 -0
- data/lib/reform/form/dry.rb +67 -0
- data/lib/reform/form/module.rb +27 -0
- data/lib/reform/form/mongoid.rb +37 -0
- data/lib/reform/form/orm.rb +26 -0
- data/lib/reform/form/populator.rb +123 -0
- data/lib/reform/form/prepopulate.rb +24 -0
- data/lib/reform/form/validate.rb +60 -0
- data/lib/reform/mongoid.rb +4 -0
- data/lib/reform/validation.rb +40 -0
- data/lib/reform/validation/groups.rb +73 -0
- data/lib/reform/version.rb +3 -0
- data/reform.gemspec +29 -0
- data/test/benchmarking.rb +26 -0
- data/test/call_test.rb +23 -0
- data/test/changed_test.rb +41 -0
- data/test/coercion_test.rb +66 -0
- data/test/composition_test.rb +149 -0
- data/test/contract_test.rb +77 -0
- data/test/default_test.rb +22 -0
- data/test/deprecation_test.rb +27 -0
- data/test/deserialize_test.rb +104 -0
- data/test/errors_test.rb +165 -0
- data/test/feature_test.rb +65 -0
- data/test/fixtures/dry_error_messages.yml +44 -0
- data/test/form_option_test.rb +24 -0
- data/test/form_test.rb +57 -0
- data/test/from_test.rb +75 -0
- data/test/inherit_test.rb +119 -0
- data/test/module_test.rb +142 -0
- data/test/parse_pipeline_test.rb +15 -0
- data/test/populate_test.rb +270 -0
- data/test/populator_skip_test.rb +28 -0
- data/test/prepopulator_test.rb +112 -0
- data/test/read_only_test.rb +3 -0
- data/test/readable_test.rb +30 -0
- data/test/readonly_test.rb +14 -0
- data/test/reform_test.rb +223 -0
- data/test/save_test.rb +89 -0
- data/test/setup_test.rb +48 -0
- data/test/skip_if_test.rb +74 -0
- data/test/skip_setter_and_getter_test.rb +54 -0
- data/test/test_helper.rb +49 -0
- data/test/validate_test.rb +420 -0
- data/test/validation/dry_test.rb +60 -0
- data/test/validation/dry_validation_test.rb +352 -0
- data/test/validation/errors.yml +4 -0
- data/test/virtual_test.rb +24 -0
- data/test/writeable_test.rb +29 -0
- metadata +265 -0
data/test/errors_test.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ErrorsTest < MiniTest::Spec
|
4
|
+
class AlbumForm < Reform::Form
|
5
|
+
property :title
|
6
|
+
|
7
|
+
property :hit do
|
8
|
+
property :title
|
9
|
+
validation do
|
10
|
+
required(:title).filled
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
collection :songs do
|
15
|
+
property :title
|
16
|
+
validation do
|
17
|
+
required(:title).filled
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
property :band do # yepp, people do crazy stuff like that.
|
22
|
+
property :name
|
23
|
+
property :label do
|
24
|
+
property :name
|
25
|
+
validation do
|
26
|
+
required(:name).filled
|
27
|
+
end
|
28
|
+
end
|
29
|
+
# TODO: make band a required object.
|
30
|
+
|
31
|
+
validation do
|
32
|
+
# required(:name).filled(:music_taste_ok?)
|
33
|
+
|
34
|
+
configure do
|
35
|
+
config.messages_file = "test/validation/errors.yml"
|
36
|
+
|
37
|
+
def music_taste_ok?(value)
|
38
|
+
value != "Nickelback"
|
39
|
+
# errors.add(:base, "You are a bad person") if name == "Nickelback"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# validate :music_taste_ok?
|
44
|
+
|
45
|
+
# private
|
46
|
+
# def music_taste_ok?
|
47
|
+
# errors.add(:base, "You are a bad person") if name == "Nickelback"
|
48
|
+
# end
|
49
|
+
end
|
50
|
+
|
51
|
+
validation do
|
52
|
+
required(:title).filled
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
let (:album) do
|
57
|
+
OpenStruct.new(
|
58
|
+
:title => "Blackhawks Over Los Angeles",
|
59
|
+
:hit => song,
|
60
|
+
:songs => songs, # TODO: document this requirement,
|
61
|
+
|
62
|
+
:band => Struct.new(:name, :label).new("Epitaph", OpenStruct.new),
|
63
|
+
)
|
64
|
+
end
|
65
|
+
let (:song) { OpenStruct.new(:title => "Downtown") }
|
66
|
+
let (:songs) { [song=OpenStruct.new(:title => "Calling"), song] }
|
67
|
+
let (:form) { AlbumForm.new(album) }
|
68
|
+
|
69
|
+
|
70
|
+
describe "incorrect #validate" do
|
71
|
+
before { form.validate(
|
72
|
+
"hit" =>{"title" => ""},
|
73
|
+
"title" => "",
|
74
|
+
"songs" => [{"title" => ""}, {"title" => ""}]) } # FIXME: what happens if item is missing?
|
75
|
+
|
76
|
+
it do
|
77
|
+
form.errors.messages.must_equal({
|
78
|
+
:title => ["must be filled"],
|
79
|
+
:"hit.title"=>["must be filled"],
|
80
|
+
:"songs.title"=>["must be filled"],
|
81
|
+
:"band.label.name"=>["is missing"]
|
82
|
+
})
|
83
|
+
end
|
84
|
+
|
85
|
+
it do
|
86
|
+
#form.errors.must_equal({:title => ["must be filled"]})
|
87
|
+
# TODO: this should only contain local errors?
|
88
|
+
end
|
89
|
+
|
90
|
+
# nested forms keep their own Errors:
|
91
|
+
it { form.hit.errors.messages.must_equal({:title=>["must be filled"]}) }
|
92
|
+
it { form.songs[0].errors.messages.must_equal({:title=>["must be filled"]}) }
|
93
|
+
|
94
|
+
it do
|
95
|
+
form.errors.messages.must_equal({
|
96
|
+
:title => ["must be filled"],
|
97
|
+
:"hit.title" => ["must be filled"],
|
98
|
+
:"songs.title"=> ["must be filled"],
|
99
|
+
:"band.label.name"=>["is missing"]
|
100
|
+
})
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
describe "#validate with main form invalid" do
|
106
|
+
it do
|
107
|
+
form.validate("title"=>"", "band"=>{"label"=>{:name => "Fat Wreck"}}).must_equal false
|
108
|
+
form.errors.messages.must_equal({:title=>["must be filled"]})
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
describe "#validate with middle nested form invalid" do
|
114
|
+
before { @result = form.validate("hit"=>{"title" => ""}, "band"=>{"label"=>{:name => "Fat Wreck"}}) }
|
115
|
+
|
116
|
+
it { @result.must_equal false }
|
117
|
+
it { form.errors.messages.must_equal({:"hit.title"=>["must be filled"]}) }
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
describe "#validate with collection form invalid" do
|
122
|
+
before { @result = form.validate("songs"=>[{"title" => ""}], "band"=>{"label"=>{:name => "Fat Wreck"}}) }
|
123
|
+
|
124
|
+
it { @result.must_equal false }
|
125
|
+
it { form.errors.messages.must_equal({:"songs.title"=>["must be filled"]}) }
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
describe "#validate with collection and 2-level-nested invalid" do
|
130
|
+
before { @result = form.validate("songs"=>[{"title" => ""}], "band" => {"label" => {}}) }
|
131
|
+
|
132
|
+
it { @result.must_equal false }
|
133
|
+
it { form.errors.messages.must_equal({:"songs.title"=>["must be filled"], :"band.label.name"=>["is missing"]}) }
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "#validate with nested form using :base invalid" do
|
137
|
+
it do
|
138
|
+
result = form.validate("songs"=>[{"title" => "Someday"}], "band" => {"name" => "Nickelback", "label" => {"name" => "Roadrunner Records"}})
|
139
|
+
result.must_equal false
|
140
|
+
form.errors.messages.must_equal({:"band.name"=>["You are a bad person"]})
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "correct #validate" do
|
145
|
+
before { @result = form.validate(
|
146
|
+
"hit" => {"title" => "Sacrifice"},
|
147
|
+
"title" => "Second Heat",
|
148
|
+
"songs" => [{"title"=>"Heart Of A Lion"}],
|
149
|
+
"band" => {"label"=>{:name => "Fat Wreck"}}
|
150
|
+
) }
|
151
|
+
|
152
|
+
it { @result.must_equal true }
|
153
|
+
it { form.hit.title.must_equal "Sacrifice" }
|
154
|
+
it { form.title.must_equal "Second Heat" }
|
155
|
+
it { form.songs.first.title.must_equal "Heart Of A Lion" }
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
describe "Errors#to_s" do
|
160
|
+
before { form.validate("songs"=>[{"title" => ""}], "band" => {"label" => {}}) }
|
161
|
+
|
162
|
+
# to_s is aliased to messages
|
163
|
+
it { form.errors.to_s.must_equal "{:\"songs.title\"=>[\"must be filled\"], :\"band.label.name\"=>[\"is missing\"]}" }
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FeatureInheritanceTest < BaseTest
|
4
|
+
Song = Struct.new(:title, :album, :composer)
|
5
|
+
Album = Struct.new(:name, :songs, :artist)
|
6
|
+
Artist = Struct.new(:name)
|
7
|
+
|
8
|
+
module Date
|
9
|
+
def date
|
10
|
+
"May 16"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(includer)
|
14
|
+
includer.send :register_feature, self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# module Name
|
19
|
+
# def name
|
20
|
+
# "Violins"
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
|
24
|
+
class AlbumForm < Reform::Form
|
25
|
+
feature Date # feature.
|
26
|
+
property :name
|
27
|
+
|
28
|
+
collection :songs do
|
29
|
+
property :title
|
30
|
+
|
31
|
+
property :composer do
|
32
|
+
property :name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
property :artist do
|
37
|
+
property :name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
let (:song) { Song.new("Broken") }
|
42
|
+
let (:song_with_composer) { Song.new("Resist Stance", nil, composer) }
|
43
|
+
let (:composer) { Artist.new("Greg Graffin") }
|
44
|
+
let (:artist) { Artist.new("Bad Religion") }
|
45
|
+
let (:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
|
46
|
+
|
47
|
+
let (:form) { AlbumForm.new(album) }
|
48
|
+
|
49
|
+
it do
|
50
|
+
form.date.must_equal "May 16"
|
51
|
+
form.songs[0].date.must_equal "May 16"
|
52
|
+
end
|
53
|
+
|
54
|
+
# it { subject.class.include?(Reform::Form::ActiveModel) }
|
55
|
+
# it { subject.class.include?(Reform::Form::Coercion) }
|
56
|
+
# it { subject.is_a?(Reform::Form::MultiParameterAttributes) }
|
57
|
+
|
58
|
+
# it { subject.band.class.include?(Reform::Form::ActiveModel) }
|
59
|
+
# it { subject.band.is_a?(Reform::Form::Coercion) }
|
60
|
+
# it { subject.band.is_a?(Reform::Form::MultiParameterAttributes) }
|
61
|
+
|
62
|
+
# it { subject.band.label.is_a?(Reform::Form::ActiveModel) }
|
63
|
+
# it { subject.band.label.is_a?(Reform::Form::Coercion) }
|
64
|
+
# it { subject.band.label.is_a?(Reform::Form::MultiParameterAttributes) }
|
65
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
array?: "%{name} must be an array"
|
2
|
+
|
3
|
+
empty?: "%{name} cannot be empty"
|
4
|
+
|
5
|
+
exclusion?: "%{name} must not be one of: %{list}"
|
6
|
+
|
7
|
+
eql?: "%{name} must be equal to %{eql_value}"
|
8
|
+
|
9
|
+
filled?: "%{name} must be filled"
|
10
|
+
|
11
|
+
format?: "%{name} is in invalid format"
|
12
|
+
|
13
|
+
gt?: "%{name} must be greater than %{num} (%{value} was given)"
|
14
|
+
|
15
|
+
gteq?: "%{name} must be greater than or equal to %{num}"
|
16
|
+
|
17
|
+
hash?: "%{name} must be a hash"
|
18
|
+
|
19
|
+
inclusion?: "%{name} must be one of: %{list}"
|
20
|
+
|
21
|
+
int?: "%{name} must be an integer"
|
22
|
+
|
23
|
+
key?: "%{name} is missing"
|
24
|
+
|
25
|
+
lt?: "%{name} must be less than %{num} (%{value} was given)"
|
26
|
+
|
27
|
+
lteq?: "%{name} must be less than or equal to %{num}"
|
28
|
+
|
29
|
+
max_size?: "%{name} size cannot be greater than %{num}"
|
30
|
+
|
31
|
+
min_size?: "%{name} size cannot be less than %{num}"
|
32
|
+
|
33
|
+
nil?: "%{name} cannot be nil"
|
34
|
+
|
35
|
+
size?:
|
36
|
+
range: "%{name} size must be within %{left} - %{right}"
|
37
|
+
default: "%{name} size must be %{num}"
|
38
|
+
|
39
|
+
str?: "%{name} must be a string"
|
40
|
+
|
41
|
+
good_musical_taste?: "you're a bad person"
|
42
|
+
|
43
|
+
form_access_validation?: "this doesn't look like a Reform form dude!!"
|
44
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FormOptionTest < MiniTest::Spec
|
4
|
+
Song = Struct.new(:title)
|
5
|
+
Album = Struct.new(:song)
|
6
|
+
|
7
|
+
class SongForm < Reform::Form
|
8
|
+
property :title
|
9
|
+
validation do
|
10
|
+
key(:title).required
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class AlbumForm < Reform::Form
|
15
|
+
property :song, form: SongForm
|
16
|
+
end
|
17
|
+
|
18
|
+
it do
|
19
|
+
form = AlbumForm.new(Album.new(Song.new("When It Comes To You")))
|
20
|
+
form.song.title.must_equal "When It Comes To You"
|
21
|
+
|
22
|
+
form.validate(song: {title: "Run For Cover"})
|
23
|
+
end
|
24
|
+
end
|
data/test/form_test.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FormTest < MiniTest::Spec
|
4
|
+
Artist = Struct.new(:name)
|
5
|
+
|
6
|
+
class AlbumForm < Reform::Form
|
7
|
+
property :title
|
8
|
+
|
9
|
+
property :hit do
|
10
|
+
property :title
|
11
|
+
end
|
12
|
+
|
13
|
+
collection :songs do
|
14
|
+
property :title
|
15
|
+
end
|
16
|
+
|
17
|
+
property :band do # yepp, people do crazy stuff like that.
|
18
|
+
property :label do
|
19
|
+
property :name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "::dup" do
|
25
|
+
let (:cloned) { AlbumForm.clone }
|
26
|
+
|
27
|
+
# #dup is called in Op.inheritable_attr(:contract_class), it must be subclass of the original one.
|
28
|
+
it { cloned.wont_equal AlbumForm }
|
29
|
+
it { AlbumForm.definitions.wont_equal cloned.definitions }
|
30
|
+
|
31
|
+
it do
|
32
|
+
# currently, forms need a name for validation, even without AM.
|
33
|
+
cloned.singleton_class.class_eval do
|
34
|
+
def name
|
35
|
+
"Album"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
cloned.validation do
|
40
|
+
key(:title).required
|
41
|
+
end
|
42
|
+
|
43
|
+
cloned.new(OpenStruct.new).validate({})
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#initialize" do
|
48
|
+
class ArtistForm < Reform::Form
|
49
|
+
property :name
|
50
|
+
property :current_user, virtual: true
|
51
|
+
end
|
52
|
+
|
53
|
+
it "allows injecting :virtual options" do
|
54
|
+
ArtistForm.new(Artist.new, current_user: Object).current_user.must_equal Object
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/test/from_test.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AsTest < BaseTest
|
4
|
+
class AlbumForm < Reform::Form
|
5
|
+
property :name, from: :title
|
6
|
+
|
7
|
+
property :single, from: :hit do
|
8
|
+
property :title
|
9
|
+
end
|
10
|
+
|
11
|
+
collection :tracks, from: :songs do
|
12
|
+
property :name, from: :title
|
13
|
+
end
|
14
|
+
|
15
|
+
property :band do
|
16
|
+
property :company, from: :label do
|
17
|
+
property :business, from: :name
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
let (:song2) { Song.new("Roxanne") }
|
23
|
+
|
24
|
+
let (:params) {
|
25
|
+
{
|
26
|
+
"name" => "Best Of The Police",
|
27
|
+
"single" => {"title" => "So Lonely"},
|
28
|
+
"tracks" => [{"name" => "Message In A Bottle"}, {"name" => "Roxanne"}]
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
subject { AlbumForm.new(Album.new("Best Of", hit, [Song.new("Fallout"), song2])) }
|
33
|
+
|
34
|
+
it { subject.name.must_equal "Best Of" }
|
35
|
+
it { subject.single.title.must_equal "Roxanne" }
|
36
|
+
it { subject.tracks[0].name.must_equal "Fallout" }
|
37
|
+
it { subject.tracks[1].name.must_equal "Roxanne" }
|
38
|
+
|
39
|
+
|
40
|
+
describe "#validate" do
|
41
|
+
|
42
|
+
|
43
|
+
before { subject.validate(params) }
|
44
|
+
|
45
|
+
it { subject.name.must_equal "Best Of The Police" }
|
46
|
+
it { subject.single.title.must_equal "So Lonely" }
|
47
|
+
it { subject.tracks[0].name.must_equal "Message In A Bottle" }
|
48
|
+
it { subject.tracks[1].name.must_equal "Roxanne" }
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
describe "#sync" do
|
53
|
+
before {
|
54
|
+
subject.tracks[1].name = "Livin' Ain't No Crime"
|
55
|
+
subject.sync
|
56
|
+
}
|
57
|
+
|
58
|
+
it { song2.title.must_equal "Livin' Ain't No Crime" }
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
describe "#save (nested hash)" do
|
63
|
+
before { subject.validate(params) }
|
64
|
+
|
65
|
+
it do
|
66
|
+
hash = nil
|
67
|
+
|
68
|
+
subject.save do |nested_hash|
|
69
|
+
hash = nested_hash
|
70
|
+
end
|
71
|
+
|
72
|
+
hash.must_equal({"title"=>"Best Of The Police", "hit"=>{"title"=>"So Lonely"}, "songs"=>[{"title"=>"Message In A Bottle"}, {"title"=>"Roxanne"}]})
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'representable/json'
|
3
|
+
|
4
|
+
class InheritTest < BaseTest
|
5
|
+
Populator = Reform::Form::Populator
|
6
|
+
|
7
|
+
class AlbumForm < Reform::Form
|
8
|
+
property :title, deserializer: {instance: "Instance"}, skip_if: "skip_if in AlbumForm" # allow direct configuration of :deserializer.
|
9
|
+
|
10
|
+
property :hit, populator: "Populator" do
|
11
|
+
property :title
|
12
|
+
end
|
13
|
+
|
14
|
+
collection :songs, populate_if_empty: lambda {}, skip_if: :all_blank do
|
15
|
+
property :title
|
16
|
+
end
|
17
|
+
|
18
|
+
property :artist, populate_if_empty: lambda {} do
|
19
|
+
|
20
|
+
def artist_id
|
21
|
+
1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
puts
|
27
|
+
puts "inherit"
|
28
|
+
|
29
|
+
class CompilationForm < AlbumForm
|
30
|
+
property :title, inherit: true, skip_if: "skip_if from CompilationForm"
|
31
|
+
puts "[#{options_for(:title)[:deserializer].object_id}] COM@@@@@ #{options_for(:title)[:deserializer].inspect}"
|
32
|
+
# property :hit, :inherit => true do
|
33
|
+
# property :rating
|
34
|
+
# validates :title, :rating, :presence => true
|
35
|
+
# end
|
36
|
+
|
37
|
+
# puts representer_class.representable_attrs.
|
38
|
+
# get(:hit)[:extend].evaluate(nil).new(OpenStruct.new).rating
|
39
|
+
|
40
|
+
# NO collection here, this is entirely inherited.
|
41
|
+
# collection :songs, ..
|
42
|
+
|
43
|
+
property :artist, inherit: true do # inherit everything, but explicitely.
|
44
|
+
end
|
45
|
+
|
46
|
+
# completely override.
|
47
|
+
property :hit, skip_if: "SkipParse" do
|
48
|
+
end
|
49
|
+
|
50
|
+
# override partly.
|
51
|
+
end
|
52
|
+
|
53
|
+
let (:album) { Album.new(nil, OpenStruct.new(:hit => OpenStruct.new()) ) }
|
54
|
+
subject { CompilationForm.new(album) }
|
55
|
+
|
56
|
+
|
57
|
+
# valid.
|
58
|
+
# it {
|
59
|
+
# subject.validate("hit" => {"title" => "LA Drone", "rating" => 10})
|
60
|
+
# subject.hit.title.must_equal "LA Drone"
|
61
|
+
# subject.hit.rating.must_equal 10
|
62
|
+
# subject.errors.messages.must_equal({})
|
63
|
+
# }
|
64
|
+
|
65
|
+
# it do
|
66
|
+
# subject.validate({})
|
67
|
+
# subject.hit.title.must_equal nil
|
68
|
+
# subject.hit.rating.must_equal nil
|
69
|
+
# subject.errors.messages.must_equal({:"hit.title"=>["can't be blank"], :"hit.rating"=>["can't be blank"]})
|
70
|
+
# end
|
71
|
+
|
72
|
+
require "pp"
|
73
|
+
|
74
|
+
it "xxx" do
|
75
|
+
# sub hashes like :deserializer must be properly cloned when inheriting.
|
76
|
+
AlbumForm.options_for(:title)[:deserializer].object_id.wont_equal CompilationForm.options_for(:title)[:deserializer].object_id
|
77
|
+
|
78
|
+
# don't overwrite direct deserializer: {} configuration.
|
79
|
+
AlbumForm.options_for(:title)[:internal_populator].must_be_instance_of Reform::Form::Populator::Sync
|
80
|
+
AlbumForm.options_for(:title)[:deserializer][:skip_parse].must_equal "skip_if in AlbumForm"
|
81
|
+
|
82
|
+
AlbumForm.options_for(:hit)[:internal_populator].inspect.must_match /Reform::Form::Populator:.+ @user_proc="Populator"/
|
83
|
+
# AlbumForm.options_for(:hit)[:deserializer][:instance].inspect.must_be_instance_with Reform::Form::Populator, user_proc: "Populator"
|
84
|
+
|
85
|
+
|
86
|
+
AlbumForm.options_for(:songs)[:internal_populator].must_be_instance_of Reform::Form::Populator::IfEmpty
|
87
|
+
AlbumForm.options_for(:songs)[:deserializer][:skip_parse].must_be_instance_of Reform::Form::Validate::Skip::AllBlank
|
88
|
+
|
89
|
+
AlbumForm.options_for(:artist)[:internal_populator].must_be_instance_of Reform::Form::Populator::IfEmpty
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
CompilationForm.options_for(:title)[:deserializer][:skip_parse].must_equal "skip_if from CompilationForm"
|
94
|
+
# pp CompilationForm.options_for(:songs)
|
95
|
+
CompilationForm.options_for(:songs)[:internal_populator].must_be_instance_of Reform::Form::Populator::IfEmpty
|
96
|
+
|
97
|
+
|
98
|
+
CompilationForm.options_for(:artist)[:internal_populator].must_be_instance_of Reform::Form::Populator::IfEmpty
|
99
|
+
|
100
|
+
# completely overwrite inherited.
|
101
|
+
CompilationForm.options_for(:hit)[:internal_populator].must_be_instance_of Reform::Form::Populator::Sync # reset to default.
|
102
|
+
CompilationForm.options_for(:hit)[:deserializer][:skip_parse].must_equal "SkipParse"
|
103
|
+
|
104
|
+
|
105
|
+
# inherit: true with block will still inherit the original class.
|
106
|
+
AlbumForm.new(OpenStruct.new(artist: OpenStruct.new)).artist.artist_id.must_equal 1
|
107
|
+
CompilationForm.new(OpenStruct.new(artist: OpenStruct.new)).artist.artist_id.must_equal 1
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
class CDForm < AlbumForm
|
112
|
+
# override :artist's original populate_if_empty but with :inherit.
|
113
|
+
property :artist, inherit: true, populator: "CD Populator" do
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it { CDForm.options_for(:artist)[:internal_populator].instance_variable_get(:@user_proc).must_equal "CD Populator" }
|
119
|
+
end
|