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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -1
  3. data/CHANGES.md +14 -0
  4. data/Gemfile +3 -2
  5. data/README.md +225 -283
  6. data/Rakefile +27 -0
  7. data/TODO.md +12 -0
  8. data/database.sqlite3 +0 -0
  9. data/gemfiles/Gemfile.rails-3.0 +1 -0
  10. data/gemfiles/Gemfile.rails-3.1 +1 -0
  11. data/gemfiles/Gemfile.rails-3.2 +1 -0
  12. data/gemfiles/Gemfile.rails-4.0 +1 -0
  13. data/lib/reform.rb +0 -1
  14. data/lib/reform/contract.rb +64 -170
  15. data/lib/reform/contract/validate.rb +10 -13
  16. data/lib/reform/form.rb +74 -19
  17. data/lib/reform/form/active_model.rb +19 -14
  18. data/lib/reform/form/coercion.rb +1 -13
  19. data/lib/reform/form/composition.rb +2 -24
  20. data/lib/reform/form/multi_parameter_attributes.rb +43 -62
  21. data/lib/reform/form/populator.rb +85 -0
  22. data/lib/reform/form/prepopulate.rb +13 -43
  23. data/lib/reform/form/validate.rb +29 -90
  24. data/lib/reform/form/validation/unique_validator.rb +13 -0
  25. data/lib/reform/version.rb +1 -1
  26. data/reform.gemspec +7 -7
  27. data/test/active_model_test.rb +43 -0
  28. data/test/changed_test.rb +23 -51
  29. data/test/coercion_test.rb +1 -7
  30. data/test/composition_test.rb +128 -34
  31. data/test/contract_test.rb +27 -86
  32. data/test/feature_test.rb +43 -6
  33. data/test/fields_test.rb +2 -12
  34. data/test/form_builder_test.rb +28 -25
  35. data/test/form_option_test.rb +19 -0
  36. data/test/from_test.rb +0 -75
  37. data/test/inherit_test.rb +178 -117
  38. data/test/model_reflections_test.rb +1 -1
  39. data/test/populate_test.rb +226 -0
  40. data/test/prepopulator_test.rb +112 -0
  41. data/test/readable_test.rb +2 -4
  42. data/test/save_test.rb +56 -112
  43. data/test/setup_test.rb +48 -0
  44. data/test/skip_if_test.rb +5 -2
  45. data/test/skip_setter_and_getter_test.rb +54 -0
  46. data/test/test_helper.rb +3 -1
  47. data/test/uniqueness_test.rb +41 -0
  48. data/test/validate_test.rb +325 -289
  49. data/test/virtual_test.rb +1 -3
  50. data/test/writeable_test.rb +3 -4
  51. metadata +35 -39
  52. data/lib/reform/composition.rb +0 -63
  53. data/lib/reform/contract/setup.rb +0 -50
  54. data/lib/reform/form/changed.rb +0 -9
  55. data/lib/reform/form/sync.rb +0 -116
  56. data/lib/reform/representer.rb +0 -84
  57. data/test/empty_test.rb +0 -58
  58. data/test/form_composition_test.rb +0 -145
  59. data/test/nested_form_test.rb +0 -197
  60. data/test/prepopulate_test.rb +0 -85
  61. data/test/sync_option_test.rb +0 -83
  62. 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
- # include Reform::Form::ActiveModel
6
- # include Coercion
7
- # include MultiParameterAttributes
25
+ feature Date # feature.
26
+ property :name
8
27
 
