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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +30 -0
  4. data/.rubocop_todo.yml +460 -0
  5. data/.travis.yml +26 -11
  6. data/CHANGES.md +25 -2
  7. data/Gemfile +6 -3
  8. data/ISSUE_TEMPLATE.md +1 -1
  9. data/README.md +2 -4
  10. data/Rakefile +18 -9
  11. data/lib/reform/contract.rb +7 -7
  12. data/lib/reform/contract/custom_error.rb +41 -0
  13. data/lib/reform/contract/validate.rb +9 -5
  14. data/lib/reform/errors.rb +27 -15
  15. data/lib/reform/form.rb +22 -11
  16. data/lib/reform/form/call.rb +1 -1
  17. data/lib/reform/form/composition.rb +2 -2
  18. data/lib/reform/form/dry.rb +10 -86
  19. data/lib/reform/form/dry/input_hash.rb +37 -0
  20. data/lib/reform/form/dry/new_api.rb +58 -0
  21. data/lib/reform/form/dry/old_api.rb +61 -0
  22. data/lib/reform/form/populator.rb +9 -11
  23. data/lib/reform/form/prepopulate.rb +3 -2
  24. data/lib/reform/form/validate.rb +19 -12
  25. data/lib/reform/result.rb +36 -9
  26. data/lib/reform/validation.rb +10 -8
  27. data/lib/reform/validation/groups.rb +2 -3
  28. data/lib/reform/version.rb +1 -1
  29. data/reform.gemspec +10 -9
  30. data/test/benchmarking.rb +10 -11
  31. data/test/call_new_api.rb +23 -0
  32. data/test/{call_test.rb → call_old_api.rb} +3 -3
  33. data/test/changed_test.rb +7 -7
  34. data/test/coercion_test.rb +50 -18
  35. data/test/composition_new_api.rb +186 -0
  36. data/test/{composition_test.rb → composition_old_api.rb} +23 -26
  37. data/test/contract/custom_error_test.rb +55 -0
  38. data/test/contract_new_api.rb +77 -0
  39. data/test/{contract_test.rb → contract_old_api.rb} +8 -8
  40. data/test/default_test.rb +1 -1
  41. data/test/deserialize_test.rb +8 -11
  42. data/test/errors_new_api.rb +225 -0
  43. data/test/errors_old_api.rb +230 -0
  44. data/test/feature_test.rb +7 -9
  45. data/test/fixtures/dry_error_messages.yml +5 -2
  46. data/test/fixtures/dry_new_api_error_messages.yml +104 -0
  47. data/test/form_new_api.rb +57 -0
  48. data/test/{form_test.rb → form_old_api.rb} +2 -2
  49. data/test/form_option_new_api.rb +24 -0
  50. data/test/{form_option_test.rb → form_option_old_api.rb} +1 -1
  51. data/test/from_test.rb +8 -12
  52. data/test/inherit_new_api.rb +105 -0
  53. data/test/{inherit_test.rb → inherit_old_api.rb} +10 -17
  54. data/test/module_new_api.rb +137 -0
  55. data/test/{module_test.rb → module_old_api.rb} +19 -15
  56. data/test/parse_option_test.rb +5 -5
  57. data/test/parse_pipeline_test.rb +2 -2
  58. data/test/populate_new_api.rb +304 -0
  59. data/test/{populate_test.rb → populate_old_api.rb} +28 -34
  60. data/test/populator_skip_test.rb +1 -2
  61. data/test/prepopulator_test.rb +5 -6
  62. data/test/read_only_test.rb +12 -1
  63. data/test/readable_test.rb +5 -5
  64. data/test/reform_new_api.rb +204 -0
  65. data/test/{reform_test.rb → reform_old_api.rb} +17 -23
  66. data/test/save_new_api.rb +101 -0
  67. data/test/{save_test.rb → save_old_api.rb} +10 -13
  68. data/test/setup_test.rb +6 -6
  69. data/test/{skip_if_test.rb → skip_if_new_api.rb} +20 -9
  70. data/test/skip_if_old_api.rb +92 -0
  71. data/test/skip_setter_and_getter_test.rb +2 -3
  72. data/test/test_helper.rb +13 -5
  73. data/test/validate_new_api.rb +408 -0
  74. data/test/{validate_test.rb → validate_old_api.rb} +43 -53
  75. data/test/validation/dry_validation_new_api.rb +826 -0
  76. data/test/validation/{dry_validation_test.rb → dry_validation_old_api.rb} +223 -116
  77. data/test/validation/result_test.rb +20 -22
  78. data/test/validation_library_provided_test.rb +3 -3
  79. data/test/virtual_test.rb +46 -6
  80. data/test/writeable_test.rb +7 -7
  81. metadata +101 -51
  82. data/test/errors_test.rb +0 -180
  83. data/test/readonly_test.rb +0 -14
