reform 2.1.0 → 2.2.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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +4 -12
  4. data/CHANGES.md +8 -0
  5. data/README.md +36 -743
  6. data/Rakefile +1 -31
  7. data/gemfiles/{Gemfile.rails-3.1 → Gemfile.disposable-0.3} +1 -2
  8. data/lib/reform.rb +0 -9
  9. data/lib/reform/contract.rb +5 -1
  10. data/lib/reform/form.rb +1 -4
  11. data/lib/reform/form/composition.rb +1 -2
  12. data/lib/reform/form/dry.rb +29 -16
  13. data/lib/reform/form/module.rb +15 -3
  14. data/lib/reform/form/validate.rb +1 -1
  15. data/lib/reform/validation.rb +3 -3
  16. data/lib/reform/version.rb +1 -1
  17. data/reform.gemspec +3 -10
  18. data/test/coercion_test.rb +7 -7
  19. data/test/composition_test.rb +5 -1
  20. data/test/contract_test.rb +10 -4
  21. data/test/deserialize_test.rb +3 -3
  22. data/test/errors_test.rb +48 -28
  23. data/test/form_option_test.rb +3 -1
  24. data/test/form_test.rb +19 -14
  25. data/test/module_test.rb +51 -11
  26. data/test/populate_test.rb +21 -7
  27. data/test/reform_test.rb +24 -20
  28. data/test/save_test.rb +10 -4
  29. data/test/skip_if_test.rb +5 -3
  30. data/test/test_helper.rb +3 -43
  31. data/test/validate_test.rb +34 -14
  32. data/test/validation/dry_test.rb +60 -0
  33. data/test/validation/dry_validation_test.rb +65 -43
  34. data/test/validation/errors.yml +4 -0
  35. metadata +16 -192
  36. data/database.sqlite3 +0 -0
  37. data/gemfiles/Gemfile.rails-3.2 +0 -7
  38. data/gemfiles/Gemfile.rails-4.0 +0 -8
  39. data/gemfiles/Gemfile.rails-4.1 +0 -8
  40. data/gemfiles/Gemfile.rails-4.2 +0 -8
  41. data/lib/reform/active_record.rb +0 -4
  42. data/lib/reform/form/active_model.rb +0 -87
  43. data/lib/reform/form/active_model/form_builder_methods.rb +0 -48
  44. data/lib/reform/form/active_model/model_reflections.rb +0 -46
  45. data/lib/reform/form/active_model/model_validations.rb +0 -110
  46. data/lib/reform/form/active_model/validations.rb +0 -107
  47. data/lib/reform/form/active_record.rb +0 -30
  48. data/lib/reform/form/lotus.rb +0 -59
  49. data/lib/reform/form/multi_parameter_attributes.rb +0 -48
  50. data/lib/reform/form/validation/unique_validator.rb +0 -54
  51. data/lib/reform/rails.rb +0 -13
  52. data/test/active_model_custom_validation_translations_test.rb +0 -75
  53. data/test/active_model_test.rb +0 -207
  54. data/test/active_model_validation_for_property_named_format_test.rb +0 -18
  55. data/test/active_record_test.rb +0 -273
  56. data/test/builder_test.rb +0 -32
  57. data/test/custom_validation_test.rb +0 -47
  58. data/test/dummy/Rakefile +0 -7
  59. data/test/dummy/app/controllers/albums_controller.rb +0 -18
  60. data/test/dummy/app/controllers/application_controller.rb +0 -4
  61. data/test/dummy/app/controllers/musician_controller.rb +0 -5
  62. data/test/dummy/app/forms/album_form.rb +0 -18
  63. data/test/dummy/app/helpers/application_helper.rb +0 -2
  64. data/test/dummy/app/models/album.rb +0 -4
  65. data/test/dummy/app/models/song.rb +0 -3
  66. data/test/dummy/app/views/albums/new.html.erb +0 -28
  67. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  68. data/test/dummy/config.ru +0 -4
  69. data/test/dummy/config/application.rb +0 -20
  70. data/test/dummy/config/boot.rb +0 -10
  71. data/test/dummy/config/database.yml +0 -22
  72. data/test/dummy/config/environment.rb +0 -5
  73. data/test/dummy/config/environments/development.rb +0 -16
  74. data/test/dummy/config/environments/production.rb +0 -46
  75. data/test/dummy/config/environments/test.rb +0 -33
  76. data/test/dummy/config/locales/en.yml +0 -14
  77. data/test/dummy/config/routes.rb +0 -4
  78. data/test/dummy/db/test.sqlite3 +0 -0
  79. data/test/form_builder_test.rb +0 -138
  80. data/test/lotus/Gemfile +0 -5
  81. data/test/lotus/lotus_test.rb +0 -31
  82. data/test/lotus_test.rb +0 -150
  83. data/test/model_reflections_test.rb +0 -138
  84. data/test/model_validations_test.rb +0 -82
  85. data/test/mongoid_test.rb +0 -313
  86. data/test/multi_parameter_attributes_test.rb +0 -50
  87. data/test/rails/integration_test.rb +0 -54
  88. data/test/unique_test.rb +0 -135
  89. data/test/validation/activemodel_validation_test.rb +0 -252
