reform 1.1.1 → 1.2.0.beta1
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.
- 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
|