reform 2.3.0.rc1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +5 -1
  3. data/.travis.yml +7 -11
  4. data/CHANGES.md +43 -3
  5. data/Gemfile +2 -5
  6. data/ISSUE_TEMPLATE.md +1 -1
  7. data/LICENSE.txt +1 -1
  8. data/README.md +7 -9
  9. data/Rakefile +6 -10
  10. data/lib/reform/contract.rb +7 -7
  11. data/lib/reform/contract/custom_error.rb +41 -0
  12. data/lib/reform/contract/validate.rb +10 -6
  13. data/lib/reform/errors.rb +27 -15
  14. data/lib/reform/form.rb +22 -11
  15. data/lib/reform/form/call.rb +1 -1
  16. data/lib/reform/form/composition.rb +2 -2
  17. data/lib/reform/form/dry.rb +22 -60
  18. data/lib/reform/form/dry/input_hash.rb +37 -0
  19. data/lib/reform/form/populator.rb +9 -11
  20. data/lib/reform/form/prepopulate.rb +3 -2
  21. data/lib/reform/form/validate.rb +19 -12
  22. data/lib/reform/result.rb +36 -9
  23. data/lib/reform/validation.rb +10 -8
  24. data/lib/reform/validation/groups.rb +2 -4
  25. data/lib/reform/version.rb +1 -1
  26. data/reform.gemspec +9 -9
  27. data/test/benchmarking.rb +10 -11
  28. data/test/call_test.rb +8 -8
  29. data/test/changed_test.rb +13 -13
  30. data/test/coercion_test.rb +56 -24
  31. data/test/composition_test.rb +49 -51
  32. data/test/contract/custom_error_test.rb +55 -0
  33. data/test/contract_test.rb +18 -18
  34. data/test/default_test.rb +3 -3
  35. data/test/deserialize_test.rb +14 -17
  36. data/test/docs/validation_test.rb +134 -0
  37. data/test/errors_test.rb +131 -86
  38. data/test/feature_test.rb +9 -11
  39. data/test/fixtures/dry_error_messages.yml +65 -52
  40. data/test/form_option_test.rb +3 -3
  41. data/test/form_test.rb +6 -6
  42. data/test/from_test.rb +17 -21
  43. data/test/inherit_test.rb +28 -35
  44. data/test/module_test.rb +23 -28
  45. data/test/parse_option_test.rb +12 -12
  46. data/test/parse_pipeline_test.rb +3 -3
  47. data/test/populate_test.rb +146 -93
  48. data/test/populator_skip_test.rb +3 -4
  49. data/test/prepopulator_test.rb +20 -21
  50. data/test/read_only_test.rb +12 -1
  51. data/test/readable_test.rb +7 -7
  52. data/test/reform_test.rb +38 -42
  53. data/test/save_test.rb +16 -19
  54. data/test/setup_test.rb +15 -15
  55. data/test/skip_if_test.rb +30 -19
  56. data/test/skip_setter_and_getter_test.rb +8 -9
  57. data/test/test_helper.rb +12 -5
  58. data/test/validate_test.rb +160 -140
  59. data/test/validation/dry_validation_test.rb +407 -236
  60. data/test/validation/result_test.rb +29 -31
  61. data/test/validation_library_provided_test.rb +3 -3
  62. data/test/virtual_test.rb +46 -6
  63. data/test/writeable_test.rb +13 -13
  64. metadata +32 -29
  65. data/test/readonly_test.rb +0 -14
@@ -8,72 +8,70 @@ class ErrorsResultTest < Minitest::Spec
8
8
  # TODO: errors(args) not tested.
9
9
 
10
10
  describe "Contract::Result#success?" do
11
- let (:failed) { MyResult.new(false) }
12
- let (:succeeded) { MyResult.new(true) }
11
+ let(:failed) { MyResult.new(false) }
12
+ let(:succeeded) { MyResult.new(true) }
13
13
 