@@ -6,7 +6,9 @@ class FormOptionTest < MiniTest::Spec
6
6
 
7
7
  class SongForm < Reform::Form
8
8
  property :title
9
- validates :title, presence: true
9
+ validation do
10
+ key(:title).required
11
+ end
10
12
  end
11
13
 
12
14
  class AlbumForm < Reform::Form
@@ -1,6 +1,8 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class FormTest < MiniTest::Spec
4
+ Artist = Struct.new(:name)
5
+
4
6
  class AlbumForm < Reform::Form
5
7
  property :title
6
8
 
@@ -19,18 +21,6 @@ class FormTest < MiniTest::Spec
19
21
  end
20
22
  end
21
23
 
22
- # combined property/validates syntax.
23
- class SongForm < Reform::Form
24
- property :composer
25
- property :title, validates: {presence: true}
26
- properties :genre, :band, validates: {presence: true}
27
- end
28
- it do
29
- form = SongForm.new(OpenStruct.new)
30
- form.validate({})
31
- form.errors.to_s.must_equal "{:title=>[\"can't be blank\"], :genre=>[\"can't be blank\"], :band=>[\"can't be blank\"]}"
32
- end
33
-
34
24
  describe "::dup" do
35
25
  let (:cloned) { AlbumForm.clone }
36
26
 
@@ -45,8 +35,23 @@ class FormTest < MiniTest::Spec
45
35
  "Album"
46
36
  end
47
37
  end
48
- cloned.validates :title, presence: true
38
+
39
+ cloned.validation do
40
+ key(:title).required
41
+ end
42
+
49
43
  cloned.new(OpenStruct.new).validate({})
50
44
  end
51
45
  end
52
- 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
@@ -8,7 +8,9 @@ class ModuleInclusionTest < MiniTest::Spec
8
8
  property :band do
9
9
  property :title
10
10
 
11
- validates :title, presence: true
11
+ validation do
12
+ key(:title).required
13
+ end
12
14
 
13
15
  def id # gets mixed into Form, too.
14
16
  2
@@ -19,9 +21,12 @@ class ModuleInclusionTest < MiniTest::Spec
19
21
  1
20
22
  end
21
23
 
22
- validates :band, presence: true
24
+ validation do
25
+ key(:band).required
26
+ end
23
27
 
24
- property :cool, type: Virtus::Attribute::Boolean # test coercion.
28
+ include Dry::Types.module # allows using Types::* in module.
29
+ property :cool, type: Form::Bool # test coercion.
25
30
  end
26
31
 
27
32
  # TODO: test if works, move stuff into inherit_schema!
@@ -30,9 +35,13 @@ class ModuleInclusionTest < MiniTest::Spec
30
35
 
31
36
  collection :airplays do
32
37
  property :station
33
- validates :station, presence: true
38
+ validation do
39
+ key(:station).required
40
+ end
41
+ end
42
+ validation do
43
+ key(:airplays).required
34
44
  end
35
- validates :airplays, presence: true
36
45
  end
37
46
 
