reform 1.2.6 → 2.0.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.
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