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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 565c9da5e49ef68eac9707011e9574284cac113c
4
- data.tar.gz: 5feef4e923913adb8099b6e307aa38b0adff6dbf
3
+ metadata.gz: a7b6c745acf6fc96e9d5c0291d4fa64df5be3c92
4
+ data.tar.gz: 0304e04e195f525af7aed8081c87a328885c2581
5
5
  SHA512:
6
- metadata.gz: c1e962dda69e280292e94394aea4876e3ec2714cf1dc07de305a0c316248ecc065ab23785014838780258c6ac0b91d68d99c5c985494d601ac157636067e97e4
7
- data.tar.gz: dbc31dd351bb1ac8cf223e513676d061ed85237a5eecba759319d753a482e5a20246a3859d6e23b8a6ede2893628587c833c8c1b70242fa2dc2a22e3c78252c9
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
@@ -4,5 +4,4 @@ gemspec
4
4
 
5
5
  #gem 'representable', path: "../representable"
6
6
  # gem "disposable", path: "../disposable"
7
- # gem "disposable", github: "apotonick/disposable"o
8
- # gem "uber", path: "../uber"
7
+ # gem "disposable", github: "apotonick/disposable"
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
- # Note: The preferred way for validations should be Lotus::Validations, as ActiveModel::Validation's
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
- # Validators is the validatable object. On the class level, we define validations,
37
+ # Validator is the validatable object. On the class level, we define validations,
44
38
  # on instance, it exposes #valid?.
45
- class Validator
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
- @form = form
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(method_name, *args, &block)
69
- @form.send(method_name, *args, &block)
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
- return nil if [year, month, day].any?(&:blank?)
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(year.to_i, month.to_i, day.to_i) # TODO: test fails.
35
+ Date.new(*date_fields)
31
36
  else
32
- args = [year, month, day, hour, minute].map(&:to_i)
37
+ args = date_fields + time_fields
33
38
  Time.zone ? Time.zone.local(*args) :
34
39
  Time.new(*args)
35
40
  end
@@ -1,3 +1,3 @@
1
1
  module Reform
2
- VERSION = "2.0.4"
2
+ VERSION = "2.0.5"
3
3
  end
@@ -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 "xxx" do
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\"]}"
@@ -131,4 +131,8 @@ class ModelReflectionTest < MiniTest::Spec
131
131
  form.defined_enums.must_include Artist
132
132
  end
133
133
  end
134
+
135
+ describe "::validators_on" do
136
+ it { assert SongWithArtistForm.validators_on }
137
+ end
134
138
  end
data/test/mongoid_test.rb CHANGED
@@ -1,313 +1,313 @@
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
-
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
- # class PopulateWithActiveRecordTest < MiniTest::Spec
120
- # class DiscForm < Reform::Form
119
+ class PopulateWithActiveRecordTest < MiniTest::Spec
120
+ class DiscForm < Reform::Form
121
121
 
122
- # property :title
122
+ property :title
123
123
 
124
- # collection :tunes, :populate_if_empty => Tune do
125
- # property :title
126
- # end
127
- # end
124
+ collection :tunes, :populate_if_empty => Tune do
125
+ property :title
126
+ end
127
+ end
128
128
 
129
- # let (:disc) { Disc.new(:tunes => []) }
130
- # it do
131
- # form = DiscForm.new(disc)
129
+ let (:disc) { Disc.new(:tunes => []) }
130
+ it do
131
+ form = DiscForm.new(disc)
132
132
 
133
- # form.validate("tunes" => [{"title" => "Straight From The Jacket"}])
133
+ form.validate("tunes" => [{"title" => "Straight From The Jacket"}])
134
134
 
135
- # # form populated.
136
- # form.tunes.size.must_equal 1
137
- # form.tunes[0].model.must_be_kind_of Tune
135
+ # form populated.
136
+ form.tunes.size.must_equal 1
137
+ form.tunes[0].model.must_be_kind_of Tune
138
138
 
139
- # # model NOT populated.
140
- # disc.tunes.must_equal []
139
+ # model NOT populated.
140
+ disc.tunes.must_equal []
141
141
 
142
142
 
143
- # form.sync
143
+ form.sync
144
144
 
145
- # # form populated.
146
- # form.tunes.size.must_equal 1
147
- # form.tunes[0].model.must_be_kind_of Tune
145
+ # form populated.
146
+ form.tunes.size.must_equal 1
147
+ form.tunes[0].model.must_be_kind_of Tune
148
148
 
149
- # # model also populated.
150
- # tune = disc.tunes[0]
151
- # disc.tunes.must_equal [tune]
152
- # tune.title.must_equal "Straight From The Jacket"
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
- # # 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
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
- # describe "modifying 1., adding 2." do
168
- # let (:tune) { Tune.new(:title => "Part 2") }
169
- # let (:disc) { Disc.create.tap { |a| a.tunes << tune } }
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
- # it do
172
- # form = DiscForm.new(disc)
171
+ it do
172
+ form = DiscForm.new(disc)
173
173
 