38
47
 
@@ -63,7 +72,7 @@ class ModuleInclusionTest < MiniTest::Spec
63
72
  it do
64
73
  form = SongForm.new(OpenStruct.new)
65
74
  form.validate({})
66
- form.errors.messages.must_equal({:band=>["can't be blank"]})
75
+ form.errors.messages.must_equal({:band=>["is missing"]})
67
76
  end
68
77
 
69
78
  # coercion works
@@ -80,8 +89,9 @@ class ModuleInclusionTest < MiniTest::Spec
80
89
  include BandPropertyForm
81
90
 
82
91
  property :name
83
- validates :name, :presence => true
84
-
92
+ validation do
93
+ key(:name).required
94
+ end
85
95
  end
86
96
 
87
97
  class AlbumForm < Reform::Form
@@ -90,13 +100,43 @@ class ModuleInclusionTest < MiniTest::Spec
90
100
  # pp heritage
91
101
  property :band, :inherit => true do
92
102
  property :label
93
- validates :label, :presence => true
103
+ validation do
104
+ key(:label).required
105
+ end
94
106
  end
95
107
  end
96
108
 
97
109
  it do
98
110
  form = AlbumForm.new(OpenStruct.new(:band => OpenStruct.new))
99
111
  form.validate({"band" => {}})
100
- form.errors.messages.must_equal({:"band.title"=>["can't be blank"], :"band.label"=>["can't be blank"], :name=>["can't be blank"]})
112
+ form.errors.messages.must_equal({:band=>["must be filled"], :"band.title"=>["is missing"], :"band.label"=>["is missing"], :name=>["is missing"]})
113
+ end
114
+
115
+
116
+ describe "module with custom accessors" do
117
+ module SongModule
118
+ include Reform::Form::Module
119
+
120
+ property :id # no custom accessor for id.
121
+ property :title # has custom accessor.
122
+
123
+ module InstanceMethods
124
+ def title
125
+ super.upcase
126
+ end
127
+ end
128
+ end
129
+
130
+ class IncludingSongForm < Reform::Form
131
+ include SongModule
132
+ end
133
+
134
+ let (:song) { OpenStruct.new(id: 1, title: "Instant Mash") }
135
+
136
+ it do
137
+ IncludingSongForm.new(song).id.must_equal 1
138
+ IncludingSongForm.new(song).title.must_equal "INSTANT MASH"
139
+ end
101
140
  end
102
- end
141
+ end
142
+
@@ -7,7 +7,9 @@ class PopulatorTest < MiniTest::Spec
7
7
 
8
8
  class AlbumForm < Reform::Form
9
9
  property :name, populator: ->(options) { self.name = options[:fragment].reverse }
10
- validates :name, presence: true
10
+ validation do
11
+ key(:name).required
12
+ end
11
13
 
12
14
  collection :songs,
13
15
  populator: ->(options) {
@@ -16,11 +18,15 @@ class PopulatorTest < MiniTest::Spec
16
18
  (item = collection[index]) ? item : collection.insert(index, Song.new) } do
17
19
 
18
20
  property :title
19
- validates :title, presence: true
21
+ validation do
22
+ key(:title).required
23
+ end
20
24
 
21
25
  property :composer, populator: ->(options) { options[:model] || self.composer= Artist.new } do
22
26
  property :name
23
- validates :name, presence: true
27
+ validation do
28
+ key(:name).required
29
+ end
24
30
  end
25
31
  end
26
32
 
@@ -99,6 +105,8 @@ class PopulatorTest < MiniTest::Spec
99
105
  end
100
106
 
101
107
  class PopulateWithMethodTest < Minitest::Spec
108
+ Album = Struct.new(:title)
109
+
102
110
  class AlbumForm < Reform::Form
103
111
  property :title, populator: :title!
104
112
 
@@ -138,11 +146,15 @@ class PopulateIfEmptyTest < MiniTest::Spec
138
146
  populate_if_empty: Song do # class name works.
139
147
 
140
148
  property :title
141
- validates :title, presence: true
149
+ validation do
150
+ key(:title).required
151
+ end
142
152
 
