reform 1.1.1 → 1.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +35 -1
  3. data/Gemfile +1 -1
  4. data/README.md +83 -21
  5. data/TODO.md +8 -0
  6. data/database.sqlite3 +0 -0
  7. data/gemfiles/Gemfile.rails-4.0 +1 -0
  8. data/lib/reform.rb +4 -2
  9. data/lib/reform/active_record.rb +2 -1
  10. data/lib/reform/composition.rb +2 -2
  11. data/lib/reform/contract.rb +24 -7
  12. data/lib/reform/contract/setup.rb +21 -9
  13. data/lib/reform/contract/validate.rb +0 -6
  14. data/lib/reform/form.rb +6 -8
  15. data/lib/reform/form/active_model.rb +3 -2
  16. data/lib/reform/form/active_model/model_validations.rb +13 -1
  17. data/lib/reform/form/active_record.rb +1 -7
  18. data/lib/reform/form/changed.rb +9 -0
  19. data/lib/reform/form/json.rb +13 -0
  20. data/lib/reform/form/model_reflections.rb +18 -0
  21. data/lib/reform/form/save.rb +25 -3
  22. data/lib/reform/form/scalar.rb +4 -2
  23. data/lib/reform/form/sync.rb +82 -12
  24. data/lib/reform/form/validate.rb +38 -0
  25. data/lib/reform/rails.rb +1 -1
  26. data/lib/reform/representer.rb +14 -23
  27. data/lib/reform/schema.rb +23 -0
  28. data/lib/reform/twin.rb +20 -0
  29. data/lib/reform/version.rb +1 -1
  30. data/reform.gemspec +2 -2
  31. data/test/active_model_test.rb +2 -2
  32. data/test/active_record_test.rb +7 -4
  33. data/test/changed_test.rb +69 -0
  34. data/test/custom_validation_test.rb +47 -0
  35. data/test/deserialize_test.rb +2 -7
  36. data/test/empty_test.rb +30 -0
  37. data/test/fields_test.rb +24 -0
  38. data/test/form_composition_test.rb +24 -2
  39. data/test/form_test.rb +84 -0
  40. data/test/inherit_test.rb +12 -0
  41. data/test/model_reflections_test.rb +65 -0
  42. data/test/read_only_test.rb +28 -0
  43. data/test/reform_test.rb +2 -175
  44. data/test/representer_test.rb +47 -0
  45. data/test/save_test.rb +51 -1
  46. data/test/scalar_test.rb +0 -18
  47. data/test/skip_if_test.rb +62 -0
  48. data/test/skip_unchanged_test.rb +86 -0
  49. data/test/sync_option_test.rb +83 -0
  50. data/test/twin_test.rb +23 -0
  51. data/test/validate_test.rb +9 -1
  52. metadata +37 -9
  53. data/lib/reform/form/virtual_attributes.rb +0 -22