@@ -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 < TestForm
8
+ property :title
9
+ validation do
10
+ params { 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,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class FormOptionTest < MiniTest::Spec
4
4
  Song = Struct.new(:title)
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class AsTest < BaseTest
4
4
  class AlbumForm < TestForm
@@ -19,15 +19,15 @@ class AsTest < BaseTest
19
19
  end
20
20
  end
21
21
 
22
- let (:song2) { Song.new("Roxanne") }
22
+ let(:song2) { Song.new("Roxanne") }
23
23
 
24
- let (:params) {
24
+ let(:params) do
25
25
  {
26
26
  "name" => "Best Of The Police",
27
- "single" => {"title" => "So Lonely"},
27
+ "single" => {"title" => "So Lonely"},
28
28
  "tracks" => [{"name" => "Message In A Bottle"}, {"name" => "Roxanne"}]
29
29
  }
30
- }
30
+ end
31
31
 
32
32
  subject { AlbumForm.new(Album.new("Best Of", hit, [Song.new("Fallout"), song2])) }
33
33
 
@@ -36,10 +36,8 @@ class AsTest < BaseTest
36
36
  it { subject.tracks[0].name.must_equal "Fallout" }
37
37
  it { subject.tracks[1].name.must_equal "Roxanne" }
38
38
 
39
-
40
39
  describe "#validate" do
41
40
 
42
-
43
41
  before { subject.validate(params) }
44
42
 
45
43
  it { subject.name.must_equal "Best Of The Police" }
@@ -48,17 +46,15 @@ class AsTest < BaseTest
48
46
  it { subject.tracks[1].name.must_equal "Roxanne" }
49
47
  end
50
48
 
51
-
52
49
  describe "#sync" do
53
- before {
50
+ before do
54
51
  subject.tracks[1].name = "Livin' Ain't No Crime"
55
52
  subject.sync
56
- }
53
+ end
57
54
 
58
55
  it { song2.title.must_equal "Livin' Ain't No Crime" }
59
56
  end
60
57
 
61
-
62
58
  describe "#save (nested hash)" do
63
59
  before { subject.validate(params) }
64
60
 
@@ -69,7 +65,7 @@ class AsTest < BaseTest
69
65
  hash = nested_hash
70
66
  end
71
67
 
72
- hash.must_equal({"title"=>"Best Of The Police", "hit"=>{"title"=>"So Lonely"}, "songs"=>[{"title"=>"Message In A Bottle"}, {"title"=>"Roxanne"}], "band"=> nil})
68
+ hash.must_equal({"title" => "Best Of The Police", "hit" => {"title" => "So Lonely"}, "songs" => [{"title" => "Message In A Bottle"}, {"title" => "Roxanne"}], "band" => nil})
73
69
  end
74
70
  end
75
71
  end
@@ -0,0 +1,105 @@
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
+ params { 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
+ params { 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,12 +1,12 @@
1
- require 'test_helper'
2
- require 'representable/json'
1
+ require "test_helper"
2
+ require "representable/json"
3
3
 
4
4
  class InheritTest < BaseTest
5
5
  Populator = Reform::Form::Populator
6
6
 
7
7
  class SkipParse
8
8
  include Uber::Callable
9
- def call(*args)
9
+ def call(*_args)
10
10
  false
11
11
  end
12
12
  end
@@ -14,19 +14,18 @@ class InheritTest < BaseTest
14
14
  class AlbumForm < TestForm
15
15
  property :title, deserializer: {instance: "Instance"}, skip_if: "skip_if in AlbumForm" # allow direct configuration of :deserializer.
16
16
 
17
- property :hit, populate_if_empty: -> (*) { Song.new } do
17
+ property :hit, populate_if_empty: ->(*) { Song.new } do
18
18
  property :title
19
19
  validation do
20
20
  required(:title).filled
21
21
  end
22
22
  end
23
23
 
24
- collection :songs, populate_if_empty: lambda {}, skip_if: :all_blank do
24
+ collection :songs, populate_if_empty: -> {}, skip_if: :all_blank do
25
25
  property :title
26
26
  end
27
27
 
28
- property :band, populate_if_empty: lambda {} do
29
-
28
+ property :band, populate_if_empty: -> {} do
30
29
  def band_id
31
30
  1
32
31
  end
@@ -35,7 +34,7 @@ class InheritTest < BaseTest
35
34
 
36
35
  class CompilationForm < AlbumForm
37
36
  property :title, inherit: true, skip_if: "skip_if from CompilationForm"
38
- property :hit, :inherit => true, populate_if_empty: -> (*) { Song.new }, skip_if: SkipParse.new do
37
+ property :hit, inherit: true, populate_if_empty: ->(*) { Song.new }, skip_if: SkipParse.new do
39
38
  property :rating
40
39
  validation do
41
40
  required(:rating).filled
@@ -48,11 +47,11 @@ class InheritTest < BaseTest
48
47
  end
49
48
  end
50
49
 
51
- let (:album) { Album.new(nil, Song.new, [], Band.new) }
50
+ let(:album) { Album.new(nil, Song.new, [], Band.new) }
52
51
  subject { CompilationForm.new(album) }
53
52
 
54
53
  it do
55
- subject.validate({"hit" => {"title" => "LA Drone", "rating" => 10}})
54
+ subject.validate("hit" => {"title" => "LA Drone", "rating" => 10})
56
55
  subject.hit.title.must_equal "LA Drone"
57
56
  subject.hit.rating.must_equal 10
58
57
  subject.errors.messages.must_equal({})
@@ -62,7 +61,7 @@ class InheritTest < BaseTest
62
61
  subject.validate({})
63
62
  assert_nil subject.model.hit.title
64
63
  assert_nil subject.model.hit.rating
65
- subject.errors.messages.must_equal({:"hit.title"=>["must be filled"], :"hit.rating"=>["must be filled"]})
64
+ subject.errors.messages.must_equal("hit.title": ["must be filled"], "hit.rating": ["must be filled"])
66
65
  end
67
66
 
68
67
  it "xxx" do
@@ -76,31 +75,25 @@ class InheritTest < BaseTest
76
75
  # AlbumForm.options_for(:hit)[:internal_populator].inspect.must_match /Reform::Form::Populator:.+ @user_proc="Populator"/
77
76
  # AlbumForm.options_for(:hit)[:deserializer][:instance].inspect.must_be_instance_with Reform::Form::Populator, user_proc: "Populator"
78
77
 
79
-
80
78
  AlbumForm.options_for(:songs)[:internal_populator].must_be_instance_of Reform::Form::Populator::IfEmpty
81
79
  AlbumForm.options_for(:songs)[:deserializer][:skip_parse].must_be_instance_of Reform::Form::Validate::Skip::AllBlank
82
80
 
83
81
  AlbumForm.options_for(:band)[:internal_populator].must_be_instance_of Reform::Form::Populator::IfEmpty
84
82
 
85
-
86
-
87
83
  CompilationForm.options_for(:title)[:deserializer][:skip_parse].must_equal "skip_if from CompilationForm"
88
84
  # pp CompilationForm.options_for(:songs)
89
85
  CompilationForm.options_for(:songs)[:internal_populator].must_be_instance_of Reform::Form::Populator::IfEmpty
90
86
 
91
-
92
87
  CompilationForm.options_for(:band)[:internal_populator].must_be_instance_of Reform::Form::Populator::IfEmpty
93
88
 
94
89
  # completely overwrite inherited.
95
90
  CompilationForm.options_for(:hit)[:deserializer][:skip_parse].must_be_instance_of SkipParse
96
91
 
97
-
98
92
  # inherit: true with block will still inherit the original class.
99
93
  AlbumForm.new(OpenStruct.new(band: OpenStruct.new)).band.band_id.must_equal 1
100
94
  CompilationForm.new(OpenStruct.new(band: OpenStruct.new)).band.band_id.must_equal 1
101
95
  end
102
96
 
103
-
104
97
  class CDForm < AlbumForm
105
98
  # override :band's original populate_if_empty but with :inherit.
106
99
  property :band, inherit: true, populator: "CD Populator" do
@@ -0,0 +1,137 @@
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 :band do
9
+ property :title
10
+
11
+ validation do
12
+ params { required(:title).filled }
13
+ end
14
+
15
+ def id # gets mixed into Form, too.
16
+ 2
17
+ end
18
+ end
19
+
20
+ def id # gets mixed into Form, too.
21
+ 1
22
+ end
23
+
24
+ validation do
25
+ params { required(:band).filled }
26
+ end
27
+
28
+ include Dry::Types.module # allows using Types::* in module.
29
+ property :cool, type: DRY_TYPES_CONSTANT::Bool # test coercion.
30
+ end
31
+
32
+ # TODO: test if works, move stuff into inherit_schema!
33
+ module AirplaysPropertyForm
34
+ include Reform::Form::Module
35
+
36
+ collection :airplays do
37
+ property :station
38
+ validation do
39
+ params { required(:station).filled }
40
+ end
41
+ end
42
+ validation do
43
+ params { required(:airplays).filled }
44
+ end
45
+ end
46
+
47
+ # test:
48
+ # by including BandPropertyForm into multiple classes we assure that options hashes don't get messed up by AM:V.
49
+ class HitForm < TestForm
50
+ include BandPropertyForm
51
+ end
52
+
53
+ class SongForm < TestForm
54
+ include Coercion
55
+ property :title
56
+
57
+ include BandPropertyForm
58
+ end
59
+
60
+ let(:song) { OpenStruct.new(band: OpenStruct.new(title: "Time Again")) }
61
+
62
+ # nested form from module is present and creates accessor.
63
+ it { SongForm.new(song).band.title.must_equal "Time Again" }
64
+
65
+ # methods from module get included.
66
+ it { SongForm.new(song).id.must_equal 1 }
67
+ it { SongForm.new(song).band.id.must_equal 2 }
68
+
69
+ # validators get inherited.
70
+ it do
71
+ form = SongForm.new(OpenStruct.new)
72
+ form.validate({})
73
+ form.errors.messages.must_equal(band: ["must be filled"])
74
+ end
75
+
76
+ # coercion works
77
+ it do
78
+ form = SongForm.new(OpenStruct.new)
79
+ form.validate(cool: "1")
80
+ form.cool.must_equal true
81
+ end
82
+
83
+ # include a module into a module into a class :)
84
+ module AlbumFormModule
85
+ include Reform::Form::Module
86
+ include BandPropertyForm
87
+
88
+ property :name
89
+ validation do
90
+ params { required(:name).filled }
91
+ end
92
+ end
93
+
94
+ class AlbumForm < TestForm
95
+ include AlbumFormModule
96
+
97
+ # pp heritage
98
+ property :band, inherit: true do
99
+ property :label
100
+ validation do
101
+ params { required(:label).filled }
102
+ end
103
+ end
104
+ end
105
+
106
+ it do
107
+ form = AlbumForm.new(OpenStruct.new(band: OpenStruct.new))
108
+ form.validate("band" => {})
109
+ form.errors.messages.must_equal("band.title": ["must be filled"], "band.label": ["must be filled"], name: ["must be filled"])
110
+ end
111
+
112
+ describe "module with custom accessors" do
113
+ module SongModule
114
+ include Reform::Form::Module
115
+
116
+ property :id # no custom accessor for id.
117
+ property :title # has custom accessor.
118
+
119
+ module InstanceMethods
120
+ def title
121
+ super.upcase
122
+ end
123
+ end
124
+ end
125
+
126
+ class IncludingSongForm < TestForm
127
+ include SongModule
128
+ end
129
+
130
+ let(:song) { OpenStruct.new(id: 1, title: "Instant Mash") }
131
+
132
+ it do
133
+ IncludingSongForm.new(song).id.must_equal 1
134
+ IncludingSongForm.new(song).title.must_equal "INSTANT MASH"
135
+ end
136
+ end
137
+ end
@@ -1,10 +1,11 @@
1
1
  require "test_helper"
2
- require 'reform/form/coercion'
2
+ require "reform/form/coercion"
3
3
 
4
4
  class ModuleInclusionTest < MiniTest::Spec
5
5
  module BandPropertyForm
6
6
  include Reform::Form::Module
7
7
 
8
+ property :artist
8
9
  property :band do
9
10
  property :title
10
11
 
@@ -26,7 +27,14 @@ class ModuleInclusionTest < MiniTest::Spec
26
27
  end
27
28
 
28
29
  include Dry::Types.module # allows using Types::* in module.
29
- property :cool, type: Form::Bool # test coercion.
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
30
38
  end
31
39
 
32
40
  # TODO: test if works, move stuff into inherit_schema!
@@ -44,7 +52,6 @@ class ModuleInclusionTest < MiniTest::Spec
44
52
  end
45
53
  end
46
54
 
47
-
48
55
  # test:
49
56
  # by including BandPropertyForm into multiple classes we assure that options hashes don't get messed up by AM:V.
50
57
  class HitForm < TestForm
@@ -58,11 +65,11 @@ class ModuleInclusionTest < MiniTest::Spec
58
65
  include BandPropertyForm
59
66
  end
60
67
 
61
-
62
- let (:song) { OpenStruct.new(:band => OpenStruct.new(:title => "Time Again")) }
68
+ let(:song) { OpenStruct.new(band: OpenStruct.new(title: "Time Again"), artist: "Ketama") }
63
69
 
64
70
  # nested form from module is present and creates accessor.
65
71
  it { SongForm.new(song).band.title.must_equal "Time Again" }
72
+ it { SongForm.new(song).artist.must_equal "Ketama" }
66
73
 
67
74
  # methods from module get included.
68
75
  it { SongForm.new(song).id.must_equal 1 }
@@ -71,8 +78,8 @@ class ModuleInclusionTest < MiniTest::Spec
71
78
  # validators get inherited.
72
79
  it do
73
80
  form = SongForm.new(OpenStruct.new)
74
- form.validate({})
75
- form.errors.messages.must_equal({:band=>["must be filled"]})
81
+ form.validate(artist: nil)
82
+ form.errors.messages.must_equal(artist: ["this needs to be filled"], band: ["must be filled"])
76
83
  end
77
84
 
78
85
  # coercion works
@@ -82,7 +89,6 @@ class ModuleInclusionTest < MiniTest::Spec
82
89
  form.cool.must_equal true
83
90
  end
84
91
 
85
-
86
92
  # include a module into a module into a class :)
87
93
  module AlbumFormModule
88
94
  include Reform::Form::Module
@@ -98,7 +104,7 @@ class ModuleInclusionTest < MiniTest::Spec
98
104
  include AlbumFormModule
99
105
 
100
106
  # pp heritage
101
- property :band, :inherit => true do
107
+ property :band, inherit: true do
102
108
  property :label
103
109
  validation do
104
110
  required(:label).filled
@@ -107,12 +113,11 @@ class ModuleInclusionTest < MiniTest::Spec
107
113
  end
108
114
 
109
115
  it do
110
- form = AlbumForm.new(OpenStruct.new(:band => OpenStruct.new))
111
- form.validate({"band" => {}})
112
- form.errors.messages.must_equal({:"band.title"=>["must be filled"], :"band.label"=>["must be filled"], :name=>["must be filled"]})
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"])
113
119
  end
114
120
 
115
-
116
121
  describe "module with custom accessors" do
117
122
  module SongModule
118
123
  include Reform::Form::Module
@@ -131,7 +136,7 @@ class ModuleInclusionTest < MiniTest::Spec
131
136
  include SongModule
132
137
  end
133
138
 
134
- let (:song) { OpenStruct.new(id: 1, title: "Instant Mash") }
139
+ let(:song) { OpenStruct.new(id: 1, title: "Instant Mash") }
135
140
 
136
141
  it do
137
142
  IncludingSongForm.new(song).id.must_equal 1
@@ -139,4 +144,3 @@ class ModuleInclusionTest < MiniTest::Spec
139
144
  end
140
145
  end
141
146
  end
142
-