143
153
  property :composer, populate_if_empty: :populate_composer! do # lambda works, too. in form context.
144
154
  property :name
145
- validates :name, presence: true
155
+ validation do
156
+ key(:name).required
157
+ end
146
158
  end
147
159
 
148
160
  private
@@ -232,7 +244,9 @@ class PopulateIfEmptyWithDeletionTest < MiniTest::Spec
232
244
  populate_if_empty: Song, skip_if: :delete_song! do
233
245
 
234
246
  property :title
235
- validates :title, presence: true
247
+ validation do
248
+ key(:title).required
249
+ end
236
250
  end
237
251
 
238
252
  def delete_song!(options)
@@ -253,4 +267,4 @@ class PopulateIfEmptyWithDeletionTest < MiniTest::Spec
253
267
  form.songs.size.must_equal 1
254
268
  form.songs[0].title.must_equal "Roxanne"
255
269
  end
256
- end
270
+ end
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  # TODO: this test should be removed.
4
- class ReformTest < ReformSpec
4
+ class ReformTest < Minitest::Spec
5
5
  let (:comp) { OpenStruct.new(:name => "Duran Duran", :title => "Rio") }
6
6
 
7
7
  let (:form) { SongForm.new(comp) }
@@ -10,7 +10,9 @@ class ReformTest < ReformSpec
10
10
  property :name
11
11
  property :title
12
12
 
13
- validates :name, :presence => true
13
+ validation do
14
+ key(:name).required
15
+ end
14
16
  end
15
17
 
16
18
  describe "(new) form with empty models" do
@@ -70,8 +72,10 @@ class ReformTest < ReformSpec
70
72
  property :name
71
73
  property :title
72
74
 
73
- validates :name, :presence => true
74
- validates :title, :presence => true
75
+ validation do
76
+ key(:name).required
77
+ key(:title).required
78
+ end
75
79
  end
76
80
  let (:form) { ValidatingForm.new(comp) }
77
81
 
@@ -81,21 +85,22 @@ class ReformTest < ReformSpec
81
85
 
82
86
  it "populates errors" do
83
87
  form.validate({})
84
- form.errors.messages.must_equal({:name=>["can't be blank"], :title=>["can't be blank"]})
88
+ form.errors.messages.must_equal({:name=>["is missing"], :title=>["is missing"]})
85
89
  end
86
90
  end
87
91
  end
88
92
 
93
+ # FIXME: add this test to reform-rails.
89
94
  describe "#errors" do
90
95
  before { form.validate({})}
91
96
 
92
- it { form.errors.must_be_kind_of Reform::Form::ActiveModel::Errors }
97
+ it { form.errors.must_be_kind_of Reform::Contract::Errors }
93
98
 
94
99
  it { form.errors.messages.must_equal({}) }
95
100
 
96
101
  it do
97
102
  form.validate({"name"=>""})
98
- form.errors.messages.must_equal({:name=>["can't be blank"]})
103
+ form.errors.messages.must_equal({:name=>["must be filled"]})
99
104
  end
100
105
  end
101
106
 
@@ -132,21 +137,20 @@ class ReformTest < ReformSpec
132
137
  end
133
138
 
134
139
 
135
- unless (rails4_0? or rails3_2?)
136
- describe "inheritance" do
137
- class HitForm < SongForm
138
- property :position
139
- validates :position, :presence => true
140
-
140
+ describe "inheritance" do
141
+ class HitForm < SongForm
142
+ property :position
143
+ validation do
144
+ key(:position).required
141
145
  end
146
+ end
142
147
 
143
- let (:form) { HitForm.new(OpenStruct.new()) }
144
- it do
145
- form.validate({"title" => "The Body"})
146
- form.title.must_equal "The Body"
147
- form.position.must_equal nil
148
- form.errors.messages.must_equal({:name=>["can't be blank"], :position=>["can't be blank"]})
149
- end
148
+ let (:form) { HitForm.new(OpenStruct.new()) }
149
+ it do
150
+ form.validate({"title" => "The Body"})
151
+ form.title.must_equal "The Body"
152
+ form.position.must_equal nil
153
+ form.errors.messages.must_equal({:name=>["is missing"], :position=>["is missing"]})
150
154
  end
