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,104 +0,0 @@
1
- en:
2
- dry_validation:
3
- errors:
4
- array?: "must be an array"
5
-
6
- empty?: "must be empty"
7
-
8
- excludes?: "must not include %{value}"
9
-
10
- excluded_from?:
11
- arg:
12
- default: "must not be one of: %{list}"
13
- range: "must not be one of: %{list_left} - %{list_right}"
14
-
15
- eql?: "must be equal to %{left}"
16
-
17
- not_eql?: "must not be equal to %{left}"
18
-
19
- filled?: "must be filled"
20
-
21
- format?: "is in invalid format"
22
-
23
- number?: "must be a number"
24
-
25
- odd?: "must be odd"
26
-
27
- even?: "must be even"
28
-
29
- gt?: "must be greater than %{num}"
30
-
31
- gteq?: "must be greater than or equal to %{num}"
32
-
33
- hash?: "must be a hash"
34
-
35
- included_in?:
36
- arg:
37
- default: "must be one of: %{list}"
38
- range: "must be one of: %{list_left} - %{list_right}"
39
-
40
- includes?: "must include %{value}"
41
-
42
- bool?: "must be boolean"
43
-
44
- true?: "must be true"
45
-
46
- false?: "must be false"
47
-
48
- int?: "must be an integer"
49
-
50
- float?: "must be a float"
51
-
52
- decimal?: "must be a decimal"
53
-
54
- date?: "must be a date"
55
-
56
- date_time?: "must be a date time"
57
-
58
- time?: "must be a time"
59
-
60
- key?: "is missing"
61
-
62
- attr?: "is missing"
63
-
64
- lt?: "must be less than %{num}"
65
-
66
- lteq?: "must be less than or equal to %{num}"
67
-
68
- max_size?: "size cannot be greater than %{num}"
69
-
70
- min_size?: "size cannot be less than %{num}"
71
-
72
- none?: "cannot be defined"
73
-
74
- str?: "must be a string"
75
-
76
- type?: "must be %{type}"
77
-
78
- size?:
79
- arg:
80
- default: "size must be %{size}"
81
- range: "size must be within %{size_left} - %{size_right}"
82
-
83
- value:
84
- string:
85
- arg:
86
- default: "length must be %{size}"
87
- range: "length must be within %{size_left} - %{size_right}"
88
-
89
-
90
-
91
- rules:
92
- name:
93
- good_musical_taste?: "you're a bad person"
94
- title:
95
- good_musical_taste?: "you're a bad person"
96
- songs:
97
- a_song?: "must have at least one enabled song"
98
- artist:
99
- with_last_name?: "must have last name"
100
-
101
- de:
102
- dry_validation:
103
- errors:
104
- filled?: "muss abgefüllt sein"
data/test/form_old_api.rb DELETED
@@ -1,57 +0,0 @@
1
- require "test_helper"
2
-
3
- class FormTest < MiniTest::Spec
4
- Artist = Struct.new(:name)
5
-
6
- class AlbumForm < TestForm
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
- required(:title).filled
41
- end
42
-
43
- cloned.new(OpenStruct.new).validate({})
44
- end
45
- end
46
-
47
- describe "#initialize" do
48
- class ArtistForm < TestForm
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
@@ -1,24 +0,0 @@
1
- require "test_helper"
2
-
3
- class FormOptionTest < MiniTest::Spec
4
- Song = Struct.new(:title)
5
- Album = Struct.new(:song)
6
-
7
- class SongForm < TestForm
8
- property :title
9
- validation do
10
- required(:title).filled
11
- end
12
- end
13
-
14
- class AlbumForm < TestForm
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
@@ -1,105 +0,0 @@
1
- require "test_helper"
2
- require "representable/json"
3
-
4
- class InheritTest < BaseTest
5
- Populator = Reform::Form::Populator
6
-
7
- class SkipParse
8
- include Uber::Callable
9
- def call(*_args)
10
- false
11
- end
12
- end
13
-
14
- class AlbumForm < TestForm
15
- property :title, deserializer: {instance: "Instance"}, skip_if: "skip_if in AlbumForm" # allow direct configuration of :deserializer.
16
-
17
- property :hit, populate_if_empty: ->(*) { Song.new } do
18
- property :title
19
- validation do
20
- required(:title).filled
21
- end
22
- end
23
-
24
- collection :songs, populate_if_empty: -> {}, skip_if: :all_blank do
25
- property :title
26
- end
27
-
28
- property :band, populate_if_empty: -> {} do
29
- def band_id
30
- 1
31
- end
32
- end
33
- end
34
-
35
- class CompilationForm < AlbumForm
36
- property :title, inherit: true, skip_if: "skip_if from CompilationForm"
37
- property :hit, inherit: true, populate_if_empty: ->(*) { Song.new }, skip_if: SkipParse.new do
38
- property :rating
39
- validation do
40
- required(:rating).filled
41
- end
42
- end
43
-
44
- # NO collection here, this is entirely inherited.
45
-
46
- property :band, inherit: true do # inherit everything, but explicitely.
47
- end
48
- end
49
-
50
- let(:album) { Album.new(nil, Song.new, [], Band.new) }
51
- subject { CompilationForm.new(album) }
52
-
53
- it do
54
- subject.validate("hit" => {"title" => "LA Drone", "rating" => 10})
55
- _(subject.hit.title).must_equal "LA Drone"
56
- _(subject.hit.rating).must_equal 10
57
- _(subject.errors.messages).must_equal({})
58
- end
59
-
60
- it do
61
- subject.validate({})
62
- assert_nil subject.model.hit.title
63
- assert_nil subject.model.hit.rating
64
- _(subject.errors.messages).must_equal("hit.title": ["must be filled"], "hit.rating": ["must be filled"])
65
- end
66
-
67
- it "xxx" do
68
- # sub hashes like :deserializer must be properly cloned when inheriting.
69
- _(AlbumForm.options_for(:title)[:deserializer].object_id).wont_equal CompilationForm.options_for(:title)[:deserializer].object_id
70
-
71
- # don't overwrite direct deserializer: {} configuration.
72
- _(AlbumForm.options_for(:title)[:internal_populator]).must_be_instance_of Reform::Form::Populator::Sync
73
- _(AlbumForm.options_for(:title)[:deserializer][:skip_parse]).must_equal "skip_if in AlbumForm"
74
-
75
- # AlbumForm.options_for(:hit)[:internal_populator].inspect.must_match /Reform::Form::Populator:.+ @user_proc="Populator"/
76
- # AlbumForm.options_for(:hit)[:deserializer][:instance].inspect.must_be_instance_with Reform::Form::Populator, user_proc: "Populator"
77
-
78
- _(AlbumForm.options_for(:songs)[:internal_populator]).must_be_instance_of Reform::Form::Populator::IfEmpty
79
- _(AlbumForm.options_for(:songs)[:deserializer][:skip_parse]).must_be_instance_of Reform::Form::Validate::Skip::AllBlank
80
-
81
- _(AlbumForm.options_for(:band)[:internal_populator]).must_be_instance_of Reform::Form::Populator::IfEmpty
82
-
83
- _(CompilationForm.options_for(:title)[:deserializer][:skip_parse]).must_equal "skip_if from CompilationForm"
84
- # pp CompilationForm.options_for(:songs)
85
- _(CompilationForm.options_for(:songs)[:internal_populator]).must_be_instance_of Reform::Form::Populator::IfEmpty
86
-
87
- _(CompilationForm.options_for(:band)[:internal_populator]).must_be_instance_of Reform::Form::Populator::IfEmpty
88
-
89
- # completely overwrite inherited.
90
- _(CompilationForm.options_for(:hit)[:deserializer][:skip_parse]).must_be_instance_of SkipParse
91
-
92
- # inherit: true with block will still inherit the original class.
93
- _(AlbumForm.new(OpenStruct.new(band: OpenStruct.new)).band.band_id).must_equal 1
94
- _(CompilationForm.new(OpenStruct.new(band: OpenStruct.new)).band.band_id).must_equal 1
95
- end
96
-
97
- class CDForm < AlbumForm
98
- # override :band's original populate_if_empty but with :inherit.
99
- property :band, inherit: true, populator: "CD Populator" do
100
-
101
- end
102
- end
103
-
104
- it { _(CDForm.options_for(:band)[:internal_populator].instance_variable_get(:@user_proc)).must_equal "CD Populator" }
105
- end
@@ -1,146 +0,0 @@
1
- require "test_helper"
2
- require "reform/form/coercion"
3
-
4
- class ModuleInclusionTest < MiniTest::Spec
5
- module BandPropertyForm
6
- include Reform::Form::Module
7
-
8
- property :artist
9
- property :band do
10
- property :title
11
-
12
- validation do
13
- required(:title).filled
14
- end
15
-
16
- def id # gets mixed into Form, too.
17
- 2
18
- end
19
- end
20
-
21
- def id # gets mixed into Form, too.
22
- 1
23
- end
24
-
25
- validation do
26
- required(:band).filled
27
- end
28
-
29
- include Dry::Types.module # allows using Types::* in module.
30
- property :cool, type: DRY_TYPES_CONSTANT::Bool # test coercion.
31
-
32
- module InstanceMethods
33
- def artist=(new_value)
34
- errors.add(:artist, "this needs to be filled") if new_value.nil?
35
- super(new_value)
36
- end
37
- end
38
- end
39
-
40
- # TODO: test if works, move stuff into inherit_schema!
41
- module AirplaysPropertyForm
42
- include Reform::Form::Module
43
-
44
- collection :airplays do
45
- property :station
46
- validation do
47
- required(:station).filled
48
- end
49
- end
50
- validation do
51
- required(:airplays).filled
52
- end
53
- end
54
-
55
- # test:
56
- # by including BandPropertyForm into multiple classes we assure that options hashes don't get messed up by AM:V.
57
- class HitForm < TestForm
58
- include BandPropertyForm
59
- end
60
-
61
- class SongForm < TestForm
62
- include Coercion
63
- property :title
64
-
65
- include BandPropertyForm
66
- end
67
-
68
- let(:song) { OpenStruct.new(band: OpenStruct.new(title: "Time Again"), artist: "Ketama") }
69
-
70
- # nested form from module is present and creates accessor.
71
- it { _(SongForm.new(song).band.title).must_equal "Time Again" }
72
- it { _(SongForm.new(song).artist).must_equal "Ketama" }
73
-
74
- # methods from module get included.
75
- it { _(SongForm.new(song).id).must_equal 1 }
76
- it { _(SongForm.new(song).band.id).must_equal 2 }
77
-
78
- # validators get inherited.
79
- it do
80
- form = SongForm.new(OpenStruct.new)
81
- form.validate(artist: nil)
82
- _(form.errors.messages).must_equal(artist: ["this needs to be filled"], band: ["must be filled"])
83
- end
84
-
85
- # coercion works
86
- it do
87
- form = SongForm.new(OpenStruct.new)
88
- form.validate({cool: "1"})
89
- _(form.cool).must_equal true
90
- end
91
-
92
- # include a module into a module into a class :)
93
- module AlbumFormModule
94
- include Reform::Form::Module
95
- include BandPropertyForm
96
-
97
- property :name
98
- validation do
99
- required(:name).filled
100
- end
101
- end
102
-
103
- class AlbumForm < TestForm
104
- include AlbumFormModule
105
-
106
- # pp heritage
107
- property :band, inherit: true do
108
- property :label
109
- validation do
110
- required(:label).filled
111
- end
112
- end
113
- end
114
-
115
- it do
116
- form = AlbumForm.new(OpenStruct.new(band: OpenStruct.new))
117
- form.validate("band" => {})
118
- _(form.errors.messages).must_equal("band.title": ["must be filled"], "band.label": ["must be filled"], name: ["must be filled"])
119
- end
120
-
121
- describe "module with custom accessors" do
122
- module SongModule
123
- include Reform::Form::Module
124
-
125
- property :id # no custom accessor for id.
126
- property :title # has custom accessor.
127
-
128
- module InstanceMethods
129
- def title
130
- super.upcase
131
- end
132
- end
133
- end
134
-
135
- class IncludingSongForm < TestForm
136
- include SongModule
137
- end
138
-
139
- let(:song) { OpenStruct.new(id: 1, title: "Instant Mash") }
140
-
141
- it do
142
- _(IncludingSongForm.new(song).id).must_equal 1
143
- _(IncludingSongForm.new(song).title).must_equal "INSTANT MASH"
144
- end
145
- end
146
- end
@@ -1,304 +0,0 @@
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
- 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
- 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
- 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
- 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
- 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
- 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