@@ -0,0 +1,86 @@
1
+ require 'test_helper'
2
+
3
+ class SkipUnchangedTest < MiniTest::Spec
4
+ class SongForm < Reform::Form
5
+ include Sync::SkipUnchanged
6
+ register_feature Sync::SkipUnchanged
7
+
8
+ property :id
9
+ property :title
10
+ property :image, sync: lambda { |value, *| model.image = "processed via :sync: #{value}" }#, virtual: true
11
+ property :band do
12
+ property :name, sync: lambda { |value, *| model.name = "band, processed: #{value}" }
13
+ end
14
+ end
15
+
16
+ Song = Struct.new(:id, :title, :image, :band) do
17
+ def id=(v); raise "never call me #{v.inspect}"; end
18
+ end
19
+ Band = Struct.new(:name)
20
+
21
+ let (:song) { Song.new(1, "Injection", Object, Band.new("Rise Against")) }
22
+
23
+ # skips when not present in hash + SkipUnchanged.
24
+ it("zhz") do
25
+ form = SongForm.new(song)
26
+
27
+ form.validate("title" => "Ready To Fall").must_equal true
28
+ form.sync
29
+
30
+ song.id.must_equal 1 # old
31
+ song.title.must_equal "Ready To Fall" # new!
32
+ song.image.must_equal Object # old
33
+ song.band.name.must_equal "Rise Against" # old
34
+ end
35
+
36
+ # uses :sync when present in params hash.
37
+ it do
38
+ form = SongForm.new(song)
39
+
40
+ form.validate("title" => "Ready To Fall", "image" => Module, "band" => {"name" => Class})
41
+ form.sync
42
+
43
+ song.id.must_equal 1
44
+ song.image.must_equal "processed via :sync: Module"
45
+ # nested works.
46
+ song.band.name.must_equal "band, processed: Class"
47
+ end
48
+ end
49
+
50
+
51
+ # :virtual is considered with SkipUnchanged
52
+ class SkipUnchangedWithVirtualTest < MiniTest::Spec
53
+ Song = Struct.new(:title, :image, :band) do
54
+ def image=(v)
55
+ raise "i should not be called: #{v}"
56
+ end
57
+ end
58
+ Band = Struct.new(:name) do
59
+ def name=(v)
60
+ raise "i should not be called: #{v}"
61
+ end
62
+ end
63
+
64
+ let (:form) { HitForm.new(song) }
65
+ let (:song) { Song.new(nil, nil, Band.new) }
66
+
67
+ class HitForm < Reform::Form
68
+ include Sync::SkipUnchanged
69
+ register_feature Sync::SkipUnchanged
70
+
71
+ property :title
72
+ property :image, virtual: true
73
+ property :band do
74
+ property :name, virtual: true
75
+ end
76
+ end
77
+
78
+ it "hhy" do
79
+ form.validate("title" => "Full Throttle", "image" => "Funny photo of Steve Harris", "band" => {"name" => "Iron Maiden"}).must_equal true
80
+
81
+ form.sync
82
+ song.title.must_equal "Full Throttle"
83
+ song.image.must_equal nil
84
+ song.band.name.must_equal nil
85
+ end
86
+ end
@@ -0,0 +1,83 @@
1
+ require 'test_helper'
2
+
3
+ class SyncOptionTest < MiniTest::Spec
4
+ Band = Struct.new(:name)
5
+ let (:band) { Band.new("Metallica") }
6
+ let (:form) { BandForm.new(band) }
7
+
8
+ # access to :form!
9
+ describe ":sync allows you conditionals" do
10
+ class BandForm < Reform::Form
11
+ property :name, sync: lambda { |value, options| options.user_options[:form].changed?(:name) ? model.name = value : nil } # change if it hasn't changed
12
+ end
13
+
14
+ # don't set name, didn't change.
15
+ it do
16
+ band.instance_exec { def name=(*); raise; end }
17
+ form.validate("name" => "Metallica").must_equal true
18
+ form.sync
19
+ band.name.must_equal "Metallica"
20
+ end
21
+
22
+ # update name.
23
+ it do
24
+ form.validate("name" => "Iron Maiden").must_equal true
25
+ form.sync
26
+ form.name.must_equal "Iron Maiden"
27
+ end
28
+ end
29
+ end
30
+
31
+
32
+ class SyncWithDynamicOptionsTest < MiniTest::Spec
33
+ Song = Struct.new(:id, :title, :length)
34
+
35
+ class SongForm < Reform::Form
36
+ property :id
37
+ property :title, sync: true
38
+ property :length
39
+ end
40
+
41
+ let (:song) { Song.new }
42
+ let (:form) { SongForm.new(song) }
43
+
44
+ # we have access to original input value and outside parameters.
45
+ it do
46
+ form.validate("title" => "A Poor Man's Memory", "length" => 10)
47
+ length_seconds = 120
48
+ form.sync(title: lambda { |value, options| form.model.title = "#{value}: #{length_seconds}" })
49
+
50
+ song.title.must_equal "A Poor Man's Memory: 120"
51
+ song.length.must_equal 10
52
+ song.id.must_equal nil
53
+ end
54
+ end
55
+
56
+
57
+ # :virtual wins over :sync
58
+ # class SyncWithVirtualTest < MiniTest::Spec
59
+ # Song = Struct.new(:title, :image, :band)
60
+ # Band = Struct.new(:name)
61
+
62
+ # let (:form) { HitForm.new(song) }
63
+ # let (:song) { Song.new("Injection", Object, Band.new("Rise Against")) }
64
+
65
+ # class HitForm < Reform::Form
66
+ # include Sync::SkipUnchanged
67
+ # register_feature Sync::SkipUnchanged
68
+
69
+ # property :image, sync: lambda { |value, *| model.image = "processed via :sync: #{value}" }
70
+ # property :band do
71
+ # property :name, sync: lambda { |value, *| model.name = "band, processed: #{value}" }, virtual: true
72
+ # end
73
+ # end
74
+
75
+ # it "abc" do
76
+ # form.validate("image" => "Funny photo of Steve Harris", "band" => {"name" => "Iron Maiden"}).must_equal true
77
+
78
+ # form.sync
79
+ # song.image.must_equal "processed via :sync: Funny photo of Steve Harris"
80
+ # song.band.name.must_equal "Rise Against"
81
+ # end
82
+ # end
83
+
data/test/twin_test.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ require 'test_helper'
4
+ require 'reform/twin'
5
+
6
+ class TwinTest < MiniTest::Spec
7
+ class SongForm < Reform::Form
8
+ class Twin < Disposable::Twin
9
+ property :title
10
+ option :is_online # TODO: this should make it read-only in reform!
11
+ end
12
+
13
+ include Reform::Twin
14
+ twin Twin
15
+ end
16
+
17
+ let (:model) { OpenStruct.new(title: "Kenny") }
18
+
19
+ let (:form) { SongForm.new(model, is_online: true) }
20
+
21
+ it { form.title.must_equal "Kenny" }
22
+ it { form.is_online.must_equal true }
23
+ end
@@ -9,8 +9,11 @@ class ValidateTest < BaseTest
9
9
  "songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"}]