151
155
  end
152
156
  end
@@ -7,15 +7,21 @@ class SaveTest < BaseTest
7
7
 
8
8
  class AlbumForm < Reform::Form
9
9
  property :name
10
- validates :name, presence: true
10
+ validation do
11
+ key(:name).required
12
+ end
11
13
 
12
14
  collection :songs do
13
15
  property :title
14
- validates :title, presence: true
16
+ validation do
17
+ key(:title).required
18
+ end
15
19
 
16
20
  property :composer do
17
21
  property :name
18
- validates :name, presence: true
22
+ validation do
23
+ key(:name).required
24
+ end
19
25
  end
20
26
  end
21
27
 
@@ -80,4 +86,4 @@ end
80
86
  # song.length.must_equal nil
81
87
  # song.id.must_equal "10: 120"
82
88
  # end
83
- # end
89
+ # end
@@ -5,9 +5,11 @@ class SkipIfTest < BaseTest
5
5
  class AlbumForm < Reform::Form
6
6
  property :title
7
7
 
8
- property :hit, skip_if: lambda { |options| options[:fragment]["title"].blank? } do
8
+ property :hit, skip_if: lambda { |options| options[:fragment]["title"]=="" } do
9
9
  property :title
10
- validates :title, presence: true
10
+ validation do
11
+ key(:title).required
12
+ end
11
13
  end
12
14
 
13
15
  collection :songs, skip_if: :skip_song?, populate_if_empty: BaseTest::Song do
@@ -69,4 +71,4 @@ class SkipIfAllBlankTest < BaseTest
69
71
  form.songs.size.must_equal 1
70
72
  form.songs[0].title.must_equal "Apathy"
71
73
  end
72
- end
74
+ end
@@ -4,31 +4,6 @@ require "representable/debug"
4
4
  require "declarative/testing"
5
5
  require "pp"
6
6
 
7
- class ReformSpec < MiniTest::Spec
8
- let (:duran) { Struct.new(:name).new("Duran Duran") }
9
- let (:rio) { Struct.new(:title).new("Rio") }
10
- end
11
-
12
- require 'active_record'
13
- class Artist < ActiveRecord::Base
14
- end
15
-
16
- class Song < ActiveRecord::Base
17
- belongs_to :artist
18
- end
19
-
20
- class Album < ActiveRecord::Base
21
- has_many :songs
22
- end
23
-
24
- ActiveRecord::Base.establish_connection(
25
- :adapter => "sqlite3",
26
- :database => "#{Dir.pwd}/database.sqlite3"
27
- )
28
-
29
-
30
- #Artist.delete_all
31
-
32
7
  class BaseTest < MiniTest::Spec
33
8
  class AlbumForm < Reform::Form
34
9
  property :title
@@ -62,28 +37,13 @@ MiniTest::Spec.class_eval do
62
37
  @saved
63
38
  end
64
39
  end
65
-
66
- def self.rails4_2?
67
- ::ActiveModel::VERSION::MAJOR == 4 and ::ActiveModel::VERSION::MINOR == 2
68
- end
69
-
70
- def self.rails4_0?
71
- ::ActiveModel::VERSION::MAJOR == 4 and ::ActiveModel::VERSION::MINOR == 0
72
- end
73
-
74
- def self.rails3_2?
75
- ::ActiveModel::VERSION::MAJOR == 3 and ::ActiveModel::VERSION::MINOR == 2
76
- end
77
40
  end
78
41
 
79
- require "reform/form/active_model/validations"
42
+ require "reform/form/dry"
80
43
  Reform::Contract.class_eval do
81
- feature Reform::Form::ActiveModel::Validations
44
+ feature Reform::Form::Dry
82
45
  end
83
46
  # FIXME!
84
47
  Reform::Form.class_eval do
85
- feature Reform::Form::ActiveModel::Validations
48
+ feature Reform::Form::Dry
86
49
  end
87
-
88
- I18n.load_path << Dir['test/dummy/config/locales/*.yml']
89
- I18n.backend.load_translations