14
- it { Reform::Contract::Result.new([failed, failed]).success?.must_equal false }
15
- it { Reform::Contract::Result.new([succeeded, failed]).success?.must_equal false }
16
- it { Reform::Contract::Result.new([failed, succeeded]).success?.must_equal false }
17
- it { Reform::Contract::Result.new([succeeded, succeeded]).success?.must_equal true }
14
+ it { assert_equal Reform::Contract::Result.new([failed, failed]).success?, false }
15
+ it { assert_equal Reform::Contract::Result.new([succeeded, failed]).success?, false }
16
+ it { assert_equal Reform::Contract::Result.new([failed, succeeded]).success?, false }
17
+ it { assert Reform::Contract::Result.new([succeeded, succeeded]).success? }
18
18
  end
19
19
 
20
20
  describe "Contract::Result#errors" do
21
- let (:results) {
21
+ let(:results) do
22
22
  [
23
- MyResult.new(false, { title: ["must be filled"], nested: { something: [] } }),
24
- MyResult.new(false, { length: ["no Int"] })
23
+ MyResult.new(false, {length: ["no Int"]}),
24
+ MyResult.new(false, {title: ["must be filled"], nested: {something: []}}),
25
+ MyResult.new(false, {title: ["must be filled"], nested: {something: []}}),
26
+ MyResult.new(false, {title: ["something more"], nested: {something: []}})
25
27
  ]
26
- }
28
+ end
27
29
 
28
- it { Reform::Contract::Result.new(results).errors.must_equal({:title=>["must be filled"], :length=>["no Int"]}) }
30
+ it { assert_equal Reform::Contract::Result.new(results).errors, {title: ["must be filled", "something more"], length: ["no Int"]} }
29
31
  end
30
32
 
31
33
  describe "Result::Pointer" do
