reform 2.1.0 → 2.2.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/.gitignore +0 -1
- data/.travis.yml +4 -12
- data/CHANGES.md +8 -0
- data/README.md +36 -743
- data/Rakefile +1 -31
- data/gemfiles/{Gemfile.rails-3.1 → Gemfile.disposable-0.3} +1 -2
- data/lib/reform.rb +0 -9
- data/lib/reform/contract.rb +5 -1
- data/lib/reform/form.rb +1 -4
- data/lib/reform/form/composition.rb +1 -2
- data/lib/reform/form/dry.rb +29 -16
- data/lib/reform/form/module.rb +15 -3
- data/lib/reform/form/validate.rb +1 -1
- data/lib/reform/validation.rb +3 -3
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +3 -10
- data/test/coercion_test.rb +7 -7
- data/test/composition_test.rb +5 -1
- data/test/contract_test.rb +10 -4
- data/test/deserialize_test.rb +3 -3
- data/test/errors_test.rb +48 -28
- data/test/form_option_test.rb +3 -1
- data/test/form_test.rb +19 -14
- data/test/module_test.rb +51 -11
- data/test/populate_test.rb +21 -7
- data/test/reform_test.rb +24 -20
- data/test/save_test.rb +10 -4
- data/test/skip_if_test.rb +5 -3
- data/test/test_helper.rb +3 -43
- data/test/validate_test.rb +34 -14
- data/test/validation/dry_test.rb +60 -0
- data/test/validation/dry_validation_test.rb +65 -43
- data/test/validation/errors.yml +4 -0
- metadata +16 -192
- data/database.sqlite3 +0 -0
- data/gemfiles/Gemfile.rails-3.2 +0 -7
- data/gemfiles/Gemfile.rails-4.0 +0 -8
- data/gemfiles/Gemfile.rails-4.1 +0 -8
- data/gemfiles/Gemfile.rails-4.2 +0 -8
- data/lib/reform/active_record.rb +0 -4
- data/lib/reform/form/active_model.rb +0 -87
- data/lib/reform/form/active_model/form_builder_methods.rb +0 -48
- data/lib/reform/form/active_model/model_reflections.rb +0 -46
- data/lib/reform/form/active_model/model_validations.rb +0 -110
- data/lib/reform/form/active_model/validations.rb +0 -107
- data/lib/reform/form/active_record.rb +0 -30
- data/lib/reform/form/lotus.rb +0 -59
- data/lib/reform/form/multi_parameter_attributes.rb +0 -48
- data/lib/reform/form/validation/unique_validator.rb +0 -54
- data/lib/reform/rails.rb +0 -13
- data/test/active_model_custom_validation_translations_test.rb +0 -75
- data/test/active_model_test.rb +0 -207
- data/test/active_model_validation_for_property_named_format_test.rb +0 -18
- data/test/active_record_test.rb +0 -273
- data/test/builder_test.rb +0 -32
- data/test/custom_validation_test.rb +0 -47
- data/test/dummy/Rakefile +0 -7
- data/test/dummy/app/controllers/albums_controller.rb +0 -18
- data/test/dummy/app/controllers/application_controller.rb +0 -4
- data/test/dummy/app/controllers/musician_controller.rb +0 -5
- data/test/dummy/app/forms/album_form.rb +0 -18
- data/test/dummy/app/helpers/application_helper.rb +0 -2
- data/test/dummy/app/models/album.rb +0 -4
- data/test/dummy/app/models/song.rb +0 -3
- data/test/dummy/app/views/albums/new.html.erb +0 -28
- data/test/dummy/app/views/layouts/application.html.erb +0 -14
- data/test/dummy/config.ru +0 -4
- data/test/dummy/config/application.rb +0 -20
- data/test/dummy/config/boot.rb +0 -10
- data/test/dummy/config/database.yml +0 -22
- data/test/dummy/config/environment.rb +0 -5
- data/test/dummy/config/environments/development.rb +0 -16
- data/test/dummy/config/environments/production.rb +0 -46
- data/test/dummy/config/environments/test.rb +0 -33
- data/test/dummy/config/locales/en.yml +0 -14
- data/test/dummy/config/routes.rb +0 -4
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/form_builder_test.rb +0 -138
- data/test/lotus/Gemfile +0 -5
- data/test/lotus/lotus_test.rb +0 -31
- data/test/lotus_test.rb +0 -150
- data/test/model_reflections_test.rb +0 -138
- data/test/model_validations_test.rb +0 -82
- data/test/mongoid_test.rb +0 -313
- data/test/multi_parameter_attributes_test.rb +0 -50
- data/test/rails/integration_test.rb +0 -54
- data/test/unique_test.rb +0 -135
- data/test/validation/activemodel_validation_test.rb +0 -252
@@ -1,18 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class AMValidationWithFormatTest < MiniTest::Spec
|
4
|
-
class SongForm < Reform::Form
|
5
|
-
property :format
|
6
|
-
validates :format, presence: true
|
7
|
-
end
|
8
|
-
|
9
|
-
class Song
|
10
|
-
def format
|
11
|
-
1
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
it do
|
16
|
-
SongForm.new(Song.new).validate({}).must_equal true
|
17
|
-
end
|
18
|
-
end
|
data/test/active_record_test.rb
DELETED
@@ -1,273 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'reform/active_record'
|
3
|
-
|
4
|
-
# ActiveRecord::Schema.define do
|
5
|
-
# create_table :artists do |table|
|
6
|
-
# table.column :name, :string
|
7
|
-
# table.timestamps
|
8
|
-
# end
|
9
|
-
# create_table :songs do |table|
|
10
|
-
# table.column :title, :string
|
11
|
-
# table.column :artist_id, :integer
|
12
|
-
# table.column :album_id, :integer
|
13
|
-
# table.timestamps
|
14
|
-
# end
|
15
|
-
# create_table :albums do |table|
|
16
|
-
# table.column :title, :string
|
17
|
-
# table.timestamps
|
18
|
-
# end
|
19
|
-
# end
|
20
|
-
# Artist.new(:name => "Racer X").save
|
21
|
-
|
22
|
-
class ActiveRecordTest < MiniTest::Spec
|
23
|
-
class SongForm < Reform::Form
|
24
|
-
feature Reform::Form::ActiveModel::Validations
|
25
|
-
|
26
|
-
include Reform::Form::ActiveRecord
|
27
|
-
model :song
|
28
|
-
|
29
|
-
property :title
|
30
|
-
property :created_at
|
31
|
-
|
32
|
-
validates_uniqueness_of :title, scope: [:album_id, :artist_id]
|
33
|
-
validates :created_at, :presence => true # have another property to test if we mix up.
|
34
|
-
|
35
|
-
property :artist do
|
36
|
-
property :name
|
37
|
-
validates_uniqueness_of :name # this currently also tests if Form::AR is included as a feature.
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
let(:album) { Album.create(:title => "Damnation") }
|
42
|
-
let(:artist) { Artist.create(:name => "Opeth") }
|
43
|
-
let(:form) { SongForm.new(Song.new(:artist => Artist.new)) }
|
44
|
-
|
45
|
-
it { form.class.i18n_scope.must_equal :activerecord }
|
46
|
-
|
47
|
-
# uniqueness
|
48
|
-
it "has no errors on title when title is unique for the same artist and album" do
|
49
|
-
form.validate("title" => "The Gargoyle", "artist_id" => artist.id, "album" => album.id, "created_at" => "November 6, 1966")
|
50
|
-
assert_empty form.errors[:title]
|
51
|
-
end
|
52
|
-
|
53
|
-
it "has errors on title when title is taken for the same artist and album" do
|
54
|
-
skip "replace ActiveModel::Validations with our own, working and reusable gem."
|
55
|
-
Song.create(title: "Windowpane", artist_id: artist.id, album_id: album.id)
|
56
|
-
form.validate("title" => "Windowpane", "artist_id" => artist.id, "album" => album)
|
57
|
-
refute_empty form.errors[:title]
|
58
|
-
end
|
59
|
-
|
60
|
-
# nested object taken.
|
61
|
-
it "is valid when artist name is unique" do
|
62
|
-
form.validate("artist" => {"name" => "Paul Gilbert"}, "title" => "The Gargoyle", "created_at" => "November 6, 1966").must_equal true
|
63
|
-
end
|
64
|
-
|
65
|
-
it "is invalid and shows error when taken" do
|
66
|
-
Song.delete_all
|
67
|
-
Artist.create(:name => "Racer X")
|
68
|
-
|
69
|
-
form.validate("artist" => {"name" => "Racer X"}, "title" => "Ghost Inside My Skin").must_equal false
|
70
|
-
form.errors.messages.must_equal({:"artist.name"=>["has already been taken"], :created_at => ["can't be blank"]})
|
71
|
-
end
|
72
|
-
|
73
|
-
it "works with Composition" do
|
74
|
-
form = Class.new(Reform::Form) do
|
75
|
-
include Reform::Form::ActiveRecord
|
76
|
-
include Reform::Form::Composition
|
77
|
-
|
78
|
-
property :name, :on => :artist
|
79
|
-
validates_uniqueness_of :name
|
80
|
-
end.new(:artist => Artist.new)
|
81
|
-
|
82
|
-
Artist.create(:name => "Bad Religion")
|
83
|
-
form.validate("name" => "Bad Religion").must_equal false
|
84
|
-
end
|
85
|
-
|
86
|
-
describe "#save" do
|
87
|
-
# TODO: test 1-n?
|
88
|
-
it "calls model.save" do
|
89
|
-
Artist.delete_all
|
90
|
-
form.validate("artist" => {"name" => "Bad Religion"}, "title" => "Ghost Inside My Skin")
|
91
|
-
form.save
|
92
|
-
Artist.where(:name => "Bad Religion").size.must_equal 1
|
93
|
-
end
|
94
|
-
|
95
|
-
it "doesn't call model.save when block is given" do
|
96
|
-
Artist.delete_all
|
97
|
-
form.validate("name" => "Bad Religion")
|
98
|
-
form.save {}
|
99
|
-
Artist.where(:name => "Bad Religion").size.must_equal 0
|
100
|
-
end
|
101
|
-
|
102
|
-
it "can access block params using string or hash key" do
|
103
|
-
Artist.delete_all
|
104
|
-
form.validate("artist" => {"name" => "Paul Gilbert"}, "title" => "The Gargoyle", "created_at" => "November 6, 1966")
|
105
|
-
form.save do |params|
|
106
|
-
params[:title].must_equal 'The Gargoyle'
|
107
|
-
params['title'].must_equal 'The Gargoyle'
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
|
114
|
-
class PopulateWithActiveRecordTest < MiniTest::Spec
|
115
|
-
class AlbumForm < Reform::Form
|
116
|
-
|
117
|
-
property :title
|
118
|
-
|
119
|
-
collection :songs, :populate_if_empty => Song do
|
120
|
-
property :title
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
let (:album) { Album.new(:songs => []) }
|
125
|
-
it do
|
126
|
-
form = AlbumForm.new(album)
|
127
|
-
|
128
|
-
form.validate("songs" => [{"title" => "Straight From The Jacket"}])
|
129
|
-
|
130
|
-
# form populated.
|
131
|
-
form.songs.size.must_equal 1
|
132
|
-
form.songs[0].model.must_be_kind_of Song
|
133
|
-
|
134
|
-
# model NOT populated.
|
135
|
-
album.songs.must_equal []
|
136
|
-
|
137
|
-
|
138
|
-
form.sync
|
139
|
-
|
140
|
-
# form populated.
|
141
|
-
form.songs.size.must_equal 1
|
142
|
-
form.songs[0].model.must_be_kind_of Song
|
143
|
-
|
144
|
-
# model also populated.
|
145
|
-
song = album.songs[0]
|
146
|
-
album.songs.must_equal [song]
|
147
|
-
song.title.must_equal "Straight From The Jacket"
|
148
|
-
|
149
|
-
|
150
|
-
if ActiveRecord::VERSION::STRING !~ /^3.0/
|
151
|
-
# saving saves association.
|
152
|
-
form.save
|
153
|
-
|
154
|
-
album.reload
|
155
|
-
song = album.songs[0]
|
156
|
-
album.songs.must_equal [song]
|
157
|
-
song.title.must_equal "Straight From The Jacket"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
|
162
|
-
describe "modifying 1., adding 2." do
|
163
|
-
let (:song) { Song.new(:title => "Part 2") }
|
164
|
-
let (:album) { Album.create.tap { |a| a.songs << song } }
|
165
|
-
|
166
|
-
it do
|
167
|
-
form = AlbumForm.new(album)
|
168
|
-
|
169
|
-
id = album.songs[0].id
|
170
|
-
assert id > 0
|
171
|
-
|
172
|
-
form.validate("songs" => [{"title" => "Part Two"}, {"title" => "Check For A Pulse"}])
|
173
|
-
|
174
|
-
# form populated.
|
175
|
-
form.songs.size.must_equal 2
|
176
|
-
form.songs[0].model.must_be_kind_of Song
|
177
|
-
form.songs[1].model.must_be_kind_of Song
|
178
|
-
|
179
|
-
# model NOT populated.
|
180
|
-
album.songs.must_equal [song]
|
181
|
-
|
182
|
-
|
183
|
-
form.sync
|
184
|
-
|
185
|
-
# form populated.
|
186
|
-
form.songs.size.must_equal 2
|
187
|
-
|
188
|
-
# model also populated.
|
189
|
-
album.songs.size.must_equal 2
|
190
|
-
|
191
|
-
# corrected title
|
192
|
-
album.songs[0].title.must_equal "Part Two"
|
193
|
-
# ..but same song.
|
194
|
-
album.songs[0].id.must_equal id
|
195
|
-
|
196
|
-
# and a new song.
|
197
|
-
album.songs[1].title.must_equal "Check For A Pulse"
|
198
|
-
album.songs[1].persisted?.must_equal true # TODO: with << strategy, this shouldn't be saved.
|
199
|
-
end
|
200
|
-
|
201
|
-
describe 'using nested_models_attributes to modify nested collection' do
|
202
|
-
class ActiveModelAlbumForm < Reform::Form
|
203
|
-
include Reform::Form::ActiveModel
|
204
|
-
include Reform::Form::ActiveModel::FormBuilderMethods
|
205
|
-
|
206
|
-
property :title
|
207
|
-
|
208
|
-
collection :songs, :populate_if_empty => Song do
|
209
|
-
property :title
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
let (:album) { Album.create(:title => 'Greatest Hits') }
|
214
|
-
let (:form) { ActiveModelAlbumForm.new(album) }
|
215
|
-
|
216
|
-
it "xxx"do
|
217
|
-
form.validate('songs_attributes' => {'0' => {'title' => 'Tango'}})
|
218
|
-
|
219
|
-
# form populated.
|
220
|
-
form.songs.size.must_equal 1
|
221
|
-
form.songs[0].model.must_be_kind_of Song
|
222
|
-
form.songs[0].title.must_equal 'Tango'
|
223
|
-
|
224
|
-
# model NOT populated.
|
225
|
-
album.songs.must_equal []
|
226
|
-
|
227
|
-
form.save
|
228
|
-
|
229
|
-
# nested model persisted.
|
230
|
-
first_song = album.songs[0]
|
231
|
-
assert first_song.id > 0
|
232
|
-
|
233
|
-
# form populated.
|
234
|
-
form.songs.size.must_equal 1
|
235
|
-
|
236
|
-
# model also populated.
|
237
|
-
album.songs.size.must_equal 1
|
238
|
-
album.songs[0].title.must_equal 'Tango'
|
239
|
-
|
240
|
-
# DISCUSS: IfEmpty uses twin.original[index] for syncing. in our case, this is empty, so it will add Tango again.
|
241
|
-
form = ActiveModelAlbumForm.new(album)
|
242
|
-
form.validate('songs_attributes' => {'0' => {'id' => first_song.id, 'title' => 'Tango nuevo'}, '1' => {'title' => 'Waltz'}})
|
243
|
-
|
244
|
-
# form populated.
|
245
|
-
form.songs.size.must_equal 2
|
246
|
-
form.songs[0].model.must_be_kind_of Song
|
247
|
-
form.songs[1].model.must_be_kind_of Song
|
248
|
-
form.songs[0].title.must_equal 'Tango nuevo'
|
249
|
-
form.songs[1].title.must_equal 'Waltz'
|
250
|
-
|
251
|
-
# model NOT populated.
|
252
|
-
album.songs.size.must_equal 1
|
253
|
-
album.songs[0].title.must_equal 'Tango'
|
254
|
-
|
255
|
-
form.save
|
256
|
-
|
257
|
-
# form populated.
|
258
|
-
form.songs.size.must_equal 2
|
259
|
-
|
260
|
-
# model also populated.
|
261
|
-
album.songs.size.must_equal 2
|
262
|
-
album.songs[0].id.must_equal first_song.id
|
263
|
-
album.songs[0].persisted?.must_equal true
|
264
|
-
album.songs[1].persisted?.must_equal true
|
265
|
-
album.songs[0].title.must_equal 'Tango nuevo'
|
266
|
-
album.songs[1].title.must_equal 'Waltz'
|
267
|
-
end
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
|
273
|
-
|
data/test/builder_test.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# require 'test_helper'
|
2
|
-
|
3
|
-
# class BuilderTest < MiniTest::Spec
|
4
|
-
# it do
|
5
|
-
# Builder.new.checkboxes(:settings, :hash => {"play" => true, "released" => false}).must_equal %{<input name="yo" type="hidden" value="unchecked_value" /><input id="object_name_method" name="yo" type="checkbox" value="checked_value" />
|
6
|
-
# <input name="yo" type="hidden" value="unchecked_value" /><input id="object_name_method" name="yo" type="checkbox" value="checked_value" />}
|
7
|
-
# end
|
8
|
-
# end
|
9
|
-
|
10
|
-
|
11
|
-
# require 'action_view/helpers/capture_helper'
|
12
|
-
# require 'action_view/helpers/tag_helper'
|
13
|
-
# require 'action_view/helpers/url_helper'
|
14
|
-
# require 'action_view/helpers/sanitize_helper'
|
15
|
-
# require 'action_view/helpers/text_helper'
|
16
|
-
# require 'action_view/helpers/form_tag_helper'
|
17
|
-
# require 'action_view/helpers/form_helper'
|
18
|
-
|
19
|
-
# class Builder
|
20
|
-
# include ActionView::Helpers::CaptureHelper
|
21
|
-
# include ActionView::Helpers::FormHelper
|
22
|
-
|
23
|
-
# # {name: value}
|
24
|
-
# def checkboxes(name, options)
|
25
|
-
# # get property form.to_a ? to_builder_hash or something like that
|
26
|
-
# options[:hash].collect do |id, value|
|
27
|
-
# ActionView::Helpers::InstanceTag.new(:object_name, :method, self).to_check_box_tag({:name => "yo"}, :checked_value, :unchecked_value)
|
28
|
-
|
29
|
-
# # check_box_tag(id, value, checked = false, {})
|
30
|
-
# end.join("\n")
|
31
|
-
# end
|
32
|
-
# end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
unless ActiveModel::VERSION::MAJOR == 3 and ActiveModel::VERSION::MINOR == 0
|
4
|
-
|
5
|
-
class UnexistantTitleValidator < ActiveModel::Validator
|
6
|
-
def validate record
|
7
|
-
if record.title == 'unexistant_song'
|
8
|
-
record.errors.add(:title, 'this title does not exist!')
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class CustomValidationTest < MiniTest::Spec
|
14
|
-
|
15
|
-
class Album
|
16
|
-
include ActiveModel::Validations
|
17
|
-
attr_accessor :title, :artist
|
18
|
-
|
19
|
-
validates_with UnexistantTitleValidator
|
20
|
-
end
|
21
|
-
|
22
|
-
class AlbumForm < Reform::Form
|
23
|
-
extend ActiveModel::ModelValidations
|
24
|
-
|
25
|
-
property :title
|
26
|
-
property :artist_name, from: :artist
|
27
|
-
copy_validations_from Album
|
28
|
-
end
|
29
|
-
|
30
|
-
let(:album) { Album.new }
|
31
|
-
|
32
|
-
describe 'non-composite form' do
|
33
|
-
|
34
|
-
let(:album_form) { AlbumForm.new(album) }
|
35
|
-
|
36
|
-
it 'is not valid when title is unexistant_song' do
|
37
|
-
album_form.validate(artist_name: 'test', title: 'unexistant_song').must_equal false
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'is valid when title is something existant' do
|
41
|
-
album_form.validate(artist_name: 'test', title: 'test').must_equal true
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
end
|
data/test/dummy/Rakefile
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
|
-
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
|
-
|
4
|
-
require File.expand_path('../config/application', __FILE__)
|
5
|
-
require 'rake'
|
6
|
-
|
7
|
-
Rails::Application.load_tasks
|
@@ -1,18 +0,0 @@
|
|
1
|
-
class AlbumsController < ActionController::Base
|
2
|
-
def new
|
3
|
-
album = Album.new(:songs => [Song.new, Song.new])
|
4
|
-
@form = AlbumForm.new(album)
|
5
|
-
end
|
6
|
-
|
7
|
-
def create
|
8
|
-
album = Album.new(songs: [Song.new, Song.new])
|
9
|
-
@form = AlbumForm.new(album)
|
10
|
-
|
11
|
-
if @form.validate(params["album"])
|
12
|
-
@form.save
|
13
|
-
redirect_to album_path(album)
|
14
|
-
else
|
15
|
-
render :new
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
class AlbumForm < Reform::Form # FIXME: sub forms don't inherit FBM.
|
2
|
-
|
3
|
-
model :album
|
4
|
-
|
5
|
-
property :title
|
6
|
-
|
7
|
-
collection :songs do
|
8
|
-
property :title
|
9
|
-
validates :title, presence: true
|
10
|
-
end
|
11
|
-
|
12
|
-
validates :title, presence: true
|
13
|
-
|
14
|
-
def save
|
15
|
-
super
|
16
|
-
model.save
|
17
|
-
end
|
18
|
-
end
|