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.
- checksums.yaml +4 -4
- data/CHANGES.md +35 -1
- data/Gemfile +1 -1
- data/README.md +83 -21
- data/TODO.md +8 -0
- data/database.sqlite3 +0 -0
- data/gemfiles/Gemfile.rails-4.0 +1 -0
- data/lib/reform.rb +4 -2
- data/lib/reform/active_record.rb +2 -1
- data/lib/reform/composition.rb +2 -2
- data/lib/reform/contract.rb +24 -7
- data/lib/reform/contract/setup.rb +21 -9
- data/lib/reform/contract/validate.rb +0 -6
- data/lib/reform/form.rb +6 -8
- data/lib/reform/form/active_model.rb +3 -2
- data/lib/reform/form/active_model/model_validations.rb +13 -1
- data/lib/reform/form/active_record.rb +1 -7
- data/lib/reform/form/changed.rb +9 -0
- data/lib/reform/form/json.rb +13 -0
- data/lib/reform/form/model_reflections.rb +18 -0
- data/lib/reform/form/save.rb +25 -3
- data/lib/reform/form/scalar.rb +4 -2
- data/lib/reform/form/sync.rb +82 -12
- data/lib/reform/form/validate.rb +38 -0
- data/lib/reform/rails.rb +1 -1
- data/lib/reform/representer.rb +14 -23
- data/lib/reform/schema.rb +23 -0
- data/lib/reform/twin.rb +20 -0
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +2 -2
- data/test/active_model_test.rb +2 -2
- data/test/active_record_test.rb +7 -4
- data/test/changed_test.rb +69 -0
- data/test/custom_validation_test.rb +47 -0
- data/test/deserialize_test.rb +2 -7
- data/test/empty_test.rb +30 -0
- data/test/fields_test.rb +24 -0
- data/test/form_composition_test.rb +24 -2
- data/test/form_test.rb +84 -0
- data/test/inherit_test.rb +12 -0
- data/test/model_reflections_test.rb +65 -0
- data/test/read_only_test.rb +28 -0
- data/test/reform_test.rb +2 -175
- data/test/representer_test.rb +47 -0
- data/test/save_test.rb +51 -1
- data/test/scalar_test.rb +0 -18
- data/test/skip_if_test.rb +62 -0
- data/test/skip_unchanged_test.rb +86 -0
- data/test/sync_option_test.rb +83 -0
- data/test/twin_test.rb +23 -0
- data/test/validate_test.rb +9 -1
- metadata +37 -9
- 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
|
data/test/validate_test.rb
CHANGED
@@ -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,
|
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.
|
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-
|
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
|
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
|
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.
|
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.
|
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:
|
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
|