reform 2.0.4 → 2.0.5
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 +6 -0
- data/Gemfile +1 -2
- data/database.sqlite3 +0 -0
- data/lib/reform/form/active_model/model_reflections.rb +5 -0
- data/lib/reform/form/active_model/validations.rb +8 -14
- data/lib/reform/form/multi_parameter_attributes.rb +8 -3
- data/lib/reform/version.rb +1 -1
- data/test/active_model_validation_for_property_named_format_test.rb +18 -0
- data/test/form_test.rb +1 -1
- data/test/model_reflections_test.rb +4 -0
- data/test/mongoid_test.rb +261 -261
- data/test/multi_parameter_attributes_test.rb +50 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7b6c745acf6fc96e9d5c0291d4fa64df5be3c92
|
4
|
+
data.tar.gz: 0304e04e195f525af7aed8081c87a328885c2581
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1070cf32ba255c0b08d5b0dc7bc3a666cd1a515fe627e77af2168519908fe9a0680b132cdc2e77e512cd346c1b458051bc5c1e055db31bcc101ac718dfca8bf4
|
7
|
+
data.tar.gz: 42777ea0870fa57d5eb6c87df3cda716bd6eff0f0c479e50610df969845b089c6dcaa366ab1e14c66484c1980fbf621dd045463cc2ae357d5e8fbbcc3f13fdf8
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 2.0.5
|
2
|
+
|
3
|
+
* `ActiveModel::Validator` now delegates all methods properly to the form. It used to crashed with properties called `format` or other private `Object` methods.
|
4
|
+
* Simpleform will now properly display fields as required, or not (by introducion `ModelReflections::validators_on`).
|
5
|
+
* The `:default` option is not copied into the deserializer anymore from the schema. This requires disposable 0.1.11.
|
6
|
+
|
1
7
|
## 2.0.4
|
2
8
|
|
3
9
|
* `#sync` and `#save` with block now provide `HashWithIndifferentAccess` in Rails.
|
data/Gemfile
CHANGED
data/database.sqlite3
CHANGED
Binary file
|
@@ -16,6 +16,11 @@ class Reform::Form < Reform::Contract
|
|
16
16
|
def reflect_on_association(*args)
|
17
17
|
model_name.to_s.constantize.reflect_on_association(*args)
|
18
18
|
end
|
19
|
+
|
20
|
+
# this is needed in simpleform to infer required fields.
|
21
|
+
def validators_on(*args)
|
22
|
+
validator.validators_on(*args)
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
26
|
# Delegate column for attribute to the model to support simple_form's
|
@@ -5,19 +5,13 @@ require "uber/delegates"
|
|
5
5
|
module Reform::Form::ActiveModel
|
6
6
|
# AM::Validations for your form.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
# implementation is old, very complex given that it needs to do a simple thing, is using
|
10
|
-
# globals like @errors, and relies and more than 100 methods to be mixed into your form.
|
11
|
-
#
|
12
|
-
# Implements ::validates and friends, and #valid?.
|
13
|
-
#
|
8
|
+
# Provides ::validates, ::validate, #validate, and #valid?.
|
14
9
|
module Validations
|
15
10
|
def self.included(includer)
|
16
11
|
includer.instance_eval do
|
17
12
|
include Reform::Form::ActiveModel
|
18
|
-
extend Uber::InheritableAttr
|
19
13
|
inheritable_attr :validator
|
20
|
-
self.validator = Class.new(Validator)
|
14
|
+
self.validator = Class.new(Validator) # the actual validations happen in this instance.
|
21
15
|
|
22
16
|
class << self
|
23
17
|
extend Uber::Delegates
|
@@ -40,9 +34,10 @@ module Reform::Form::ActiveModel
|
|
40
34
|
end
|
41
35
|
|
42
36
|
|
43
|
-
#
|
37
|
+
# Validator is the validatable object. On the class level, we define validations,
|
44
38
|
# on instance, it exposes #valid?.
|
45
|
-
|
39
|
+
require "delegate"
|
40
|
+
class Validator < SimpleDelegator
|
46
41
|
# current i18n scope: :activemodel.
|
47
42
|
include ActiveModel::Validations
|
48
43
|
|
@@ -61,12 +56,12 @@ module Reform::Form::ActiveModel
|
|
61
56
|
end
|
62
57
|
|
63
58
|
def initialize(form, name)
|
64
|
-
|
59
|
+
super(form)
|
65
60
|
self.class.model_name = name # one of the many reasons why i will drop support for AM::V in 2.1.
|
66
61
|
end
|
67
62
|
|
68
|
-
def method_missing(
|
69
|
-
|
63
|
+
def method_missing(m, *args, &block)
|
64
|
+
__getobj__.send(m, *args, &block) # send all methods to the form, even privates.
|
70
65
|
end
|
71
66
|
end
|
72
67
|
|
@@ -81,7 +76,6 @@ module Reform::Form::ActiveModel
|
|
81
76
|
validator = self.class.validator.new(self, model_name)
|
82
77
|
validator.valid? # run the Validations object's validator with the form as context. this won't pollute anything in the form.
|
83
78
|
|
84
|
-
|
85
79
|
#errors.merge!(validator.errors, "")
|
86
80
|
validator.errors.each do |name, error| # TODO: handle with proper merge, or something. validator.errors is ALWAYS AM::Errors.
|
87
81
|
errors.add(name, error)
|
@@ -24,12 +24,17 @@ module Reform::Form::MultiParameterAttributes
|
|
24
24
|
|
25
25
|
private
|
26
26
|
def params_to_date(year, month, day, hour, minute)
|
27
|
-
|
27
|
+
date_fields = [year, month, day].map!(&:to_i)
|
28
|
+
time_fields = [hour, minute].map!(&:to_i)
|
29
|
+
|
30
|
+
if date_fields.any?(&:zero?) || !Date.valid_date?(*date_fields)
|
31
|
+
return nil
|
32
|
+
end
|
28
33
|
|
29
34
|
if hour.blank? && minute.blank?
|
30
|
-
Date.new(
|
35
|
+
Date.new(*date_fields)
|
31
36
|
else
|
32
|
-
args =
|
37
|
+
args = date_fields + time_fields
|
33
38
|
Time.zone ? Time.zone.local(*args) :
|
34
39
|
Time.new(*args)
|
35
40
|
end
|
data/lib/reform/version.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
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/form_test.rb
CHANGED
@@ -25,7 +25,7 @@ class FormTest < MiniTest::Spec
|
|
25
25
|
property :title, validates: {presence: true}
|
26
26
|
properties :genre, :band, validates: {presence: true}
|
27
27
|
end
|
28
|
-
it
|
28
|
+
it do
|
29
29
|
form = SongForm.new(OpenStruct.new)
|
30
30
|
form.validate({})
|
31
31
|
form.errors.to_s.must_equal "{:title=>[\"can't be blank\"], :genre=>[\"can't be blank\"], :band=>[\"can't be blank\"]}"
|
data/test/mongoid_test.rb
CHANGED
@@ -1,313 +1,313 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
#
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
#
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
1
|
+
require 'test_helper'
|
2
|
+
def mongoid_present?
|
3
|
+
require 'mongoid'
|
4
|
+
Mongoid.configure do |config|
|
5
|
+
config.connect_to("reform-mongoid-test")
|
6
|
+
end
|
7
|
+
true
|
8
|
+
rescue
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
if mongoid_present?
|
13
|
+
require 'reform/mongoid'
|
14
|
+
|
15
|
+
class Disc
|
16
|
+
include Mongoid::Document
|
17
|
+
field :title, type: String
|
18
|
+
has_many :tunes
|
19
|
+
has_and_belongs_to_many :musicians
|
20
|
+
end
|
21
|
+
|
22
|
+
class Musician
|
23
|
+
include Mongoid::Document
|
24
|
+
field :name, type: String
|
25
|
+
end
|
26
|
+
|
27
|
+
class Tune
|
28
|
+
include Mongoid::Document
|
29
|
+
include Mongoid::Timestamps
|
30
|
+
field :title, type: String
|
31
|
+
belongs_to :disc
|
32
|
+
belongs_to :musician
|
33
|
+
end
|
34
|
+
|
35
|
+
class MongoidTest < MiniTest::Spec
|
36
|
+
class TuneForm < Reform::Form
|
37
|
+
include Reform::Form::Mongoid
|
38
|
+
model :tune
|
39
|
+
|
40
|
+
property :title
|
41
|
+
property :created_at
|
42
|
+
|
43
|
+
validates_uniqueness_of :title, scope: [:disc_id, :musician_id]
|
44
|
+
validates :created_at, :presence => true # have another property to test if we mix up.
|
45
|
+
|
46
|
+
property :musician do
|
47
|
+
property :name
|
48
|
+
validates_uniqueness_of :name # this currently also tests if Form::AR is included as a feature.
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
let(:disc) { Disc.create(:title => "Damnation") }
|
53
|
+
let(:musician) { Musician.create(:name => "Opeth") }
|
54
|
+
let(:form) { TuneForm.new(Tune.new(:musician => Musician.new)) }
|
55
|
+
|
56
|
+
it { form.class.i18n_scope.must_equal :mongoid }
|
57
|
+
|
58
|
+
it "allows accessing the database" do
|
59
|
+
end
|
60
|
+
|
61
|
+
# uniqueness
|
62
|
+
it "has no errors on title when title is unique for the same musician and disc" do
|
63
|
+
form.validate("title" => "The Gargoyle", "musician_id" => musician.id, "disc" => disc.id, "created_at" => "November 6, 1966")
|
64
|
+
assert_empty form.errors[:title]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "has errors on title when title is taken for the same musician and disc" do
|
68
|
+
skip "replace ActiveModel::Validations with our own, working and reusable gem."
|
69
|
+
Tune.create(title: "Windowpane", musician_id: musician.id, disc_id: disc.id)
|
70
|
+
form.validate("title" => "Windowpane", "musician_id" => musician.id, "disc" => disc)
|
71
|
+
refute_empty form.errors[:title]
|
72
|
+
end
|
73
|
+
|
74
|
+
# nested object taken.
|
75
|
+
it "is valid when musician name is unique" do
|
76
|
+
form.validate("musician" => {"name" => "Paul Gilbert"}, "title" => "The Gargoyle", "created_at" => "November 6, 1966").must_equal true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "is invalid and shows error when taken" do
|
80
|
+
Tune.delete_all
|
81
|
+
Musician.create(:name => "Racer X")
|
82
|
+
|
83
|
+
form.validate("musician" => {"name" => "Racer X"}, "title" => "Ghost Inside My Skin").must_equal false
|
84
|
+
form.errors.messages.must_equal({:"musician.name"=>["is already taken"], :created_at => ["can't be blank"]})
|
85
|
+
end
|
86
|
+
|
87
|
+
it "works with Composition" do
|
88
|
+
form = Class.new(Reform::Form) do
|
89
|
+
include Reform::Form::Mongoid
|
90
|
+
include Reform::Form::Composition
|
91
|
+
|
92
|
+
property :name, :on => :musician
|
93
|
+
validates_uniqueness_of :name
|
94
|
+
end.new(:musician => Musician.new)
|
95
|
+
|
96
|
+
Musician.create(:name => "Bad Religion")
|
97
|
+
form.validate("name" => "Bad Religion").must_equal false
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#save" do
|
101
|
+
# TODO: test 1-n?
|
102
|
+
it "calls model.save" do
|
103
|
+
Musician.delete_all
|
104
|
+
form.validate("musician" => {"name" => "Bad Religion"}, "title" => "Ghost Inside My Skin")
|
105
|
+
form.save
|
106
|
+
Musician.where(:name => "Bad Religion").size.must_equal 1
|
107
|
+
end
|
108
|
+
|
109
|
+
it "doesn't call model.save when block is given" do
|
110
|
+
Musician.delete_all
|
111
|
+
form.validate("name" => "Bad Religion")
|
112
|
+
form.save {}
|
113
|
+
Musician.where(:name => "Bad Religion").size.must_equal 0
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
118
|
|
119
|
-
|
120
|
-
|
119
|
+
class PopulateWithActiveRecordTest < MiniTest::Spec
|
120
|
+
class DiscForm < Reform::Form
|
121
121
|
|
122
|
-
|
122
|
+
property :title
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
124
|
+
collection :tunes, :populate_if_empty => Tune do
|
125
|
+
property :title
|
126
|
+
end
|
127
|
+
end
|
128
128
|
|
129
|
-
|
130
|
-
|
131
|
-
|
129
|
+
let (:disc) { Disc.new(:tunes => []) }
|
130
|
+
it do
|
131
|
+
form = DiscForm.new(disc)
|
132
132
|
|
133
|
-
|
133
|
+
form.validate("tunes" => [{"title" => "Straight From The Jacket"}])
|
134
134
|
|
135
|
-
#
|
136
|
-
|
137
|
-
|
135
|
+
# form populated.
|
136
|
+
form.tunes.size.must_equal 1
|
137
|
+
form.tunes[0].model.must_be_kind_of Tune
|
138
138
|
|
139
|
-
#
|
140
|
-
|
139
|
+
# model NOT populated.
|
140
|
+
disc.tunes.must_equal []
|
141
141
|
|
142
142
|
|
143
|
-
|
143
|
+
form.sync
|
144
144
|
|
145
|
-
#
|
146
|
-
|
147
|
-
|
145
|
+
# form populated.
|
146
|
+
form.tunes.size.must_equal 1
|
147
|
+
form.tunes[0].model.must_be_kind_of Tune
|
148
148
|
|
149
|
-
#
|
150
|
-
|
151
|
-
|
152
|
-
|
149
|
+
# model also populated.
|
150
|
+
tune = disc.tunes[0]
|
151
|
+
disc.tunes.must_equal [tune]
|
152
|
+
tune.title.must_equal "Straight From The Jacket"
|
153
153
|
|
154
154
|
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
|
155
|
+
# if ActiveRecord::VERSION::STRING !~ /^3.0/
|
156
|
+
# # saving saves association.
|
157
|
+
# form.save
|
158
|
+
#
|
159
|
+
# disc.reload
|
160
|
+
# tune = disc.tunes[0]
|
161
|
+
# disc.tunes.must_equal [tune]
|
162
|
+
# tune.title.must_equal "Straight From The Jacket"
|
163
|
+
# end
|
164
|
+
end
|
165
165
|
|
166
166
|
|
167
|
-
|
168
|
-
|
169
|
-
|
167
|
+
describe "modifying 1., adding 2." do
|
168
|
+
let (:tune) { Tune.new(:title => "Part 2") }
|
169
|
+
let (:disc) { Disc.create.tap { |a| a.tunes << tune } }
|
170
170
|
|
171
|
-
|
172
|
-
|
171
|
+
it do
|
172
|
+
form = DiscForm.new(disc)
|
173
173
|
|
174
|
-
|
175
|
-
|
176
|
-
|
174
|
+
id = disc.tunes[0].id
|
175
|
+
disc.tunes[0].persisted?.must_equal true
|
176
|
+
assert id.to_s.size > 0
|
177
177
|
|
178
|
-
|
178
|
+
form.validate("tunes" => [{"title" => "Part Two"}, {"title" => "Check For A Pulse"}])
|
179
179
|
|
180
|
-
#
|
181
|
-
|
182
|
-
|
183
|
-
|
180
|
+
# form populated.
|
181
|
+
form.tunes.size.must_equal 2
|
182
|
+
form.tunes[0].model.must_be_kind_of Tune
|
183
|
+
form.tunes[1].model.must_be_kind_of Tune
|
184
184
|
|
185
|
-
#
|
186
|
-
|
185
|
+
# model NOT populated.
|
186
|
+
disc.tunes.must_equal [tune]
|
187
187
|
|
188
188
|
|
189
|
-
|
189
|
+
form.sync
|
190
190
|
|
191
|
-
#
|
192
|
-
|
191
|
+
# form populated.
|
192
|
+
form.tunes.size.must_equal 2
|
193
193
|
|
194
|
-
#
|
195
|
-
|
194
|
+
# model also populated.
|
195
|
+
disc.tunes.size.must_equal 2
|
196
196
|
|
197
|
-
#
|
198
|
-
|
199
|
-
#
|
200
|
-
|
197
|
+
# corrected title
|
198
|
+
disc.tunes[0].title.must_equal "Part Two"
|
199
|
+
# ..but same tune.
|
200
|
+
disc.tunes[0].id.must_equal id
|
201
201
|
|
202
|
-
#
|
203
|
-
|
204
|
-
|
205
|
-
|
202
|
+
# and a new tune.
|
203
|
+
disc.tunes[1].title.must_equal "Check For A Pulse"
|
204
|
+
disc.tunes[1].persisted?.must_equal true # TODO: with << strategy, this shouldn't be saved.
|
205
|
+
end
|
206
206
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
207
|
+
describe 'using nested_models_attributes to modify nested collection' do
|
208
|
+
class ActiveModelDiscForm < Reform::Form
|
209
|
+
include Reform::Form::ActiveModel
|
210
|
+
include Reform::Form::ActiveModel::FormBuilderMethods
|
211
211
|
|
212
|
-
|
212
|
+
property :title
|
213
213
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
214
|
+
collection :tunes, :populate_if_empty => Tune do
|
215
|
+
property :title
|
216
|
+
end
|
217
|
+
end
|
218
218
|
|
219
|
-
|
220
|
-
|
219
|
+
let (:disc) { Disc.create(:title => 'Greatest Hits') }
|
220
|
+
let (:form) { ActiveModelDiscForm.new(disc) }
|
221
221
|
|
222
|
-
|
223
|
-
|
222
|
+
it do
|
223
|
+
form.validate('tunes_attributes' => {'0' => {'title' => 'Tango'}})
|
224
224
|
|
225
|
-
#
|
226
|
-
|
227
|
-
|
228
|
-
|
225
|
+
# form populated.
|
226
|
+
form.tunes.size.must_equal 1
|
227
|
+
form.tunes[0].model.must_be_kind_of Tune
|
228
|
+
form.tunes[0].title.must_equal 'Tango'
|
229
229
|
|
230
|
-
#
|
231
|
-
|
230
|
+
# model NOT populated.
|
231
|
+
disc.tunes.must_equal []
|
232
232
|
|
233
|
-
|
233
|
+
form.save
|
234
234
|
|
235
|
-
#
|
236
|
-
|
237
|
-
|
238
|
-
|
235
|
+
# nested model persisted.
|
236
|
+
first_tune = disc.tunes[0]
|
237
|
+
first_tune.persisted?.must_equal true
|
238
|
+
assert first_tune.id.to_s.size > 0
|
239
239
|
|
240
|
-
#
|
241
|
-
|
240
|
+
# form populated.
|
241
|
+
form.tunes.size.must_equal 1
|
242
242
|
|
243
|
-
#
|
244
|
-
|
245
|
-
|
243
|
+
# model also populated.
|
244
|
+
disc.tunes.size.must_equal 1
|
245
|
+
disc.tunes[0].title.must_equal 'Tango'
|
246
246
|
|
247
|
-
|
248
|
-
|
247
|
+
form = ActiveModelDiscForm.new(disc)
|
248
|
+
form.validate('tunes_attributes' => {'0' => {'id' => first_tune.id, 'title' => 'Tango nuevo'}, '1' => {'title' => 'Waltz'}})
|
249
249
|
|
250
|
-
#
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
250
|
+
# form populated.
|
251
|
+
form.tunes.size.must_equal 2
|
252
|
+
form.tunes[0].model.must_be_kind_of Tune
|
253
|
+
form.tunes[1].model.must_be_kind_of Tune
|
254
|
+
form.tunes[0].title.must_equal 'Tango nuevo'
|
255
|
+
form.tunes[1].title.must_equal 'Waltz'
|
256
256
|
|
257
|
-
#
|
258
|
-
|
259
|
-
|
257
|
+
# model NOT populated.
|
258
|
+
disc.tunes.size.must_equal 1
|
259
|
+
disc.tunes[0].title.must_equal 'Tango'
|
260
260
|
|
261
|
-
|
261
|
+
form.save
|
262
262
|
|
263
|
-
#
|
264
|
-
|
263
|
+
# form populated.
|
264
|
+
form.tunes.size.must_equal 2
|
265
265
|
|
266
|
-
#
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
266
|
+
# model also populated.
|
267
|
+
disc.tunes.size.must_equal 2
|
268
|
+
disc.tunes[0].id.must_equal first_tune.id
|
269
|
+
disc.tunes[0].persisted?.must_equal true
|
270
|
+
disc.tunes[1].persisted?.must_equal true
|
271
|
+
disc.tunes[0].title.must_equal 'Tango nuevo'
|
272
|
+
disc.tunes[1].title.must_equal 'Waltz'
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
276
|
|
277
|
-
#
|
278
|
-
#
|
279
|
-
#
|
277
|
+
# it do
|
278
|
+
# a=Disc.new
|
279
|
+
# a.tunes << Tune.new(title: "Old What's His Name") # Tune does not get persisted.
|
280
280
|
|
281
|
-
#
|
281
|
+
# a.tunes[1] = Tune.new(title: "Permanent Rust")
|
282
282
|
|
283
|
-
#
|
284
|
-
#
|
283
|
+
# puts "@@@"
|
284
|
+
# puts a.tunes.inspect
|
285
285
|
|
286
|
-
#
|
287
|
-
#
|
288
|
-
#
|
286
|
+
# puts "---"
|
287
|
+
# a.save
|
288
|
+
# puts a.tunes.inspect
|
289
289
|
|
290
|
-
#
|
290
|
+
# b = a.tunes.first
|
291
291
|
|
292
|
-
#
|
293
|
-
#
|
294
|
-
#
|
295
|
-
#
|
296
|
-
#
|
297
|
-
|
298
|
-
#
|
299
|
-
#
|
292
|
+
# a.tunes = [Tune.new(title:"Biomag")]
|
293
|
+
# puts "\\\\"
|
294
|
+
# a.save
|
295
|
+
# a.reload
|
296
|
+
# puts a.tunes.inspect
|
297
|
+
|
298
|
+
# b.reload
|
299
|
+
# puts "#{b.inspect}, #{b.persisted?}"
|
300
300
|
|
301
301
|
|
302
|
-
#
|
303
|
-
#
|
304
|
-
#
|
305
|
-
#
|
306
|
-
#
|
307
|
-
#
|
302
|
+
# a.tunes = [a.tunes.first, Tune.new(title: "Count Down")]
|
303
|
+
# b = a.tunes.first
|
304
|
+
# puts ":::::"
|
305
|
+
# a.save
|
306
|
+
# a.reload
|
307
|
+
# puts a.tunes.inspect
|
308
308
|
|
309
|
-
#
|
310
|
-
#
|
311
|
-
#
|
312
|
-
|
313
|
-
|
309
|
+
# b.reload
|
310
|
+
# puts "#{b.inspect}, #{b.persisted?}"
|
311
|
+
# end
|
312
|
+
end
|
313
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ReformTest < ReformSpec
|
4
|
+
describe "Date" do
|
5
|
+
Person = Struct.new(:date_of_birth)
|
6
|
+
let (:form) { DateOfBirthForm.new(Person.new) }
|
7
|
+
|
8
|
+
class DateOfBirthForm < Reform::Form
|
9
|
+
feature Reform::Form::ActiveModel::FormBuilderMethods
|
10
|
+
feature Reform::Form::MultiParameterAttributes
|
11
|
+
property :date_of_birth, type: Date, :multi_params => true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "munges multi-param date fields into a valid Date attribute" do
|
15
|
+
date_of_birth_params = { "date_of_birth(1i)"=>"1950", "date_of_birth(2i)"=>"1", "date_of_birth(3i)"=>"1" }
|
16
|
+
form.validate(date_of_birth_params)
|
17
|
+
form.date_of_birth.must_equal Date.civil(1950, 1, 1)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "handles invalid Time input" do
|
21
|
+
date_of_birth_params = { "date_of_birth(1i)"=>"1950", "date_of_birth(2i)"=>"99", "date_of_birth(3i)"=>"1" }
|
22
|
+
form.validate(date_of_birth_params)
|
23
|
+
form.date_of_birth.must_equal nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "DateTime" do
|
28
|
+
Party = Struct.new(:start_time)
|
29
|
+
let (:form) { PartyForm.new(Party.new) }
|
30
|
+
|
31
|
+
class PartyForm < Reform::Form
|
32
|
+
feature Reform::Form::ActiveModel::FormBuilderMethods
|
33
|
+
feature Reform::Form::MultiParameterAttributes
|
34
|
+
property :start_time, type: DateTime, :multi_params => true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "munges multi-param date and time fields into a valid Time attribute" do
|
38
|
+
start_time_params = { "start_time(1i)"=>"2000", "start_time(2i)"=>"1", "start_time(3i)"=>"1", "start_time(4i)"=>"12", "start_time(5i)"=>"00" }
|
39
|
+
time_format = "%Y-%m-%d %H:%M"
|
40
|
+
form.validate(start_time_params)
|
41
|
+
form.start_time.strftime(time_format).must_equal DateTime.strptime("2000-01-01 12:00", time_format)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "handles invalid Time input" do
|
45
|
+
start_time_params = { "start_time(1i)"=>"2000", "start_time(2i)"=>"99", "start_time(3i)"=>"1", "start_time(4i)"=>"12", "start_time(5i)"=>"00" }
|
46
|
+
form.validate(start_time_params)
|
47
|
+
form.start_time.must_equal nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
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.
|
4
|
+
version: 2.0.5
|
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-09-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: disposable
|
@@ -245,6 +245,7 @@ files:
|
|
245
245
|
- reform.gemspec
|
246
246
|
- test/active_model_custom_validation_translations_test.rb
|
247
247
|
- test/active_model_test.rb
|
248
|
+
- test/active_model_validation_for_property_named_format_test.rb
|
248
249
|
- test/active_record_test.rb
|
249
250
|
- test/benchmarking.rb
|
250
251
|
- test/builder_test.rb
|
@@ -292,6 +293,7 @@ files:
|
|
292
293
|
- test/model_validations_test.rb
|
293
294
|
- test/module_test.rb
|
294
295
|
- test/mongoid_test.rb
|
296
|
+
- test/multi_parameter_attributes_test.rb
|
295
297
|
- test/populate_test.rb
|
296
298
|
- test/prepopulator_test.rb
|
297
299
|
- test/rails/integration_test.rb
|
@@ -335,6 +337,7 @@ summary: Form object decoupled from models with validation, population and prese
|
|
335
337
|
test_files:
|
336
338
|
- test/active_model_custom_validation_translations_test.rb
|
337
339
|
- test/active_model_test.rb
|
340
|
+
- test/active_model_validation_for_property_named_format_test.rb
|
338
341
|
- test/active_record_test.rb
|
339
342
|
- test/benchmarking.rb
|
340
343
|
- test/builder_test.rb
|
@@ -382,6 +385,7 @@ test_files:
|
|
382
385
|
- test/model_validations_test.rb
|
383
386
|
- test/module_test.rb
|
384
387
|
- test/mongoid_test.rb
|
388
|
+
- test/multi_parameter_attributes_test.rb
|
385
389
|
- test/populate_test.rb
|
386
390
|
- test/prepopulator_test.rb
|
387
391
|
- test/rails/integration_test.rb
|