9
- property :band do
10
- property :label do
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
- subject { AlbumForm.new(Album.new(nil, nil, nil, Band.new(Label.new))) }
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
- it "accepts list of properties and values" do
12
- fields = Reform::Contract::Fields.new(["name", "title"], "title" => "The Body")
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
@@ -1,37 +1,39 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class FormBuilderCompatTest < BaseTest
4
- let (:form_class) {
5
- Class.new(Reform::Form) do
6
- include Reform::Form::ActiveModel::FormBuilderMethods
4
+ class AlbumForm < Reform::Form
5
+ feature Reform::Form::ActiveModel::FormBuilderMethods
7
6
 
8
- property :artist do
9
- property :name
10
- validates :name, :presence => true
11
- end
7
+ feature Reform::Form::MultiParameterAttributes
12
8
 
13
- collection :songs do
14
- property :title
15
- property :release_date, :multi_params => true
16
- validates :title, :presence => true
17
- end
9
+ property :artist do
10
+ property :name
11
+ validates :name, :presence => true
12
+ end
18
13
 
19
- class LabelForm < Reform::Form
20
- property :name
21
- end
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
- property :label, :form => LabelForm
21
+ class LabelForm < Reform::Form
22
+ property :name
23
+ end
24
24
 
25
- property :band do
26
- property :label do
27
- property :name
28
- end
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) { form_class.new(OpenStruct.new(
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("artist_attributes" => {"name" => "Blink 182"},
44
- "songs_attributes" => {"0" => {"title" => "Damnit"}},
45
- "band_attributes" => {"label_attributes" => {"name" => "Epitaph"}})
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
- class CompilationForm < AlbumForm
17
+ property :artist, populate_if_empty: lambda {} do
18
18
 
19
- property :hit, :inherit => true do
20
- property :rating
21
- validates :title, :rating, :presence => true
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
- subject.validate("hit" => {"title" => "LA Drone", "rating" => 10})
35
- subject.hit.title.must_equal "LA Drone"
36
- subject.hit.rating.must_equal 10
37
- subject.errors.messages.must_equal({})
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 'reform/form/coercion'
50
- class ModuleInclusionTest < MiniTest::Spec
51
- module BandPropertyForm
52
- include Reform::Form::Module
71
+ require "pp"
53
72
 
54
- property :band do
55
- property :title
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
- validates :title, :presence => true
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
- def id # gets mixed into Form, too.
60
- 2
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
- validates :band, :presence => true
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
- property :cool, type: Virtus::Attribute::Boolean # test coercion.
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
- # test:
86
- # by including BandPropertyForm into multiple classes we assure that options hashes don't get messed up by AM:V.
87
- class HitForm < Reform::Form
88
- include BandPropertyForm
89
- end
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
- include BandPropertyForm
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
- let (:song) { OpenStruct.new(:band => OpenStruct.new(:title => "Time Again")) }
110
+ # require 'reform/form/coercion'
111
+ # class ModuleInclusionTest < MiniTest::Spec
112
+ # module BandPropertyForm
113
+ # include Reform::Form::Module
99
114
 
100
- # nested form from module is present and creates accessor.
101
- it { SongForm.new(song).band.title.must_equal "Time Again" }
115
+ # property :band do
116
+ # property :title
102
117
 
103
- # methods from module get included.
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
- # validators get inherited.
108
- it do
109
- form = SongForm.new(OpenStruct.new)
110
- form.validate({})
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
- # coercion works
115
- it do
116
- form = SongForm.new(OpenStruct.new)
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
- # include a module into a module into a class :)
123
- module AlbumFormModule
124
- include Reform::Form::Module
125
- include BandPropertyForm
131
+ # property :cool, type: Virtus::Attribute::Boolean # test coercion.
132
+ # end
126
133
 
127
- property :name
128
- validates :name, :presence => true
129
- end
134
+ # # TODO: test if works, move stuff into inherit_schema!
135
+ # module AirplaysPropertyForm
136
+ # include Reform::Form::Module
130
137
 
131
- class AlbumForm < Reform::Form
132
- include AlbumFormModule
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
- it do
142
- form = AlbumForm.new(OpenStruct.new(:band => OpenStruct.new))
143
- form.validate({"band" => {}})
144
- form.errors.messages.must_equal({:"band.title"=>["can't be blank"], :"band.label"=>["can't be blank"], :name=>["can't be blank"]})
145
- end
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
- # including representer into form
149
- module GenericRepresenter
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
- class LabelForm < Reform::Form
159
- property :location
159
+ # let (:song) { OpenStruct.new(:band => OpenStruct.new(:title => "Time Again")) }
160
160
 
161
- include GenericRepresenter
162
- validates :title, :presence => true
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
- it do
171
- form = LabelForm.new(OpenStruct.new(:manager => OpenStruct.new))
172
- form.validate({"manager" => {}, "title"=>""}) # it's important to pass both nested and scalar here!
173
- form.errors.messages.must_equal(:title=>["can't be blank"], :"manager.title"=>["can't be blank"], )
174
- end
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