reform 2.0.0.beta2 → 2.0.0.rc1
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 +1 -0
- data/Gemfile +1 -1
- data/README.md +3 -0
- data/Rakefile +19 -18
- data/database.sqlite3 +0 -0
- data/lib/reform/contract.rb +0 -16
- data/lib/reform/form.rb +0 -4
- data/lib/reform/form/active_record.rb +1 -1
- data/lib/reform/form/model_reflections.rb +1 -1
- data/lib/reform/form/module.rb +2 -1
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +1 -1
- data/test/active_record_test.rb +3 -37
- data/test/inherit_test.rb +1 -130
- data/test/module_test.rb +130 -0
- data/test/populate_test.rb +2 -1
- data/test/reform_test.rb +1 -30
- data/test/twin_test.rb +28 -13
- metadata +6 -12
- data/test/fields_test.rb +0 -14
- data/test/representer_test.rb +0 -47
- data/test/scalar_test.rb +0 -167
- data/test/skip_unchanged_test.rb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 981ddfe5d276177430c4441c81e38f8d1bc89166
|
4
|
+
data.tar.gz: 269eeca94c1c7636e4ff8fd73df5e2c6bccc459c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 165337839adaf02e97f805f05974a2ce9b8b1950f848493a1feabbb5ce708c3877e7bb6f59c7d0f5ab088f36ddfc10c3b4069cbed2ada2ba95909a360c0d705d
|
7
|
+
data.tar.gz: c7cf74f86eebc98c0810299fbaa179715b2bf92ba02d666f8658a116323d8b3b637fb9cf36361612f673abe1e5aa9541d04b1606d674f758fcc264d165d0f23c
|
data/CHANGES.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
## 2.0.0
|
2
2
|
|
3
3
|
* The `::reform_2_0!` is no longer there. Guess why.
|
4
|
+
* Again: `:empty` doesn't exist anymore. You can choose from `:readable`, `:writeable` and `:virtual`.
|
4
5
|
* :populator => lambda { |fragment, index, args|
|
5
6
|
# songs[index] or songs[index] = args.binding[:form].new(Song.new)
|
6
7
|
# }
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -10,6 +10,7 @@ Although reform can be used in any Ruby framework, it comes with [Rails support]
|
|
10
10
|
|
11
11
|
Temporary note: This is the README and API for Reform 2. On the public API, only a few tiny things have changed. When in trouble, join us on the IRC (Freenode) #trailblazer channel.
|
12
12
|
|
13
|
+
[Full documentation for Reform](http://trailblazerb.org/gems/reform) is available online, or support us and grab the [Trailblazer book](https://leanpub.com/trailblazer).
|
13
14
|
|
14
15
|
## Disposable
|
15
16
|
|
@@ -527,6 +528,8 @@ end
|
|
527
528
|
|
528
529
|
Note that you can also override properties [using inheritance](#inheritance) in Reform.
|
529
530
|
|
531
|
+
When using coercion, make sure the including form already contains the `Coercion` module.
|
532
|
+
|
530
533
|
|
531
534
|
## Inheritance
|
532
535
|
|
data/Rakefile
CHANGED
@@ -6,31 +6,32 @@ Rake::TestTask.new(:test) do |test|
|
|
6
6
|
test.libs << 'test'
|
7
7
|
test.test_files = FileList['test/*_test.rb']
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
# test.test_files = ["test/changed_test.rb",
|
10
|
+
# "test/coercion_test.rb",
|
11
|
+
# "test/feature_test.rb",
|
12
12
|
|
13
|
-
|
13
|
+
# "test/contract_test.rb",
|
14
14
|
|
15
|
-
|
15
|
+
# "test/populate_test.rb", "test/prepopulator_test.rb",
|
16
16
|
|
17
|
-
|
17
|
+
# "test/readable_test.rb","test/setup_test.rb","test/skip_if_test.rb",
|
18
18
|
|
19
|
-
|
19
|
+
# "test/validate_test.rb", "test/save_test.rb",
|
20
20
|
|
21
|
-
|
21
|
+
# "test/writeable_test.rb","test/virtual_test.rb",
|
22
22
|
|
23
|
-
|
23
|
+
# "test/form_builder_test.rb", "test/active_model_test.rb",
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
# "test/readonly_test.rb",
|
26
|
+
# "test/inherit_test.rb",
|
27
|
+
# "test/uniqueness_test.rb",
|
28
|
+
# "test/from_test.rb",
|
29
|
+
# "test/composition_test.rb",
|
30
|
+
# "test/form_option_test.rb",
|
31
|
+
# "test/form_test.rb",
|
32
|
+
# "test/deserialize_test.rb",
|
33
|
+
# "test/module_test.rb"
|
34
|
+
# ]
|
34
35
|
|
35
36
|
|
36
37
|
|
data/database.sqlite3
CHANGED
Binary file
|
data/lib/reform/contract.rb
CHANGED
@@ -91,22 +91,6 @@ module Reform
|
|
91
91
|
require "reform/schema"
|
92
92
|
extend Reform::Schema
|
93
93
|
end
|
94
|
-
|
95
|
-
class Contract_ # DISCUSS: make class?
|
96
|
-
# allows including representers from Representable, Roar or disposable.
|
97
|
-
def self.inherit_module!(representer) # called from Representable::included.
|
98
|
-
# representer_class.inherit_module!(representer)
|
99
|
-
representer.representable_attrs.each do |dfn|
|
100
|
-
next if dfn.name == "links" # wait a second # FIXME what is that?
|
101
|
-
|
102
|
-
# TODO: remove manifesting and do that in representable, too!
|
103
|
-
args = [dfn.name, dfn.instance_variable_get(:@options)] # TODO: dfn.to_args (inluding &block)
|
104
|
-
|
105
|
-
property(*args) and next unless dfn.representer_module
|
106
|
-
property(*args) { include dfn.representer_module } # nested.
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
94
|
end
|
111
95
|
|
112
96
|
require 'reform/contract/errors'
|
data/lib/reform/form.rb
CHANGED
@@ -16,10 +16,6 @@ module Reform
|
|
16
16
|
module Property
|
17
17
|
# add macro logic, e.g. for :populator.
|
18
18
|
def property(name, options={}, &block)
|
19
|
-
if options.delete(:virtual)
|
20
|
-
options[:writeable] = options[:readable] = false # DISCUSS: isn't that like an #option in Twin?
|
21
|
-
end
|
22
|
-
|
23
19
|
if deserializer = options[:deserializer] # this means someone is explicitly specifying :deserializer.
|
24
20
|
options[:deserializer] = Representable::Cloneable::Hash[deserializer]
|
25
21
|
end
|
@@ -39,7 +39,7 @@ module Reform::Form::ActiveRecord
|
|
39
39
|
def model_for_property(name)
|
40
40
|
return model unless is_a?(Reform::Form::Composition) # i am too lazy for proper inheritance. there should be a ActiveRecord::Composition that handles this.
|
41
41
|
|
42
|
-
model_name =
|
42
|
+
model_name = schema.representable_attrs.get(name)[:on]
|
43
43
|
model[model_name]
|
44
44
|
end
|
45
45
|
end
|
@@ -30,7 +30,7 @@ module Reform::Form::ModelReflections
|
|
30
30
|
def defined_enums
|
31
31
|
return model.defined_enums unless is_a?(Reform::Form::Composition)
|
32
32
|
|
33
|
-
|
33
|
+
mapper.each.with_object({}) { |m,h| h.merge! m.defined_enums }
|
34
34
|
end
|
35
35
|
|
36
36
|
# this should also contain to_param and friends as this is used by the form helpers.
|
data/lib/reform/form/module.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Include this in every module that gets further included.
|
2
|
-
|
2
|
+
# TODO: this could be implemented in Declarable, as we can use that everywhere.
|
3
|
+
module Reform::Form::Module
|
3
4
|
def self.included(base)
|
4
5
|
base.extend ClassMethods
|
5
6
|
base.extend Included
|
data/lib/reform/version.rb
CHANGED
data/reform.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
20
|
spec.add_dependency "representable", ">= 2.2.2"
|
21
|
-
spec.add_dependency "disposable", "~> 0.1.
|
21
|
+
spec.add_dependency "disposable", "~> 0.1.5"
|
22
22
|
spec.add_dependency "uber", "~> 0.0.11"
|
23
23
|
spec.add_dependency "activemodel"
|
24
24
|
|
data/test/active_record_test.rb
CHANGED
@@ -205,7 +205,7 @@ class PopulateWithActiveRecordTest < MiniTest::Spec
|
|
205
205
|
let (:album) { Album.create(:title => 'Greatest Hits') }
|
206
206
|
let (:form) { ActiveModelAlbumForm.new(album) }
|
207
207
|
|
208
|
-
it do
|
208
|
+
it "xxx"do
|
209
209
|
form.validate('songs_attributes' => {'0' => {'title' => 'Tango'}})
|
210
210
|
|
211
211
|
# form populated.
|
@@ -229,6 +229,8 @@ class PopulateWithActiveRecordTest < MiniTest::Spec
|
|
229
229
|
album.songs.size.must_equal 1
|
230
230
|
album.songs[0].title.must_equal 'Tango'
|
231
231
|
|
232
|
+
# DISCUSS: IfEmpty uses twin.original[index] for syncing. in our case, this is empty, so it will add Tango again.
|
233
|
+
form = ActiveModelAlbumForm.new(album)
|
232
234
|
form.validate('songs_attributes' => {'0' => {'id' => first_song.id, 'title' => 'Tango nuevo'}, '1' => {'title' => 'Waltz'}})
|
233
235
|
|
234
236
|
# form populated.
|
@@ -257,42 +259,6 @@ class PopulateWithActiveRecordTest < MiniTest::Spec
|
|
257
259
|
end
|
258
260
|
end
|
259
261
|
end
|
260
|
-
|
261
|
-
# it do
|
262
|
-
# a=Album.new
|
263
|
-
# a.songs << Song.new(title: "Old What's His Name") # Song does not get persisted.
|
264
|
-
|
265
|
-
# a.songs[1] = Song.new(title: "Permanent Rust")
|
266
|
-
|
267
|
-
# puts "@@@"
|
268
|
-
# puts a.songs.inspect
|
269
|
-
|
270
|
-
# puts "---"
|
271
|
-
# a.save
|
272
|
-
# puts a.songs.inspect
|
273
|
-
|
274
|
-
# b = a.songs.first
|
275
|
-
|
276
|
-
# a.songs = [Song.new(title:"Biomag")]
|
277
|
-
# puts "\\\\"
|
278
|
-
# a.save
|
279
|
-
# a.reload
|
280
|
-
# puts a.songs.inspect
|
281
|
-
|
282
|
-
# b.reload
|
283
|
-
# puts "#{b.inspect}, #{b.persisted?}"
|
284
|
-
|
285
|
-
|
286
|
-
# a.songs = [a.songs.first, Song.new(title: "Count Down")]
|
287
|
-
# b = a.songs.first
|
288
|
-
# puts ":::::"
|
289
|
-
# a.save
|
290
|
-
# a.reload
|
291
|
-
# puts a.songs.inspect
|
292
|
-
|
293
|
-
# b.reload
|
294
|
-
# puts "#{b.inspect}, #{b.persisted?}"
|
295
|
-
# end
|
296
262
|
end
|
297
263
|
|
298
264
|
|
data/test/inherit_test.rb
CHANGED
@@ -104,133 +104,4 @@ require "pp"
|
|
104
104
|
AlbumForm.new(OpenStruct.new(artist: OpenStruct.new)).artist.artist_id.must_equal 1
|
105
105
|
CompilationForm.new(OpenStruct.new(artist: OpenStruct.new)).artist.artist_id.must_equal 1
|
106
106
|
end
|
107
|
-
end
|
108
|
-
|
109
|
-
|
110
|
-
# require 'reform/form/coercion'
|
111
|
-
# class ModuleInclusionTest < MiniTest::Spec
|
112
|
-
# module BandPropertyForm
|
113
|
-
# include Reform::Form::Module
|
114
|
-
|
115
|
-
# property :band do
|
116
|
-
# property :title
|
117
|
-
|
118
|
-
# validates :title, :presence => true
|
119
|
-
|
120
|
-
# def id # gets mixed into Form, too.
|
121
|
-
# 2
|
122
|
-
# end
|
123
|
-
# end
|
124
|
-
|
125
|
-
# def id # gets mixed into Form, too.
|
126
|
-
# 1
|
127
|
-
# end
|
128
|
-
|
129
|
-
# validates :band, :presence => true
|
130
|
-
|
131
|
-
# property :cool, type: Virtus::Attribute::Boolean # test coercion.
|
132
|
-
# end
|
133
|
-
|
134
|
-
# # TODO: test if works, move stuff into inherit_schema!
|
135
|
-
# module AirplaysPropertyForm
|
136
|
-
# include Reform::Form::Module
|
137
|
-
|
138
|
-
# collection :airplays do
|
139
|
-
# property :station
|
140
|
-
# validates :station, :presence => true
|
141
|
-
# end
|
142
|
-
# validates :airplays, :presence => true
|
143
|
-
# end
|
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
|
151
|
-
|
152
|
-
# class SongForm < Reform::Form
|
153
|
-
# property :title
|
154
|
-
|
155
|
-
# include BandPropertyForm
|
156
|
-
# end
|
157
|
-
|
158
|
-
|
159
|
-
# let (:song) { OpenStruct.new(:band => OpenStruct.new(:title => "Time Again")) }
|
160
|
-
|
161
|
-
# # nested form from module is present and creates accessor.
|
162
|
-
# it { SongForm.new(song).band.title.must_equal "Time Again" }
|
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 }
|
167
|
-
|
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
|
107
|
+
end
|
data/test/module_test.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require 'reform/form/coercion'
|
3
|
+
|
4
|
+
class ModuleInclusionTest < MiniTest::Spec
|
5
|
+
module BandPropertyForm
|
6
|
+
include Reform::Form::Module
|
7
|
+
|
8
|
+
property :band do
|
9
|
+
property :title
|
10
|
+
|
11
|
+
validates :title, presence: true
|
12
|
+
|
13
|
+
def id # gets mixed into Form, too.
|
14
|
+
2
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def id # gets mixed into Form, too.
|
19
|
+
1
|
20
|
+
end
|
21
|
+
|
22
|
+
validates :band, presence: true
|
23
|
+
|
24
|
+
property :cool, type: Virtus::Attribute::Boolean # test coercion.
|
25
|
+
end
|
26
|
+
|
27
|
+
# TODO: test if works, move stuff into inherit_schema!
|
28
|
+
module AirplaysPropertyForm
|
29
|
+
include Reform::Form::Module
|
30
|
+
|
31
|
+
collection :airplays do
|
32
|
+
property :station
|
33
|
+
validates :station, presence: true
|
34
|
+
end
|
35
|
+
validates :airplays, presence: true
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# test:
|
40
|
+
# by including BandPropertyForm into multiple classes we assure that options hashes don't get messed up by AM:V.
|
41
|
+
class HitForm < Reform::Form
|
42
|
+
include BandPropertyForm
|
43
|
+
end
|
44
|
+
|
45
|
+
class SongForm < Reform::Form
|
46
|
+
include Coercion
|
47
|
+
property :title
|
48
|
+
|
49
|
+
include BandPropertyForm
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
let (:song) { OpenStruct.new(:band => OpenStruct.new(:title => "Time Again")) }
|
54
|
+
|
55
|
+
# nested form from module is present and creates accessor.
|
56
|
+
it { SongForm.new(song).band.title.must_equal "Time Again" }
|
57
|
+
|
58
|
+
# methods from module get included.
|
59
|
+
it { SongForm.new(song).id.must_equal 1 }
|
60
|
+
it { SongForm.new(song).band.id.must_equal 2 }
|
61
|
+
|
62
|
+
# validators get inherited.
|
63
|
+
it do
|
64
|
+
form = SongForm.new(OpenStruct.new)
|
65
|
+
form.validate({})
|
66
|
+
form.errors.messages.must_equal({:band=>["can't be blank"]})
|
67
|
+
end
|
68
|
+
|
69
|
+
# coercion works
|
70
|
+
it do
|
71
|
+
form = SongForm.new(OpenStruct.new)
|
72
|
+
form.validate({cool: "1"})
|
73
|
+
form.cool.must_equal true
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# include a module into a module into a class :)
|
78
|
+
module AlbumFormModule
|
79
|
+
include Reform::Form::Module
|
80
|
+
include BandPropertyForm
|
81
|
+
|
82
|
+
property :name
|
83
|
+
validates :name, :presence => true
|
84
|
+
end
|
85
|
+
|
86
|
+
class AlbumForm < Reform::Form
|
87
|
+
include AlbumFormModule
|
88
|
+
|
89
|
+
property :band, :inherit => true do
|
90
|
+
property :label
|
91
|
+
validates :label, :presence => true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
# puts "......"+ AlbumForm.representer_class.representable_attrs.get(:band).inspect
|
95
|
+
|
96
|
+
it do
|
97
|
+
form = AlbumForm.new(OpenStruct.new(:band => OpenStruct.new))
|
98
|
+
form.validate({"band" => {}})
|
99
|
+
form.errors.messages.must_equal({:"band.title"=>["can't be blank"], :"band.label"=>["can't be blank"], :name=>["can't be blank"]})
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# # including representer into form
|
104
|
+
# module GenericRepresenter
|
105
|
+
# include Representable
|
106
|
+
|
107
|
+
# property :title
|
108
|
+
# property :manager do
|
109
|
+
# property :title
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
|
113
|
+
# class LabelForm < Reform::Form
|
114
|
+
# property :location
|
115
|
+
|
116
|
+
# include GenericRepresenter
|
117
|
+
# validates :title, :presence => true
|
118
|
+
# property :manager, :inherit => true do
|
119
|
+
# validates :title, :presence => true
|
120
|
+
# end
|
121
|
+
# end
|
122
|
+
# puts "......"+ LabelForm.representer_class.representable_attrs.get(:title).inspect
|
123
|
+
|
124
|
+
|
125
|
+
# it do
|
126
|
+
# form = LabelForm.new(OpenStruct.new(:manager => OpenStruct.new))
|
127
|
+
# form.validate({"manager" => {}, "title"=>""}) # it's important to pass both nested and scalar here!
|
128
|
+
# form.errors.messages.must_equal(:title=>["can't be blank"], :"manager.title"=>["can't be blank"], )
|
129
|
+
# end
|
130
|
+
end
|
data/test/populate_test.rb
CHANGED
@@ -138,6 +138,8 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
138
138
|
let (:form) { AlbumForm.new(album) }
|
139
139
|
|
140
140
|
it do
|
141
|
+
form.songs.size.must_equal 2
|
142
|
+
|
141
143
|
form.validate(
|
142
144
|
"songs" => [{"title" => "Fallout"}, {"title" => "Roxanne"},
|
143
145
|
{"title" => "Rime Of The Ancient Mariner"}, # new song.
|
@@ -181,7 +183,6 @@ class PopulateIfEmptyTest < MiniTest::Spec
|
|
181
183
|
|
182
184
|
album.artist.must_equal nil
|
183
185
|
end
|
184
|
-
|
185
186
|
end
|
186
187
|
|
187
188
|
|
data/test/reform_test.rb
CHANGED
@@ -1,40 +1,11 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
+
# TODO: this test should be removed.
|
3
4
|
class ReformTest < ReformSpec
|
4
5
|
let (:comp) { OpenStruct.new(:name => "Duran Duran", :title => "Rio") }
|
5
6
|
|
6
7
|
let (:form) { SongForm.new(comp) }
|
7
8
|
|
8
|
-
|
9
|
-
describe "::property" do
|
10
|
-
it "doesn't allow reserved names" do
|
11
|
-
assert_raises RuntimeError do
|
12
|
-
Class.new(Reform::Form) do
|
13
|
-
property :model
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
|
20
|
-
describe "::properties" do
|
21
|
-
let (:options) { {:type => String} }
|
22
|
-
|
23
|
-
subject do
|
24
|
-
opts = options
|
25
|
-
Class.new(Reform::Form) do
|
26
|
-
properties :name, :title, opts
|
27
|
-
properties :created_at
|
28
|
-
end.new(comp)
|
29
|
-
end
|
30
|
-
|
31
|
-
it { subject.name.must_equal "Duran Duran" }
|
32
|
-
it { subject.title.must_equal "Rio" }
|
33
|
-
it { subject.created_at.must_equal nil }
|
34
|
-
# don't overwrite options.
|
35
|
-
it { subject; options.must_equal({:type => String}) }
|
36
|
-
end
|
37
|
-
|
38
9
|
class SongForm < Reform::Form
|
39
10
|
property :name
|
40
11
|
property :title
|
data/test/twin_test.rb
CHANGED
@@ -3,21 +3,36 @@ require 'test_helper'
|
|
3
3
|
require 'test_helper'
|
4
4
|
require 'reform/twin'
|
5
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
|
6
24
|
class TwinTest < MiniTest::Spec
|
7
|
-
|
8
|
-
class Twin < Disposable::Twin
|
9
|
-
property :title
|
10
|
-
option :is_online # TODO: this should make it read-only in reform!
|
11
|
-
end
|
25
|
+
Song = Struct.new(:name)
|
12
26
|
|
13
|
-
|
14
|
-
|
27
|
+
class SongForm < Reform::Form
|
28
|
+
property :name
|
29
|
+
property :is_online, virtual: true
|
15
30
|
end
|
16
31
|
|
17
|
-
let (:
|
32
|
+
let (:form) { SongForm.new(Song.new("Kenny"), is_online: true) }
|
18
33
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
34
|
+
it do
|
35
|
+
form.name.must_equal "Kenny"
|
36
|
+
form.is_online.must_equal true
|
37
|
+
end
|
38
|
+
end
|
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: 2.0.0.
|
4
|
+
version: 2.0.0.rc1
|
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: 2015-
|
12
|
+
date: 2015-07-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: representable
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.1.
|
34
|
+
version: 0.1.5
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0.1.
|
41
|
+
version: 0.1.5
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: uber
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -261,7 +261,6 @@ files:
|
|
261
261
|
- test/dummy/log/server.log
|
262
262
|
- test/errors_test.rb
|
263
263
|
- test/feature_test.rb
|
264
|
-
- test/fields_test.rb
|
265
264
|
- test/form_builder_test.rb
|
266
265
|
- test/form_option_test.rb
|
267
266
|
- test/form_test.rb
|
@@ -269,6 +268,7 @@ files:
|
|
269
268
|
- test/inherit_test.rb
|
270
269
|
- test/model_reflections_test.rb
|
271
270
|
- test/model_validations_test.rb
|
271
|
+
- test/module_test.rb
|
272
272
|
- test/populate_test.rb
|
273
273
|
- test/prepopulator_test.rb
|
274
274
|
- test/rails/integration_test.rb
|
@@ -276,13 +276,10 @@ files:
|
|
276
276
|
- test/readable_test.rb
|
277
277
|
- test/readonly_test.rb
|
278
278
|
- test/reform_test.rb
|
279
|
-
- test/representer_test.rb
|
280
279
|
- test/save_test.rb
|
281
|
-
- test/scalar_test.rb
|
282
280
|
- test/setup_test.rb
|
283
281
|
- test/skip_if_test.rb
|
284
282
|
- test/skip_setter_and_getter_test.rb
|
285
|
-
- test/skip_unchanged_test.rb
|
286
283
|
- test/test_helper.rb
|
287
284
|
- test/twin_test.rb
|
288
285
|
- test/uniqueness_test.rb
|
@@ -349,7 +346,6 @@ test_files:
|
|
349
346
|
- test/dummy/log/server.log
|
350
347
|
- test/errors_test.rb
|
351
348
|
- test/feature_test.rb
|
352
|
-
- test/fields_test.rb
|
353
349
|
- test/form_builder_test.rb
|
354
350
|
- test/form_option_test.rb
|
355
351
|
- test/form_test.rb
|
@@ -357,6 +353,7 @@ test_files:
|
|
357
353
|
- test/inherit_test.rb
|
358
354
|
- test/model_reflections_test.rb
|
359
355
|
- test/model_validations_test.rb
|
356
|
+
- test/module_test.rb
|
360
357
|
- test/populate_test.rb
|
361
358
|
- test/prepopulator_test.rb
|
362
359
|
- test/rails/integration_test.rb
|
@@ -364,13 +361,10 @@ test_files:
|
|
364
361
|
- test/readable_test.rb
|
365
362
|
- test/readonly_test.rb
|
366
363
|
- test/reform_test.rb
|
367
|
-
- test/representer_test.rb
|
368
364
|
- test/save_test.rb
|
369
|
-
- test/scalar_test.rb
|
370
365
|
- test/setup_test.rb
|
371
366
|
- test/skip_if_test.rb
|
372
367
|
- test/skip_setter_and_getter_test.rb
|
373
|
-
- test/skip_unchanged_test.rb
|
374
368
|
- test/test_helper.rb
|
375
369
|
- test/twin_test.rb
|
376
370
|
- test/uniqueness_test.rb
|
data/test/fields_test.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class FieldsTest < MiniTest::Spec
|
4
|
-
describe "#new" do
|
5
|
-
it "accepts list of properties" do
|
6
|
-
fields = Reform::Contract::Fields.new([:name, :title])
|
7
|
-
fields.name.must_equal nil
|
8
|
-
fields.title.must_equal nil
|
9
|
-
|
10
|
-
fields.title= "Planet X"
|
11
|
-
fields.title.must_equal "Planet X"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/test/representer_test.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class RepresenterOptionsTest < MiniTest::Spec
|
4
|
-
subject { Reform::Representer::Options[] }
|
5
|
-
|
6
|
-
# don't maintain empty excludes until fixed in representable.
|
7
|
-
it { subject.exclude!([]).must_equal({:exclude=>[]}) }
|
8
|
-
it { subject.include!([]).must_equal({:include=>[]}) }
|
9
|
-
|
10
|
-
it { subject.exclude!([:title, :id]).must_equal({exclude: [:title, :id]}) }
|
11
|
-
it { subject.include!([:title, :id]).must_equal({include: [:title, :id]}) }
|
12
|
-
|
13
|
-
|
14
|
-
module Representer
|
15
|
-
include Representable::Hash
|
16
|
-
property :title
|
17
|
-
property :genre
|
18
|
-
property :id
|
19
|
-
end
|
20
|
-
|
21
|
-
it "representable" do
|
22
|
-
song = OpenStruct.new(title: "Title", genre: "Punk", id: 1)
|
23
|
-
puts Representer.prepare(song).to_hash(include: [:genre, :id], exclude: [:id]).inspect
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
class RepresenterTest < MiniTest::Spec
|
29
|
-
class SongRepresenter < Reform::Representer
|
30
|
-
property :title
|
31
|
-
property :name
|
32
|
-
property :genre
|
33
|
-
end
|
34
|
-
|
35
|
-
subject { SongRepresenter.new(Object.new) }
|
36
|
-
|
37
|
-
describe "#fields" do
|
38
|
-
it "returns all properties as strings" do
|
39
|
-
SongRepresenter.fields.must_equal(["title", "name", "genre"])
|
40
|
-
end
|
41
|
-
|
42
|
-
# allows block.
|
43
|
-
it do
|
44
|
-
SongRepresenter.fields { |dfn| dfn.name =~ /n/ }.must_equal ["name", "genre"]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/test/scalar_test.rb
DELETED
@@ -1,167 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
|
4
|
-
class SelfNestedTest < BaseTest
|
5
|
-
class Form < Reform::Form
|
6
|
-
property :title do
|
7
|
-
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
let (:song) { Song.new("Crash And Burn") }
|
12
|
-
it do
|
13
|
-
Form.new(song)
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
it do
|
18
|
-
form = Form.new(song)
|
19
|
-
|
20
|
-
form.title = Class.new(Reform::Form) do
|
21
|
-
@form_name = "ficken"
|
22
|
-
def self.name # needed by ActiveModel::Validation and I18N.
|
23
|
-
@form_name
|
24
|
-
end
|
25
|
-
|
26
|
-
validates :model, :length => {:minimum => 10}
|
27
|
-
|
28
|
-
|
29
|
-
def update!(object)
|
30
|
-
model.replace(object)
|
31
|
-
end
|
32
|
-
|
33
|
-
end.new("Crash And Burn") # gets initialized with string (or image object, or whatever).
|
34
|
-
|
35
|
-
form.validate({"title" => "Teaser"})
|
36
|
-
|
37
|
-
form.errors.messages.must_equal({:"title.model"=>["is too short (minimum is 10 characters)"]})
|
38
|
-
|
39
|
-
|
40
|
-
# validation only kicks in when value present
|
41
|
-
form = Form.new(song)
|
42
|
-
form.validate({})
|
43
|
-
form.errors.messages.must_equal({})
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
class ImageForm < Reform::Form
|
48
|
-
# property :image, populate_if_empty: lambda { |object, args| object } do
|
49
|
-
property :image, :scalar => true do
|
50
|
-
validates :size, numericality: { less_than: 10 }
|
51
|
-
validates :length, numericality: { greater_than: 1 } # TODO: make better validators and remove AM::Validators at some point.
|
52
|
-
|
53
|
-
# FIXME: does that only work with representable 2.0?
|
54
|
-
# def size; model.size; end
|
55
|
-
# def type; model.class.to_s; end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
AlbumCover = Struct.new(:image) do
|
60
|
-
include Saveable
|
61
|
-
end
|
62
|
-
|
63
|
-
# no image in params AND model.
|
64
|
-
it do
|
65
|
-
form = ImageForm.new(AlbumCover.new(nil))
|
66
|
-
|
67
|
-
|
68
|
-
form.validate({})
|
69
|
-
form.errors.messages.must_equal({})
|
70
|
-
end
|
71
|
-
|
72
|
-
# no image in params but in model.
|
73
|
-
it do
|
74
|
-
skip
|
75
|
-
|
76
|
-
# TODO: implement validations that only run when requested (only_validate_params: true)
|
77
|
-
form = ImageForm.new(AlbumCover.new("i don't know how i got here but i'm invalid"))
|
78
|
-
|
79
|
-
|
80
|
-
form.validate({})
|
81
|
-
form.errors.messages.must_equal({})
|
82
|
-
end
|
83
|
-
|
84
|
-
# image in params but NOT in model.
|
85
|
-
it do
|
86
|
-
form = ImageForm.new(AlbumCover.new(nil))
|
87
|
-
|
88
|
-
form.validate({"image" => "I'm OK!"})
|
89
|
-
puts form.inspect
|
90
|
-
form.errors.messages.must_equal({})
|
91
|
-
form.image.scalar.must_equal "I'm OK!"
|
92
|
-
end
|
93
|
-
|
94
|
-
# OK image, image existent.
|
95
|
-
it "hello" do
|
96
|
-
form = ImageForm.new(AlbumCover.new("nil"))
|
97
|
-
|
98
|
-
form.image.model.must_equal "nil"
|
99
|
-
|
100
|
-
form.validate({"image" => "I'm OK!"})
|
101
|
-
form.errors.messages.must_equal({})
|
102
|
-
end
|
103
|
-
|
104
|
-
# invalid image, image existent.
|
105
|
-
it "xx"do
|
106
|
-
form = ImageForm.new(AlbumCover.new("nil"))
|
107
|
-
|
108
|
-
form.validate({"image" => "I'm too long, is that a problem?"})
|
109
|
-
form.errors.messages.must_equal({:"image.size"=>["must be less than 10"]})
|
110
|
-
end
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
# validate string only if it's in params.
|
115
|
-
class StringForm < Reform::Form
|
116
|
-
property :image, :scalar => true do # creates "empty" form
|
117
|
-
validates :length => {:minimum => 10}
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
|
122
|
-
# validates when present.
|
123
|
-
# invalid
|
124
|
-
it do
|
125
|
-
form = StringForm.new(AlbumCover.new(nil))
|
126
|
-
form.validate("image" => "0x123").must_equal false
|
127
|
-
form.image.scalar.must_equal("0x123")
|
128
|
-
# TODO: errors, save
|
129
|
-
|
130
|
-
form.errors.messages.must_equal({:"image.scalar"=>["is too short (minimum is 10 characters)"]})
|
131
|
-
end
|
132
|
-
|
133
|
-
# valid
|
134
|
-
it "xxx" do
|
135
|
-
cover = AlbumCover.new(nil)
|
136
|
-
|
137
|
-
form = StringForm.new(cover)
|
138
|
-
form.validate("image" => "0x123456789").must_equal true
|
139
|
-
|
140
|
-
form.image.scalar.must_equal("0x123456789")
|
141
|
-
cover.image.must_equal nil
|
142
|
-
|
143
|
-
# errors
|
144
|
-
form.errors.messages.must_equal({})
|
145
|
-
|
146
|
-
# sync
|
147
|
-
form.sync
|
148
|
-
form.image.scalar.must_equal("0x123456789")
|
149
|
-
cover.image.must_equal "0x123456789" # that already writes it back.
|
150
|
-
|
151
|
-
# save
|
152
|
-
form.save
|
153
|
-
cover.image.must_equal "0x123456789" # #save writes back to model.
|
154
|
-
|
155
|
-
form.save do |hash|
|
156
|
-
hash.must_equal("image"=>"0x123456789")
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
# does not validate when absent (that's the whole point of this directive).
|
161
|
-
it do
|
162
|
-
form = StringForm.new(AlbumCover.new(nil))
|
163
|
-
form.validate({}).must_equal true
|
164
|
-
end
|
165
|
-
|
166
|
-
# DISCUSS: when AlbumCover.new("Hello").validate({}), does that fail?
|
167
|
-
end
|
data/test/skip_unchanged_test.rb
DELETED
@@ -1,86 +0,0 @@
|
|
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
|