reform 1.2.6 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -1
- data/CHANGES.md +14 -0
- data/Gemfile +3 -2
- data/README.md +225 -283
- data/Rakefile +27 -0
- data/TODO.md +12 -0
- data/database.sqlite3 +0 -0
- data/gemfiles/Gemfile.rails-3.0 +1 -0
- data/gemfiles/Gemfile.rails-3.1 +1 -0
- data/gemfiles/Gemfile.rails-3.2 +1 -0
- data/gemfiles/Gemfile.rails-4.0 +1 -0
- data/lib/reform.rb +0 -1
- data/lib/reform/contract.rb +64 -170
- data/lib/reform/contract/validate.rb +10 -13
- data/lib/reform/form.rb +74 -19
- data/lib/reform/form/active_model.rb +19 -14
- data/lib/reform/form/coercion.rb +1 -13
- data/lib/reform/form/composition.rb +2 -24
- data/lib/reform/form/multi_parameter_attributes.rb +43 -62
- data/lib/reform/form/populator.rb +85 -0
- data/lib/reform/form/prepopulate.rb +13 -43
- data/lib/reform/form/validate.rb +29 -90
- data/lib/reform/form/validation/unique_validator.rb +13 -0
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +7 -7
- data/test/active_model_test.rb +43 -0
- data/test/changed_test.rb +23 -51
- data/test/coercion_test.rb +1 -7
- data/test/composition_test.rb +128 -34
- data/test/contract_test.rb +27 -86
- data/test/feature_test.rb +43 -6
- data/test/fields_test.rb +2 -12
- data/test/form_builder_test.rb +28 -25
- data/test/form_option_test.rb +19 -0
- data/test/from_test.rb +0 -75
- data/test/inherit_test.rb +178 -117
- data/test/model_reflections_test.rb +1 -1
- data/test/populate_test.rb +226 -0
- data/test/prepopulator_test.rb +112 -0
- data/test/readable_test.rb +2 -4
- data/test/save_test.rb +56 -112
- data/test/setup_test.rb +48 -0
- data/test/skip_if_test.rb +5 -2
- data/test/skip_setter_and_getter_test.rb +54 -0
- data/test/test_helper.rb +3 -1
- data/test/uniqueness_test.rb +41 -0
- data/test/validate_test.rb +325 -289
- data/test/virtual_test.rb +1 -3
- data/test/writeable_test.rb +3 -4
- metadata +35 -39
- data/lib/reform/composition.rb +0 -63
- data/lib/reform/contract/setup.rb +0 -50
- data/lib/reform/form/changed.rb +0 -9
- data/lib/reform/form/sync.rb +0 -116
- data/lib/reform/representer.rb +0 -84
- data/test/empty_test.rb +0 -58
- data/test/form_composition_test.rb +0 -145
- data/test/nested_form_test.rb +0 -197
- data/test/prepopulate_test.rb +0 -85
- data/test/sync_option_test.rb +0 -83
- data/test/sync_test.rb +0 -56
data/test/feature_test.rb
CHANGED
@@ -1,18 +1,55 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class FeatureInheritanceTest < BaseTest
|
4
|
+
Song = Struct.new(:title, :album, :composer)
|
5
|
+
Album = Struct.new(:name, :songs, :artist)
|
6
|
+
Artist = Struct.new(:name)
|
7
|
+
|
8
|
+
module Date
|
9
|
+
def date
|
10
|
+
"May 16"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(base)
|
14
|
+
base.representer_class.representable_attrs.features << self # TODO: register_feature
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# module Name
|
19
|
+
# def name
|
20
|
+
# "Violins"
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
|
4
24
|
class AlbumForm < Reform::Form
|
5
|
-
#
|
6
|
-
|
7
|
-
# include MultiParameterAttributes
|
25
|
+
feature Date # feature.
|
26
|
+
property :name
|
8
27
|
|
9
|
-
|
10
|
-
property :
|
28
|
+
collection :songs do
|
29
|
+
property :title
|
30
|
+
|
31
|
+
property :composer do
|
32
|
+
property :name
|
11
33
|
end
|
12
34
|
end
|
35
|
+
|
36
|
+
property :artist do
|
37
|
+
property :name
|
38
|
+
end
|
13
39
|
end
|
14
40
|
|
15
|
-
|
41
|
+
let (:song) { Song.new("Broken") }
|
42
|
+
let (:song_with_composer) { Song.new("Resist Stance", nil, composer) }
|
43
|
+
let (:composer) { Artist.new("Greg Graffin") }
|
44
|
+
let (:artist) { Artist.new("Bad Religion") }
|
45
|
+
let (:album) { Album.new("The Dissent Of Man", [song, song_with_composer], artist) }
|
46
|
+
|
47
|
+
let (:form) { AlbumForm.new(album) }
|
48
|
+
|
49
|
+
it do
|
50
|
+
form.date.must_equal "May 16"
|
51
|
+
form.songs[0].date.must_equal "May 16"
|
52
|
+
end
|
16
53
|
|
17
54
|
# it { subject.class.include?(Reform::Form::ActiveModel) }
|
18
55
|
# it { subject.class.include?(Reform::Form::Coercion) }
|
data/test/fields_test.rb
CHANGED
@@ -6,19 +6,9 @@ class FieldsTest < MiniTest::Spec
|
|
6
6
|
fields = Reform::Contract::Fields.new([:name, :title])
|
7
7
|
fields.name.must_equal nil
|
8
8
|
fields.title.must_equal nil
|
9
|
-
end
|
10
9
|
|
11
|
-
|
12
|
-
fields
|
13
|
-
fields.name.must_equal nil
|
14
|
-
fields.title.must_equal "The Body"
|
15
|
-
end
|
16
|
-
|
17
|
-
it "processes value syms" do
|
18
|
-
skip "we don't need to test this as representer.to_hash always returns strings"
|
19
|
-
fields = Reform::Fields.new(["name", "title"], :title => "The Body")
|
20
|
-
fields.name.must_equal nil
|
21
|
-
fields.title.must_equal "The Body"
|
10
|
+
fields.title= "Planet X"
|
11
|
+
fields.title.must_equal "Planet X"
|
22
12
|
end
|
23
13
|
end
|
24
14
|
end
|
data/test/form_builder_test.rb
CHANGED
@@ -1,37 +1,39 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class FormBuilderCompatTest < BaseTest
|
4
|
-
|
5
|
-
|
6
|
-
include Reform::Form::ActiveModel::FormBuilderMethods
|
4
|
+
class AlbumForm < Reform::Form
|
5
|
+
feature Reform::Form::ActiveModel::FormBuilderMethods
|
7
6
|
|
8
|
-
|
9
|
-
property :name
|
10
|
-
validates :name, :presence => true
|
11
|
-
end
|
7
|
+
feature Reform::Form::MultiParameterAttributes
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
9
|
+
property :artist do
|
10
|
+
property :name
|
11
|
+
validates :name, :presence => true
|
12
|
+
end
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
collection :songs do
|
15
|
+
feature Reform::Form::ActiveModel::FormBuilderMethods
|
16
|
+
property :title
|
17
|
+
property :release_date, :multi_params => true
|
18
|
+
validates :title, :presence => true
|
19
|
+
end
|
22
20
|
|
23
|
-
|
21
|
+
class LabelForm < Reform::Form
|
22
|
+
property :name
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
property :label, form: LabelForm
|
26
|
+
|
27
|
+
property :band do
|
28
|
+
property :label do
|
29
|
+
property :name
|
29
30
|
end
|
30
31
|
end
|
31
|
-
|
32
|
+
end
|
33
|
+
|
32
34
|
|
33
35
|
let (:song) { OpenStruct.new }
|
34
|
-
let (:form) {
|
36
|
+
let (:form) { AlbumForm.new(OpenStruct.new(
|
35
37
|
:artist => Artist.new(:name => "Propagandhi"),
|
36
38
|
:songs => [song],
|
37
39
|
:label => OpenStruct.new,
|
@@ -40,9 +42,10 @@ class FormBuilderCompatTest < BaseTest
|
|
40
42
|
)) }
|
41
43
|
|
42
44
|
it "respects _attributes params hash" do
|
43
|
-
form.validate(
|
44
|
-
"
|
45
|
-
"
|
45
|
+
form.validate(
|
46
|
+
"artist_attributes" => {"name" => "Blink 182"},
|
47
|
+
"songs_attributes" => {"0" => {"title" => "Damnit"}},
|
48
|
+
"band_attributes" => {"label_attributes" => {"name" => "Epitaph"}})
|
46
49
|
|
47
50
|
form.artist.name.must_equal "Blink 182"
|
48
51
|
form.songs.first.title.must_equal "Damnit"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FormOptionTest < MiniTest::Spec
|
4
|
+
Song = Struct.new(:title)
|
5
|
+
Album = Struct.new(:song)
|
6
|
+
|
7
|
+
class SongForm < Reform::Form
|
8
|
+
property :title
|
9
|
+
validates_presence_of :title
|
10
|
+
end
|
11
|
+
|
12
|
+
class AlbumForm < Reform::Form
|
13
|
+
property :song, form: SongForm
|
14
|
+
end
|
15
|
+
|
16
|
+
it do
|
17
|
+
AlbumForm.new(Album.new(Song.new("When It Comes To You"))).song.title.must_equal "When It Comes To You"
|
18
|
+
end
|
19
|
+
end
|
data/test/from_test.rb
CHANGED
@@ -73,78 +73,3 @@ class AsTest < BaseTest
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
76
|
-
|
77
|
-
|
78
|
-
class AsREMOVEMEin20Test < BaseTest # TODO: remove me in 2.0.
|
79
|
-
class AlbumForm < Reform::Form
|
80
|
-
property :name, as: :title
|
81
|
-
|
82
|
-
property :single, as: :hit do
|
83
|
-
property :title
|
84
|
-
end
|
85
|
-
|
86
|
-
collection :tracks, as: :songs do
|
87
|
-
property :name, as: :title
|
88
|
-
end
|
89
|
-
|
90
|
-
property :band do
|
91
|
-
property :company, as: :label do
|
92
|
-
property :business, as: :name
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
let (:song2) { Song.new("Roxanne") }
|
98
|
-
|
99
|
-
let (:params) {
|
100
|
-
{
|
101
|
-
"name" => "Best Of The Police",
|
102
|
-
"single" => {"title" => "So Lonely"},
|
103
|
-
"tracks" => [{"name" => "Message In A Bottle"}, {"name" => "Roxanne"}]
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
subject { AlbumForm.new(Album.new("Best Of", hit, [Song.new("Fallout"), song2])) }
|
108
|
-
|
109
|
-
it { subject.name.must_equal "Best Of" }
|
110
|
-
it { subject.single.title.must_equal "Roxanne" }
|
111
|
-
it { subject.tracks[0].name.must_equal "Fallout" }
|
112
|
-
it { subject.tracks[1].name.must_equal "Roxanne" }
|
113
|
-
|
114
|
-
|
115
|
-
describe "#validate" do
|
116
|
-
|
117
|
-
|
118
|
-
before { subject.validate(params) }
|
119
|
-
|
120
|
-
it { subject.name.must_equal "Best Of The Police" }
|
121
|
-
it { subject.single.title.must_equal "So Lonely" }
|
122
|
-
it { subject.tracks[0].name.must_equal "Message In A Bottle" }
|
123
|
-
it { subject.tracks[1].name.must_equal "Roxanne" }
|
124
|
-
end
|
125
|
-
|
126
|
-
|
127
|
-
describe "#sync" do
|
128
|
-
before {
|
129
|
-
subject.tracks[1].name = "Livin' Ain't No Crime"
|
130
|
-
subject.sync
|
131
|
-
}
|
132
|
-
|
133
|
-
it { song2.title.must_equal "Livin' Ain't No Crime" }
|
134
|
-
end
|
135
|
-
|
136
|
-
|
137
|
-
describe "#save (nested hash)" do
|
138
|
-
before { subject.validate(params) }
|
139
|
-
|
140
|
-
it do
|
141
|
-
hash = nil
|
142
|
-
|
143
|
-
subject.save do |nested_hash|
|
144
|
-
hash = nested_hash
|
145
|
-
end
|
146
|
-
|
147
|
-
hash.must_equal({"title"=>"Best Of The Police", "hit"=>{"title"=>"So Lonely"}, "songs"=>[{"title"=>"Message In A Bottle"}, {"title"=>"Roxanne"}]})
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
data/test/inherit_test.rb
CHANGED
@@ -3,26 +3,50 @@ require 'representable/json'
|
|
3
3
|
|
4
4
|
class InheritTest < BaseTest
|
5
5
|
class AlbumForm < Reform::Form
|
6
|
-
property :title
|
6
|
+
property :title, deserializer: {instance: "Instance"}, skip_if: "skip_if in AlbumForm" # allow direct configuration of :deserializer.
|
7
|
+
# puts "[#{options_for(:title)[:deserializer].object_id}] ALB@@@@@ #{options_for(:title)[:deserializer].inspect}"
|
7
8
|
|
8
|
-
property :hit do
|
9
|
+
property :hit, populator: "Populator" do
|
9
10
|
property :title
|
10
11
|
end
|
11
12
|
|
12
|
-
collection :songs do
|
13
|
+
collection :songs, populate_if_empty: lambda {}, skip_if: :all_blank do
|
13
14
|
property :title
|
14
15
|
end
|
15
|
-
end
|
16
16
|
|
17
|
-
|
17
|
+
property :artist, populate_if_empty: lambda {} do
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
def artist_id
|
20
|
+
1
|
21
|
+
end
|
22
22
|
end
|
23
|
+
end
|
24
|
+
|
25
|
+
puts
|
26
|
+
puts "inherit"
|
27
|
+
|
28
|
+
class CompilationForm < AlbumForm
|
29
|
+
property :title, inherit: true, skip_if: "skip_if from CompilationForm"
|
30
|
+
puts "[#{options_for(:title)[:deserializer].object_id}] COM@@@@@ #{options_for(:title)[:deserializer].inspect}"
|
31
|
+
# property :hit, :inherit => true do
|
32
|
+
# property :rating
|
33
|
+
# validates :title, :rating, :presence => true
|
34
|
+
# end
|
23
35
|
|
24
36
|
# puts representer_class.representable_attrs.
|
25
37
|
# get(:hit)[:extend].evaluate(nil).new(OpenStruct.new).rating
|
38
|
+
|
39
|
+
# NO collection here, this is entirely inherited.
|
40
|
+
# collection :songs, ..
|
41
|
+
|
42
|
+
property :artist, inherit: true do # inherit everything, but explicitely.
|
43
|
+
end
|
44
|
+
|
45
|
+
# completely override.
|
46
|
+
property :hit, skip_if: "SkipParse" do
|
47
|
+
end
|
48
|
+
|
49
|
+
# override partly.
|
26
50
|
end
|
27
51
|
|
28
52
|
let (:album) { Album.new(nil, OpenStruct.new(:hit => OpenStruct.new()) ) }
|
@@ -30,146 +54,183 @@ class InheritTest < BaseTest
|
|
30
54
|
|
31
55
|
|
32
56
|
# valid.
|
33
|
-
it {
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
}
|
39
|
-
|
40
|
-
it do
|
41
|
-
subject.validate({})
|
42
|
-
subject.hit.title.must_equal nil
|
43
|
-
subject.hit.rating.must_equal nil
|
44
|
-
subject.errors.messages.must_equal({:"hit.title"=>["can't be blank"], :"hit.rating"=>["can't be blank"]})
|
45
|
-
end
|
46
|
-
end
|
57
|
+
# it {
|
58
|
+
# subject.validate("hit" => {"title" => "LA Drone", "rating" => 10})
|
59
|
+
# subject.hit.title.must_equal "LA Drone"
|
60
|
+
# subject.hit.rating.must_equal 10
|
61
|
+
# subject.errors.messages.must_equal({})
|
62
|
+
# }
|
47
63
|
|
64
|
+
# it do
|
65
|
+
# subject.validate({})
|
66
|
+
# subject.hit.title.must_equal nil
|
67
|
+
# subject.hit.rating.must_equal nil
|
68
|
+
# subject.errors.messages.must_equal({:"hit.title"=>["can't be blank"], :"hit.rating"=>["can't be blank"]})
|
69
|
+
# end
|
48
70
|
|
49
|
-
require
|
50
|
-
class ModuleInclusionTest < MiniTest::Spec
|
51
|
-
module BandPropertyForm
|
52
|
-
include Reform::Form::Module
|
71
|
+
require "pp"
|
53
72
|
|
54
|
-
|
55
|
-
|
73
|
+
it "xxx" do
|
74
|
+
# sub hashes like :deserializer must be properly cloned when inheriting.
|
75
|
+
AlbumForm.options_for(:title)[:deserializer].object_id.wont_equal CompilationForm.options_for(:title)[:deserializer].object_id
|
56
76
|
|
57
|
-
|
77
|
+
# don't overwrite direct deserializer: {} configuration.
|
78
|
+
AlbumForm.options_for(:title)[:deserializer][:instance].must_equal "Instance"
|
79
|
+
AlbumForm.options_for(:title)[:deserializer][:skip_parse].must_equal "skip_if in AlbumForm"
|
58
80
|
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
81
|
+
AlbumForm.options_for(:hit)[:deserializer][:instance].inspect.must_match /Reform::Form::Populator:.+ @user_proc="Populator"/
|
82
|
+
# AlbumForm.options_for(:hit)[:deserializer][:instance].inspect.must_be_instance_with Reform::Form::Populator, user_proc: "Populator"
|
63
83
|
|
64
|
-
def id # gets mixed into Form, too.
|
65
|
-
1
|
66
|
-
end
|
67
84
|
|
68
|
-
|
85
|
+
AlbumForm.options_for(:songs)[:deserializer][:instance].must_be_instance_of Reform::Form::Populator::IfEmpty
|
86
|
+
AlbumForm.options_for(:songs)[:deserializer][:skip_parse].must_be_instance_of Reform::Form::Validate::Skip::AllBlank
|
69
87
|
|
70
|
-
|
71
|
-
end
|
88
|
+
AlbumForm.options_for(:artist)[:deserializer][:instance].must_be_instance_of Reform::Form::Populator::IfEmpty
|
72
89
|
|
73
|
-
# TODO: test if works, move stuff into inherit_schema!
|
74
|
-
module AirplaysPropertyForm
|
75
|
-
include Reform::Form::Module
|
76
90
|
|
77
|
-
collection :airplays do
|
78
|
-
property :station
|
79
|
-
validates :station, :presence => true
|
80
|
-
end
|
81
|
-
validates :airplays, :presence => true
|
82
|
-
end
|
83
91
|
|
92
|
+
CompilationForm.options_for(:title)[:deserializer][:skip_parse].must_equal "skip_if from CompilationForm"
|
93
|
+
# pp CompilationForm.options_for(:songs)
|
94
|
+
CompilationForm.options_for(:songs)[:deserializer][:instance].must_be_instance_of Reform::Form::Populator::IfEmpty
|
84
95
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
96
|
+
CompilationForm.options_for(:artist)[:deserializer][:instance].must_be_instance_of Reform::Form::Populator::IfEmpty
|
97
|
+
|
98
|
+
# completely overwrite inherited.
|
99
|
+
CompilationForm.options_for(:hit)[:deserializer][:instance].must_be_instance_of Reform::Form::Populator::Sync # reset to default.
|
100
|
+
CompilationForm.options_for(:hit)[:deserializer][:skip_parse].must_equal "SkipParse"
|
90
101
|
|
91
|
-
class SongForm < Reform::Form
|
92
|
-
property :title
|
93
102
|
|
94
|
-
|
103
|
+
# inherit: true with block will still inherit the original class.
|
104
|
+
AlbumForm.new(OpenStruct.new(artist: OpenStruct.new)).artist.artist_id.must_equal 1
|
105
|
+
CompilationForm.new(OpenStruct.new(artist: OpenStruct.new)).artist.artist_id.must_equal 1
|
95
106
|
end
|
107
|
+
end
|
96
108
|
|
97
109
|
|
98
|
-
|
110
|
+
# require 'reform/form/coercion'
|
111
|
+
# class ModuleInclusionTest < MiniTest::Spec
|
112
|
+
# module BandPropertyForm
|
113
|
+
# include Reform::Form::Module
|
99
114
|
|
100
|
-
|
101
|
-
|
115
|
+
# property :band do
|
116
|
+
# property :title
|
102
117
|
|
103
|
-
|
104
|
-
it { SongForm.new(song).id.must_equal 1 }
|
105
|
-
it { SongForm.new(song).band.id.must_equal 2 }
|
118
|
+
# validates :title, :presence => true
|
106
119
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
form.errors.messages.must_equal({:band=>["can't be blank"]})
|
112
|
-
end
|
120
|
+
# def id # gets mixed into Form, too.
|
121
|
+
# 2
|
122
|
+
# end
|
123
|
+
# end
|
113
124
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
form.validate({:cool => "1"})
|
118
|
-
form.cool.must_equal true
|
119
|
-
end
|
125
|
+
# def id # gets mixed into Form, too.
|
126
|
+
# 1
|
127
|
+
# end
|
120
128
|
|
129
|
+
# validates :band, :presence => true
|
121
130
|
|
122
|
-
|
123
|
-
|
124
|
-
include Reform::Form::Module
|
125
|
-
include BandPropertyForm
|
131
|
+
# property :cool, type: Virtus::Attribute::Boolean # test coercion.
|
132
|
+
# end
|
126
133
|
|
127
|
-
|
128
|
-
|
129
|
-
|
134
|
+
# # TODO: test if works, move stuff into inherit_schema!
|
135
|
+
# module AirplaysPropertyForm
|
136
|
+
# include Reform::Form::Module
|
130
137
|
|
131
|
-
|
132
|
-
|
138
|
+
# collection :airplays do
|
139
|
+
# property :station
|
140
|
+
# validates :station, :presence => true
|
141
|
+
# end
|
142
|
+
# validates :airplays, :presence => true
|
143
|
+
# end
|
133
144
|
|
134
|
-
property :band, :inherit => true do
|
135
|
-
property :label
|
136
|
-
validates :label, :presence => true
|
137
|
-
end
|
138
|
-
end
|
139
|
-
# puts "......"+ AlbumForm.representer_class.representable_attrs.get(:band).inspect
|
140
145
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
+
# # test:
|
147
|
+
# # by including BandPropertyForm into multiple classes we assure that options hashes don't get messed up by AM:V.
|
148
|
+
# class HitForm < Reform::Form
|
149
|
+
# include BandPropertyForm
|
150
|
+
# end
|
146
151
|
|
152
|
+
# class SongForm < Reform::Form
|
153
|
+
# property :title
|
147
154
|
|
148
|
-
|
149
|
-
|
150
|
-
include Representable
|
155
|
+
# include BandPropertyForm
|
156
|
+
# end
|
151
157
|
|
152
|
-
property :title
|
153
|
-
property :manager do
|
154
|
-
property :title
|
155
|
-
end
|
156
|
-
end
|
157
158
|
|
158
|
-
|
159
|
-
property :location
|
159
|
+
# let (:song) { OpenStruct.new(:band => OpenStruct.new(:title => "Time Again")) }
|
160
160
|
|
161
|
-
|
162
|
-
|
163
|
-
property :manager, :inherit => true do
|
164
|
-
validates :title, :presence => true
|
165
|
-
end
|
166
|
-
end
|
167
|
-
puts "......"+ LabelForm.representer_class.representable_attrs.get(:title).inspect
|
161
|
+
# # nested form from module is present and creates accessor.
|
162
|
+
# it { SongForm.new(song).band.title.must_equal "Time Again" }
|
168
163
|
|
164
|
+
# # methods from module get included.
|
165
|
+
# it { SongForm.new(song).id.must_equal 1 }
|
166
|
+
# it { SongForm.new(song).band.id.must_equal 2 }
|
169
167
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
end
|
168
|
+
# # validators get inherited.
|
169
|
+
# it do
|
170
|
+
# form = SongForm.new(OpenStruct.new)
|
171
|
+
# form.validate({})
|
172
|
+
# form.errors.messages.must_equal({:band=>["can't be blank"]})
|
173
|
+
# end
|
174
|
+
|
175
|
+
# # coercion works
|
176
|
+
# it do
|
177
|
+
# form = SongForm.new(OpenStruct.new)
|
178
|
+
# form.validate({:cool => "1"})
|
179
|
+
# form.cool.must_equal true
|
180
|
+
# end
|
181
|
+
|
182
|
+
|
183
|
+
# # include a module into a module into a class :)
|
184
|
+
# module AlbumFormModule
|
185
|
+
# include Reform::Form::Module
|
186
|
+
# include BandPropertyForm
|
187
|
+
|
188
|
+
# property :name
|
189
|
+
# validates :name, :presence => true
|
190
|
+
# end
|
191
|
+
|
192
|
+
# class AlbumForm < Reform::Form
|
193
|
+
# include AlbumFormModule
|
194
|
+
|
195
|
+
# property :band, :inherit => true do
|
196
|
+
# property :label
|
197
|
+
# validates :label, :presence => true
|
198
|
+
# end
|
199
|
+
# end
|
200
|
+
# # puts "......"+ AlbumForm.representer_class.representable_attrs.get(:band).inspect
|
201
|
+
|
202
|
+
# it do
|
203
|
+
# form = AlbumForm.new(OpenStruct.new(:band => OpenStruct.new))
|
204
|
+
# form.validate({"band" => {}})
|
205
|
+
# form.errors.messages.must_equal({:"band.title"=>["can't be blank"], :"band.label"=>["can't be blank"], :name=>["can't be blank"]})
|
206
|
+
# end
|
207
|
+
|
208
|
+
|
209
|
+
# # including representer into form
|
210
|
+
# module GenericRepresenter
|
211
|
+
# include Representable
|
212
|
+
|
213
|
+
# property :title
|
214
|
+
# property :manager do
|
215
|
+
# property :title
|
216
|
+
# end
|
217
|
+
# end
|
218
|
+
|
219
|
+
# class LabelForm < Reform::Form
|
220
|
+
# property :location
|
221
|
+
|
222
|
+
# include GenericRepresenter
|
223
|
+
# validates :title, :presence => true
|
224
|
+
# property :manager, :inherit => true do
|
225
|
+
# validates :title, :presence => true
|
226
|
+
# end
|
227
|
+
# end
|
228
|
+
# puts "......"+ LabelForm.representer_class.representable_attrs.get(:title).inspect
|
229
|
+
|
230
|
+
|
231
|
+
# it do
|
232
|
+
# form = LabelForm.new(OpenStruct.new(:manager => OpenStruct.new))
|
233
|
+
# form.validate({"manager" => {}, "title"=>""}) # it's important to pass both nested and scalar here!
|
234
|
+
# form.errors.messages.must_equal(:title=>["can't be blank"], :"manager.title"=>["can't be blank"], )
|
235
|
+
# end
|
236
|
+
# end
|