32
- let (:errors) do # dry result #errors format.
34
+ let(:errors) do # dry result #errors format.
33
35
  {
34
36
  title: ["ignore"],
35
- artist: { age: ["too old"],
37
+ artist: {age: ["too old"],
36
38
  bands: {
37
- 0 => { name: "too new school" },
38
- 1 => { name: "too boring" },
39
+ 0 => {name: "too new school"},
40
+ 1 => {name: "too boring"},
39
41
  }
40
42
  }
41
43
  }
42
44
  end
43
45
 
44
- let (:top) { Reform::Contract::Result::Pointer.new(MyResult.new(false, errors), []) }
45
- it { top.success?.must_equal false }
46
- it { top.errors.must_equal errors }
46
+ let(:top) { Reform::Contract::Result::Pointer.new(MyResult.new(false, errors), []) }
47
+ it { assert_equal top.success?, false }
48
+ it { assert_equal top.errors, errors }
47
49
 
48
- let (:artist) { Reform::Contract::Result::Pointer.new(MyResult.new(false, errors), [:artist]) }
49
- it { artist.success?.must_equal false }
50
- it { artist.errors.must_equal({:age=>["too old"], :bands=>{0=>{:name=>"too new school"}, 1=>{:name=>"too boring"}}}) }
50
+ let(:artist) { Reform::Contract::Result::Pointer.new(MyResult.new(false, errors), [:artist]) }
51
+ it { assert_equal artist.success?, false }
52
+ it { assert_equal artist.errors,({age: ["too old"], bands: {0 => {name: "too new school"}, 1 => {name: "too boring"}}}) }
51
53
 
52
- let (:band) { Reform::Contract::Result::Pointer.new(MyResult.new(false, errors), [:artist, :bands, 1]) }
53
- it { band.success?.must_equal false }
54
- it { band.errors.must_equal({:name=>"too boring"}) }
54
+ let(:band) { Reform::Contract::Result::Pointer.new(MyResult.new(false, errors), [:artist, :bands, 1]) }
55
+ it { assert_equal band.success?, false }
56
+ it { assert_equal band.errors,({name: "too boring"}) }
55
57
 
56
58
  describe "advance" do
57
59
  let(:advanced) { artist.advance(:bands, 1) }
58
60
 
59
- it { advanced.success?.must_equal false }
60
- it { advanced.errors.must_equal({:name=>"too boring"}) }
61
+ it { assert_equal advanced.success?, false }
62
+ it { assert_equal advanced.errors,({name: "too boring"}) }
61
63
 
62
- it { artist.advance([:absolute, :nonsense]).must_equal nil }
64
+ it { assert_nil artist.advance(%i[absolute nonsense]) }
63
65
  end
64
66
  end
65
67
  end
66
68
 
67
-
68
69
  # validation group:
69
70
 
70
71
  # form.errors/messages/hint(*args) ==> {:title: [..]}
71
72
  # @call_result.errors/messages/hint(*args) }
72
73
 
73
-
74
-
75
74
  # # result = Result(original_result => [:band, :label], my_local_result => [] )
76
75
  # # result.messages(locale: :en) merges original_result and my_local_result
77
76
 
78
77
  # form.errors => Result(fetch tree of all nested forms.messages(*args))
79
-
@@ -1,8 +1,8 @@
1
- require 'reform'
2
- require 'minitest/autorun'
1
+ require "reform"
2
+ require "minitest/autorun"
3
3
 
4
4
  class ValidationLibraryProvidedTest < MiniTest::Spec
5
- it 'no validation library loaded' do
5
+ it "no validation library loaded" do
6
6
  assert_raises Reform::Validation::NoValidationLibraryError do
7
7
  class PersonForm < Reform::Form
8
8
  property :name
data/test/virtual_test.rb CHANGED
@@ -1,16 +1,20 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class VirtualTest < MiniTest::Spec
4
4
  class CreditCardForm < TestForm
5
5
  property :credit_card_number, virtual: true # no read, no write, it's virtual.
6
+ collection :transactions, virtual: true, populate_if_empty: OpenStruct do
7
+ property :id
8
+ end
6
9
  end
7
10
 
8
- let (:form) { CreditCardForm.new(Object.new) }
11
+ let(:form) { CreditCardForm.new(Object.new) }
9
12
 
10
13
  it {
11
- form.validate("credit_card_number" => "123")
14
+ form.validate(credit_card_number: "123", transactions: [id: 1])
12
15
 
13
- form.credit_card_number.must_equal "123" # this is still readable in the UI.
16
+ assert_equal form.credit_card_number, "123" # this is still readable in the UI.
17
+ assert_equal form.transactions.first.id, 1 # this is still readable in the UI.
14
18
 
15
19
  form.sync
16
20
 
@@ -19,6 +23,42 @@ class VirtualTest < MiniTest::Spec
19
23
  hash = nested
20
24
  end
21
25
 
22
- hash.must_equal("credit_card_number"=> "123")
26
+ assert_equal hash, "credit_card_number" => "123", "transactions" => ["id" => 1]
27
+ }
28
+ end
29
+
30
+ class VirtualAndDefaultTest < MiniTest::Spec
31
+ class CreditCardForm < TestForm
32
+ property :credit_card_number, virtual: true, default: "123" # no read, no write, it's virtual.
33
+ collection :transactions, virtual: true, populate_if_empty: OpenStruct, default: [OpenStruct.new(id: 2)] do
34
+ property :id
35
+ end
36
+ end
37
+
38
+ def hash(form)
39
+ hash = {}
40
+ form.save do |nested|
41
+ hash = nested
42
+ end
43
+ hash
44
+ end
45
+
46
+ let(:form) { CreditCardForm.new(Object.new) }
47
+
48
+ it {
49
+ form = CreditCardForm.new(Object.new)
50
+ form.validate({})
51
+
52
+ assert_equal hash(form), "credit_card_number" => "123", "transactions" => ["id" => 2]
53
+
54
+ form = CreditCardForm.new(Object.new)
55
+ form.validate(credit_card_number: "123", transactions: [id: 1])
56
+
57
+ assert_equal form.credit_card_number, "123" # this is still readable in the UI.
58
+ assert_equal form.transactions.first.id, 1 # this is still readable in the UI.
59
+
60
+ form.sync
61
+
62
+ assert_equal hash(form), "credit_card_number" => "123", "transactions" => ["id" => 1]
23
63
  }
24
- end
64
+ end
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class WriteableTest < MiniTest::Spec
4
4
  Location = Struct.new(:country)
@@ -7,24 +7,24 @@ class WriteableTest < MiniTest::Spec
7
7
  property :country, writeable: false
8
8
  end
9
9
 
10
- let (:loc) { Location.new("Australia") }
11
- let (:form) { LocationForm.new(loc) }
10
+ let(:loc) { Location.new("Australia") }
11
+ let(:form) { LocationForm.new(loc) }
12
12
 
13
13
  it do
14
- form.country.must_equal "Australia"
14
+ assert_equal form.country, "Australia"
15
15
 
16
16
  form.validate("country" => "Germany") # this usually won't change when submitting.
17
- form.country.must_equal "Germany"
17
+ assert_equal form.country, "Germany"
18
18
 
19
19
  form.sync
20
- loc.country.must_equal "Australia" # the writer wasn't called.
20
+ assert_equal loc.country, "Australia" # the writer wasn't called.
21
21
 
22
22
  hash = {}
23
23
  form.save do |nested|
24
24
  hash = nested
25
25
  end
26
26
 
27
- hash.must_equal("country"=> "Germany")
27
+ assert_equal hash, "country" => "Germany"
28
28
  end
29
29
  end
30
30
 
@@ -36,23 +36,23 @@ class WritableTest < MiniTest::Spec
36
36
  property :country, writable: false
37
37
  end
38
38
 
39
- let (:loc) { Location.new("Australia") }
40
- let (:form) { LocationForm.new(loc) }
39
+ let(:loc) { Location.new("Australia") }
40
+ let(:form) { LocationForm.new(loc) }
41
41
 
42
42
  it do
43
- form.country.must_equal "Australia"
43
+ assert_equal form.country, "Australia"
44
44
 
45
45
  form.validate("country" => "Germany") # this usually won't change when submitting.
46
- form.country.must_equal "Germany"
46
+ assert_equal form.country, "Germany"
47
47
 
48
48
  form.sync
49
- loc.country.must_equal "Australia" # the writer wasn't called.
49
+ assert_equal loc.country, "Australia" # the writer wasn't called.
50
50
 
51
51
  hash = {}
52
52
  form.save do |nested|
53
53
  hash = nested
54
54
  end
55
55
 
56
- hash.must_equal("country"=> "Germany")
56
+ assert_equal hash, "country" => "Germany"
57
57
  end
58
58
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reform
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0.rc1
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  - Fran Worley
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-02-26 00:00:00.000000000 Z
12
+ date: 2021-02-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: disposable
@@ -32,39 +32,39 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.5.0
34
34
  - !ruby/object:Gem::Dependency
35
- name: uber
35
+ name: representable
36
36
  requirement: !ruby/object:Gem::Requirement
37
37
  requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.4.0
38
41
  - - "<"
39
42
  - !ruby/object:Gem::Version
40
- version: 0.2.0
43
+ version: 3.1.0
41
44
  type: :runtime
42
45
  prerelease: false
43
46
  version_requirements: !ruby/object:Gem::Requirement
44
47
  requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 2.4.0
45
51
  - - "<"
46
52
  - !ruby/object:Gem::Version
47
- version: 0.2.0
53
+ version: 3.1.0
48
54
  - !ruby/object:Gem::Dependency
49
- name: representable
55
+ name: uber
50
56
  requirement: !ruby/object:Gem::Requirement
51
57
  requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: 2.4.0
55
58
  - - "<"
56
59
  - !ruby/object:Gem::Version
57
- version: 3.1.0
60
+ version: 0.2.0
58
61
  type: :runtime
59
62
  prerelease: false
60
63
  version_requirements: !ruby/object:Gem::Requirement
61
64
  requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- version: 2.4.0
65
65
  - - "<"
66
66
  - !ruby/object:Gem::Version
67
- version: 3.1.0
67
+ version: 0.2.0
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: bundler
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +80,7 @@ dependencies:
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  - !ruby/object:Gem::Dependency
83
- name: rake
83
+ name: minitest
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - ">="
@@ -94,7 +94,7 @@ dependencies:
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
96
  - !ruby/object:Gem::Dependency
97
- name: minitest
97
+ name: minitest-line
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - ">="
@@ -108,7 +108,7 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  - !ruby/object:Gem::Dependency
111
- name: dry-types
111
+ name: pry-byebug
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - ">="
@@ -136,19 +136,19 @@ dependencies:
136
136
  - !ruby/object:Gem::Version
137
137
  version: '0'
138
138
  - !ruby/object:Gem::Dependency
139
- name: dry-validation
139
+ name: rake
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - ">="
143
143
  - !ruby/object:Gem::Version
144
- version: 0.10.1
144
+ version: '0'
145
145
  type: :development
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - ">="
150
150
  - !ruby/object:Gem::Version
151
- version: 0.10.1
151
+ version: '0'
152
152
  description: Form object decoupled from models.
153
153
  email:
154
154
  - apotonick@gmail.com
@@ -169,6 +169,7 @@ files:
169
169
  - TODO.md
170
170
  - lib/reform.rb
171
171
  - lib/reform/contract.rb
172
+ - lib/reform/contract/custom_error.rb
172
173
  - lib/reform/contract/validate.rb
173
174
  - lib/reform/errors.rb
174
175
  - lib/reform/form.rb
@@ -176,6 +177,7 @@ files:
176
177
  - lib/reform/form/coercion.rb
177
178
  - lib/reform/form/composition.rb
178
179
  - lib/reform/form/dry.rb
180
+ - lib/reform/form/dry/input_hash.rb
179
181
  - lib/reform/form/module.rb
180
182
  - lib/reform/form/populator.rb
181
183
  - lib/reform/form/prepopulate.rb
@@ -190,9 +192,11 @@ files:
190
192
  - test/changed_test.rb
191
193
  - test/coercion_test.rb
192
194
  - test/composition_test.rb
195
+ - test/contract/custom_error_test.rb
193
196
  - test/contract_test.rb
194
197
  - test/default_test.rb
195
198
  - test/deserialize_test.rb
199
+ - test/docs/validation_test.rb
196
200
  - test/errors_test.rb
197
201
  - test/feature_test.rb
198
202
  - test/fixtures/dry_error_messages.yml
@@ -208,7 +212,6 @@ files:
208
212
  - test/prepopulator_test.rb
209
213
  - test/read_only_test.rb
210
214
  - test/readable_test.rb
211
- - test/readonly_test.rb
212
215
  - test/reform_test.rb
213
216
  - test/save_test.rb
214
217
  - test/setup_test.rb
@@ -225,7 +228,7 @@ homepage: https://github.com/trailblazer/reform
225
228
  licenses:
226
229
  - MIT
227
230
  metadata: {}
228
- post_install_message:
231
+ post_install_message:
229
232
  rdoc_options: []
230
233
  require_paths:
231
234
  - lib
@@ -236,13 +239,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
236
239
  version: '0'
237
240
  required_rubygems_version: !ruby/object:Gem::Requirement
238
241
  requirements:
239
- - - ">"
242
+ - - ">="
240
243
  - !ruby/object:Gem::Version
241
- version: 1.3.1
244
+ version: '0'
242
245
  requirements: []
243
- rubyforge_project:
244
- rubygems_version: 2.6.3
245
- signing_key:
246
+ rubygems_version: 3.0.3
247
+ signing_key:
246
248
  specification_version: 4
247
249
  summary: Form object decoupled from models with validation, population and presentation.
248
250
  test_files:
@@ -251,9 +253,11 @@ test_files:
251
253
  - test/changed_test.rb
252
254
  - test/coercion_test.rb
253
255
  - test/composition_test.rb
256
+ - test/contract/custom_error_test.rb
254
257
  - test/contract_test.rb
255
258
  - test/default_test.rb
256
259
  - test/deserialize_test.rb
260
+ - test/docs/validation_test.rb
257
261
  - test/errors_test.rb
258
262
  - test/feature_test.rb
259
263
  - test/fixtures/dry_error_messages.yml
@@ -269,7 +273,6 @@ test_files:
269
273
  - test/prepopulator_test.rb
270
274
  - test/read_only_test.rb
271
275
  - test/readable_test.rb
272
- - test/readonly_test.rb
273
276
  - test/reform_test.rb
274
277
  - test/save_test.rb
275
278
  - test/setup_test.rb