10
10
  }
11
11
  }
12
+ let (:hit) { Song.new }
13
+ let (:song2) { Song.new }
14
+ let (:song1) { Song.new }
12
15
 
13
- subject { AlbumForm.new(Album.new(nil, Song.new, [Song.new, Song.new])) }
16
+ subject { AlbumForm.new(Album.new(nil, hit, [song1, song2])) }
14
17
 
15
18
  before { subject.validate(params) }
16
19
 
@@ -27,6 +30,11 @@ class ValidateTest < BaseTest
27
30
 
28
31
  it { subject.songs[1].must_be_kind_of Reform::Form }
29
32
  it { subject.songs[1].title.must_equal "Roxanne" }
33
+
34
+ # don't touch model.
35
+ it { hit.title.must_equal nil }
36
+ it { song1.title.must_equal nil }
37
+ it { song2.title.must_equal nil }
30
38
  end
31
39
 
32
40
  # TODO: the following tests go to populate_test.rb
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reform
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-09-04 00:00:00.000000000 Z
12
+ date: 2014-10-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: representable
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: 2.0.3
20
+ version: 2.1.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: 2.0.3
27
+ version: 2.1.0
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: disposable
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -101,14 +101,14 @@ dependencies:
101
101
  requirements:
102
102
  - - '='
103
103
  - !ruby/object:Gem::Version
104
- version: 4.2.0
104
+ version: 5.4.1
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - '='
110
110
  - !ruby/object:Gem::Version
111
- version: 4.2.0
111
+ version: 5.4.1
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: activerecord
114
114
  requirement: !ruby/object:Gem::Requirement
@@ -211,26 +211,32 @@ files:
211
211
  - lib/reform/form/active_model.rb
212
212
  - lib/reform/form/active_model/model_validations.rb
213
213
  - lib/reform/form/active_record.rb
214
+ - lib/reform/form/changed.rb
214
215
  - lib/reform/form/coercion.rb
215
216
  - lib/reform/form/composition.rb
217
+ - lib/reform/form/json.rb
218
+ - lib/reform/form/model_reflections.rb
216
219
  - lib/reform/form/module.rb
217
220
  - lib/reform/form/multi_parameter_attributes.rb
218
221
  - lib/reform/form/save.rb
219
222
  - lib/reform/form/scalar.rb
220
223
  - lib/reform/form/sync.rb
221
224
  - lib/reform/form/validate.rb
222
- - lib/reform/form/virtual_attributes.rb
223
225
  - lib/reform/rails.rb
224
226
  - lib/reform/representer.rb
227
+ - lib/reform/schema.rb
228
+ - lib/reform/twin.rb
225
229
  - lib/reform/version.rb
226
230
  - reform.gemspec
227
231
  - test/active_model_test.rb
228
232
  - test/active_record_test.rb
229
233
  - test/as_test.rb
230
234
  - test/builder_test.rb
235
+ - test/changed_test.rb
231
236
  - test/coercion_test.rb
232
237
  - test/composition_test.rb
233
238
  - test/contract_test.rb