174
- # id = disc.tunes[0].id
175
- # disc.tunes[0].persisted?.must_equal true
176
- # assert id.to_s.size > 0
174
+ id = disc.tunes[0].id
175
+ disc.tunes[0].persisted?.must_equal true
176
+ assert id.to_s.size > 0
177
177
 
178
- # form.validate("tunes" => [{"title" => "Part Two"}, {"title" => "Check For A Pulse"}])
178
+ form.validate("tunes" => [{"title" => "Part Two"}, {"title" => "Check For A Pulse"}])
179
179
 
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
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
- # # model NOT populated.
186
- # disc.tunes.must_equal [tune]
185
+ # model NOT populated.
186
+ disc.tunes.must_equal [tune]
187
187
 
188
188
 
189
- # form.sync
189
+ form.sync
190
190
 
191
- # # form populated.
192
- # form.tunes.size.must_equal 2
191
+ # form populated.
192
+ form.tunes.size.must_equal 2
193
193
 
194
- # # model also populated.
195
- # disc.tunes.size.must_equal 2
194
+ # model also populated.
195
+ disc.tunes.size.must_equal 2
196
196
 
197
- # # corrected title
198
- # disc.tunes[0].title.must_equal "Part Two"
199
- # # ..but same tune.
200
- # disc.tunes[0].id.must_equal id
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
- # # 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
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
- # 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
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
- # property :title
212
+ property :title
213
213
 
214
- # collection :tunes, :populate_if_empty => Tune do
215
- # property :title
216
- # end
217
- # end
214
+ collection :tunes, :populate_if_empty => Tune do
215
+ property :title
216
+ end
217
+ end
218
218
 
219
- # let (:disc) { Disc.create(:title => 'Greatest Hits') }
220
- # let (:form) { ActiveModelDiscForm.new(disc) }
219
+ let (:disc) { Disc.create(:title => 'Greatest Hits') }
220
+ let (:form) { ActiveModelDiscForm.new(disc) }
221
221
 
222
- # it do
223
- # form.validate('tunes_attributes' => {'0' => {'title' => 'Tango'}})
222
+ it do
223
+ form.validate('tunes_attributes' => {'0' => {'title' => 'Tango'}})
224
224
 
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'
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
- # # model NOT populated.
231
- # disc.tunes.must_equal []
230
+ # model NOT populated.
231
+ disc.tunes.must_equal []
232
232
 
233
- # form.save
233
+ form.save
234
234
 
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
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
- # # form populated.
241
- # form.tunes.size.must_equal 1
240
+ # form populated.
241
+ form.tunes.size.must_equal 1
242
242
 
243
- # # model also populated.
244
- # disc.tunes.size.must_equal 1
245
- # disc.tunes[0].title.must_equal 'Tango'
243
+ # model also populated.
244
+ disc.tunes.size.must_equal 1
245
+ disc.tunes[0].title.must_equal 'Tango'
246
246
 
247
- # form = ActiveModelDiscForm.new(disc)
248
- # form.validate('tunes_attributes' => {'0' => {'id' => first_tune.id, 'title' => 'Tango nuevo'}, '1' => {'title' => 'Waltz'}})
247
+ form = ActiveModelDiscForm.new(disc)
248
+ form.validate('tunes_attributes' => {'0' => {'id' => first_tune.id, 'title' => 'Tango nuevo'}, '1' => {'title' => 'Waltz'}})
249
249
 
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'
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
- # # model NOT populated.
258
- # disc.tunes.size.must_equal 1
259
- # disc.tunes[0].title.must_equal 'Tango'
257
+ # model NOT populated.
258
+ disc.tunes.size.must_equal 1
259
+ disc.tunes[0].title.must_equal 'Tango'
260
260
 
261
- # form.save
261
+ form.save
262
262
 
263
- # # form populated.
264
- # form.tunes.size.must_equal 2
263
+ # form populated.
264
+ form.tunes.size.must_equal 2
265
265
 
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
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
- # # it do
278
- # # a=Disc.new
279
- # # a.tunes << Tune.new(title: "Old What's His Name") # Tune does not get persisted.
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
- # # a.tunes[1] = Tune.new(title: "Permanent Rust")
281
+ # a.tunes[1] = Tune.new(title: "Permanent Rust")
282
282
 
283
- # # puts "@@@"
284
- # # puts a.tunes.inspect
283
+ # puts "@@@"
284
+ # puts a.tunes.inspect
285
285
 
286
- # # puts "---"
287
- # # a.save
288
- # # puts a.tunes.inspect
286
+ # puts "---"
287
+ # a.save
288
+ # puts a.tunes.inspect
289
289
 
290
- # # b = a.tunes.first
290
+ # b = a.tunes.first
291
291
 
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?}"
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
- # # 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
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
- # # b.reload
310
- # # puts "#{b.inspect}, #{b.persisted?}"
311
- # # end
312
- # end
313
- # end
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
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-08-27 00:00:00.000000000 Z
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