239
+ - test/custom_validation_test.rb
234
240
  - test/deserialize_test.rb
235
241
  - test/dummy/Rakefile
236
242
  - test/dummy/app/controllers/albums_controller.rb
@@ -255,19 +261,29 @@ files:
255
261
  - test/dummy/db/test.sqlite3
256
262
  - test/dummy/log/production.log
257
263
  - test/dummy/log/server.log
264
+ - test/empty_test.rb
258
265
  - test/errors_test.rb
259
266
  - test/feature_test.rb
267
+ - test/fields_test.rb
260
268
  - test/form_builder_test.rb
261
269
  - test/form_composition_test.rb
270
+ - test/form_test.rb
262
271
  - test/inherit_test.rb
272
+ - test/model_reflections_test.rb
263
273
  - test/model_validations_test.rb
264
274
  - test/nested_form_test.rb
265
275
  - test/rails/integration_test.rb
276
+ - test/read_only_test.rb
266
277
  - test/reform_test.rb
278
+ - test/representer_test.rb
267
279
  - test/save_test.rb
268
280
  - test/scalar_test.rb
281
+ - test/skip_if_test.rb
282
+ - test/skip_unchanged_test.rb
283
+ - test/sync_option_test.rb
269
284
  - test/sync_test.rb
270
285
  - test/test_helper.rb
286
+ - test/twin_test.rb
271
287
  - test/validate_test.rb
272
288
  homepage: https://github.com/apotonick/reform
273
289
  licenses:
@@ -284,9 +300,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
284
300
  version: '0'
285
301
  required_rubygems_version: !ruby/object:Gem::Requirement
286
302
  requirements:
287
- - - ">="
303
+ - - ">"
288
304
  - !ruby/object:Gem::Version
289
- version: '0'
305
+ version: 1.3.1
290
306
  requirements: []
291
307
  rubyforge_project:
292
308
  rubygems_version: 2.2.2
@@ -299,9 +315,11 @@ test_files:
299
315
  - test/active_record_test.rb
300
316
  - test/as_test.rb
301
317
  - test/builder_test.rb
318
+ - test/changed_test.rb
302
319
  - test/coercion_test.rb
303
320
  - test/composition_test.rb
304
321
  - test/contract_test.rb
322
+ - test/custom_validation_test.rb
305
323
  - test/deserialize_test.rb
306
324
  - test/dummy/Rakefile
307
325
  - test/dummy/app/controllers/albums_controller.rb
@@ -326,17 +344,27 @@ test_files:
326
344
  - test/dummy/db/test.sqlite3
327
345
  - test/dummy/log/production.log
328
346
  - test/dummy/log/server.log
347
+ - test/empty_test.rb
329
348
  - test/errors_test.rb
330
349
  - test/feature_test.rb
350
+ - test/fields_test.rb
331
351
  - test/form_builder_test.rb
332
352
  - test/form_composition_test.rb
353
+ - test/form_test.rb
333
354
  - test/inherit_test.rb
355
+ - test/model_reflections_test.rb
334
356
  - test/model_validations_test.rb
335
357
  - test/nested_form_test.rb
336
358
  - test/rails/integration_test.rb
359
+ - test/read_only_test.rb
337
360
  - test/reform_test.rb
361
+ - test/representer_test.rb
338
362
  - test/save_test.rb
339
363
  - test/scalar_test.rb
364
+ - test/skip_if_test.rb
365
+ - test/skip_unchanged_test.rb
366
+ - test/sync_option_test.rb
340
367
  - test/sync_test.rb
341
368
  - test/test_helper.rb
369
+ - test/twin_test.rb
342
370
  - test/validate_test.rb
@@ -1,22 +0,0 @@
1
- class Reform::Form < Reform::Contract
2
- # TODO: this should be in Representer namespace.
3
- module EmptyAttributesOptions
4
- def options
5
- empty_fields = representable_attrs.
6
- find_all { |d| d[:empty] }.
7
- collect { |d| d.name.to_sym }
8
-
9
- super.exclude!(empty_fields)
10
- end
11
- end
12
-
13
- module ReadonlyAttributesOptions
14
- def options
15
- readonly_fields = representable_attrs.
16
- find_all { |d| d[:virtual] }.
17
- collect { |d| d.name.to_sym }
18
-
19
- super.exclude!(readonly_fields)
20
- end
21
- end
22
- end