form_objects 1.0.0
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +524 -0
- data/Rakefile +6 -0
- data/form_objects.gemspec +27 -0
- data/lib/form_objects/associated_validator.rb +9 -0
- data/lib/form_objects/base.rb +33 -0
- data/lib/form_objects/naming.rb +13 -0
- data/lib/form_objects/nesting.rb +13 -0
- data/lib/form_objects/params_converter/collection_converter.rb +51 -0
- data/lib/form_objects/params_converter/date_converter.rb +41 -0
- data/lib/form_objects/params_converter.rb +18 -0
- data/lib/form_objects/serializer.rb +18 -0
- data/lib/form_objects/version.rb +3 -0
- data/lib/form_objects.rb +11 -0
- data/spec/base_spec.rb +97 -0
- data/spec/naming_spec.rb +14 -0
- data/spec/nesting_spec.rb +88 -0
- data/spec/params_converter_spec.rb +91 -0
- data/spec/serializer_spec.rb +75 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/examples.rb +44 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 29632d193346200cb575dc61d4693a60ce990177
|
4
|
+
data.tar.gz: 08422a044d13f719e346d2efd03dc88816f7a78a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: be332e69fa86a7066cdfa3e0c3ebfc4826e5eab0821ea77a4a6c267774c582446a766a9389f396826314ef980bd944a5396bb5e16ad74f69f2b529fcb4b6e45f
|
7
|
+
data.tar.gz: 90f906ac406cb2b4bf720dae71790a6b8bc5ad1fa251bb13e9404f7fac6ee824efc5ee46bc49898a9ea3287e4b9445fc73433ad1efe1483ea83758ffd6b4791e
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in form_objects.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem 'rspec', '~> 2.14'
|
8
|
+
gem 'rspec-mocks', '~> 2.14'
|
9
|
+
gem "codeclimate-test-reporter", require: nil
|
10
|
+
gem 'mutant'
|
11
|
+
gem 'mutant-rspec'
|
12
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Przemek Lusar
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,524 @@
|
|
1
|
+
# FormObjects
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/lluzak/form_objects)
|
4
|
+
[](https://travis-ci.org/lluzak/form_objects)
|
5
|
+
|
6
|
+
FormObjects gives you a easy way of building complex and nested form objects.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'form_objects'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install form_objects
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
In this micro-library you will not find any magic. Explicit is better than implicit. Simple is better than complex.
|
25
|
+
|
26
|
+
### Standard form
|
27
|
+
|
28
|
+
At the beginning of the life of your application most of the objects is exactly the same as the form. User include `first_name` and `last_name`.
|
29
|
+
Only `first_name` is required.
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
class User
|
33
|
+
validates :first_name, :presence => true
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# controller
|
39
|
+
|
40
|
+
def new
|
41
|
+
@user = User.new
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
```erb
|
46
|
+
<%= form_for @user do |f| %>
|
47
|
+
<%= f.label :first_name %>:
|
48
|
+
<%= f.text_field :first_name %><br />
|
49
|
+
|
50
|
+
<%= f.label :last_name %>:
|
51
|
+
<%= f.text_field :last_name %><br />
|
52
|
+
|
53
|
+
<%= f.submit %>
|
54
|
+
<% end %>
|
55
|
+
```
|
56
|
+
|
57
|
+
## Form with FormObjects
|
58
|
+
|
59
|
+
How the same can be achieved using `FormObjects`?
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class UserForm < FormObjects::Base
|
63
|
+
field :first_name, String
|
64
|
+
field :last_name, String
|
65
|
+
|
66
|
+
validates :first_name, presence: true
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
Out new `UserForm` class does not know nothing about user. Because there is no connection to database.
|
71
|
+
That is why you need to explicitly defined each field. First argument is name of attribute and second argument is type
|
72
|
+
of this attribute. `#field` method is just alias for `attribute` method from [virtus](https://github.com/solnic/virtus#using-virtus-with-classes).
|
73
|
+
|
74
|
+
On `FormObjects` you can use the same validations like in `ActiveRecord::Base` object. So here there is no change.
|
75
|
+
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
# controller
|
79
|
+
|
80
|
+
def new
|
81
|
+
@user_form = UserForm.new
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
```erb
|
86
|
+
<%= form_for @user_form do |f| %>
|
87
|
+
<%= f.label :first_name %>:
|
88
|
+
<%= f.text_field :first_name %><br />
|
89
|
+
|
90
|
+
<%= f.label :last_name %>:
|
91
|
+
<%= f.text_field :last_name %><br />
|
92
|
+
|
93
|
+
<%= f.submit %>
|
94
|
+
<% end %>
|
95
|
+
```
|
96
|
+
|
97
|
+
## How to save FormObject do database?
|
98
|
+
|
99
|
+
Ok, now we can just save user to our storage. Do you you think about `@user_form.save`?
|
100
|
+
|
101
|
+

|
102
|
+
|
103
|
+
Keep your objects simple. Form object is responsible for maintaining and validating data. Things like storing these data leave other objects. So what now?
|
104
|
+
You can create `UserCreator`.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
class UserCreator
|
108
|
+
def initialize(attributes)
|
109
|
+
@attributes = attributes
|
110
|
+
end
|
111
|
+
|
112
|
+
def create
|
113
|
+
User.create(@attributes)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
## Namespace for attributes
|
119
|
+
|
120
|
+
Rails form generator will generate form with attributes scoped in `user_form`. So when you submit your form `params` will look like this:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
{
|
124
|
+
:user_form => {
|
125
|
+
:first_name => "First name",
|
126
|
+
:last_name => "Last name"
|
127
|
+
}
|
128
|
+
}
|
129
|
+
```
|
130
|
+
|
131
|
+
You can change it by adding `FormObjects::Naming` to your form class definition.
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
class UserForm < FormObjects::Base
|
135
|
+
include FormObjects::Naming
|
136
|
+
|
137
|
+
field :first_name, String
|
138
|
+
field :last_name, String
|
139
|
+
|
140
|
+
validates :first_name, presence: true
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
`FormObjects::Naming` will generate `.model_name` method. This method will return `ActiveModel::Name` object who will pretend that the model does not include `Form` in the name.
|
145
|
+
You can of course define your own `.model_name` method.
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
class UserForm < FormObjects::Base
|
149
|
+
field :first_name, String
|
150
|
+
field :last_name, String
|
151
|
+
|
152
|
+
validates :first_name, presence: true
|
153
|
+
|
154
|
+
def self.model_name
|
155
|
+
ActiveModel::Name.new(self, nil, "User")
|
156
|
+
end
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
After this change params will look like this:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
{
|
164
|
+
:user => {
|
165
|
+
:first_name => "First name",
|
166
|
+
:last_name => "Last name"
|
167
|
+
}
|
168
|
+
}
|
169
|
+
```
|
170
|
+
|
171
|
+
So we can implement `create` controller action.
|
172
|
+
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
# controller
|
176
|
+
|
177
|
+
def create
|
178
|
+
@user_form = UserForm.new(params[:user])
|
179
|
+
|
180
|
+
if @user_form.valid?
|
181
|
+
UserCreator.new(@user_form.serialized_attributes).create
|
182
|
+
else
|
183
|
+
render :new
|
184
|
+
end
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
## Additional attribute
|
189
|
+
|
190
|
+
Let's do something standard. Add term and condition checkbox. In rails way you will add `term` attribute to your `User` model, didn't you?
|
191
|
+
Do not you think it's a little weird? I think so. Let's do this in `UserForm`.
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
class UserForm < FormObjects::Base
|
195
|
+
include FormObjects::Naming
|
196
|
+
|
197
|
+
field :first_name, String
|
198
|
+
field :last_name, String
|
199
|
+
field :terms, Boolean
|
200
|
+
|
201
|
+
validates :first_name, presence: true
|
202
|
+
validates :terms, acceptance: true
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
But there is a problem with `terms` validation.
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
UserForm.new(:terms => "1")
|
210
|
+
# => #<UserForm:0x00000004bbd2e0 @first_name=nil, @last_name=nil, @terms=true>
|
211
|
+
```
|
212
|
+
|
213
|
+
Virtus library will transform `terms` value into boolean. But by default `acceptance` will look for `"1"` value.
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
form = UserForm.new(:terms => "1")
|
217
|
+
# => #<UserForm:0x00000004be2400 @first_name=nil, @last_name=nil, @terms=true>
|
218
|
+
form.valid?
|
219
|
+
# => false
|
220
|
+
form.errors.full_messages
|
221
|
+
# => ["First name can't be blank", "Terms must be accepted"]
|
222
|
+
```
|
223
|
+
|
224
|
+
Solution? You can change `terms` field into `String` type. But this is strange. I recommended clarify validation.
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
class UserForm < FormObjects::Base
|
228
|
+
include FormObjects::Naming
|
229
|
+
|
230
|
+
field :first_name, String
|
231
|
+
field :last_name, String
|
232
|
+
field :terms, Boolean
|
233
|
+
|
234
|
+
validates :first_name, presence: true
|
235
|
+
validates :terms, acceptance: { accept: true }
|
236
|
+
end
|
237
|
+
```
|
238
|
+
|
239
|
+
Now everything should works just fine. No magic.
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
form = UserForm.new(:terms => "1")
|
243
|
+
# => #<UserForm:0x00000004de7f20 @terms=true, @first_name=nil, @last_name=nil>
|
244
|
+
form.valid?
|
245
|
+
# => false
|
246
|
+
form.errors.full_messages
|
247
|
+
# => ["First name can't be blank"]
|
248
|
+
# No terms errors
|
249
|
+
```
|
250
|
+
|
251
|
+
## Form in form (nested_form)
|
252
|
+
|
253
|
+
Let add another form to our `UserForm`. User during registration should give the address. Lets create `LocationForm`.
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
class LocationForm < FormObjects::Form
|
257
|
+
field :address, String
|
258
|
+
|
259
|
+
validates :address, presence: true
|
260
|
+
end
|
261
|
+
```
|
262
|
+
|
263
|
+
Instead of `field` method we need to use `nested_form`.
|
264
|
+
|
265
|
+
```ruby
|
266
|
+
class UserForm < FormObjects::Base
|
267
|
+
include FormObjects::Naming
|
268
|
+
|
269
|
+
field :first_name, String
|
270
|
+
field :last_name, String
|
271
|
+
field :terms, Boolean
|
272
|
+
|
273
|
+
nested_form :address, LocationForm
|
274
|
+
|
275
|
+
validates :first_name, presence: true
|
276
|
+
validates :terms, acceptance: { accept: true }
|
277
|
+
end
|
278
|
+
```
|
279
|
+
|
280
|
+
I will switch now to `simple_form`. But you can use original `form_for` form rails.
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
<%= simple_form_for @user_form, :url => homes_path do |f| %>
|
284
|
+
<%= f.input :first_name %>
|
285
|
+
<%= f.input :last_name %>
|
286
|
+
<%= f.input :terms, :as => :boolean %>
|
287
|
+
|
288
|
+
<%= f.simple_fields_for :address do |a| %>
|
289
|
+
<%= a.input :address %>
|
290
|
+
<% end %>
|
291
|
+
|
292
|
+
<%= f.button :submit %>
|
293
|
+
<% end %>
|
294
|
+
```
|
295
|
+
|
296
|
+
You will notice one problem. That `address` field is not rendered. The reason is that `LocationForm` is not initialized.
|
297
|
+
You can use Virtus `default` attribute to accomplish this.
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
class UserForm < FormObjects::Base
|
301
|
+
include FormObjects::Naming
|
302
|
+
|
303
|
+
field :first_name, String
|
304
|
+
field :last_name, String
|
305
|
+
field :terms, Boolean
|
306
|
+
|
307
|
+
nested_form :address, LocationForm, default: proc { LocationForm.new }
|
308
|
+
|
309
|
+
validates :first_name, presence: true
|
310
|
+
validates :terms, acceptance: { accept: true }
|
311
|
+
end
|
312
|
+
```
|
313
|
+
|
314
|
+
After this change location form should be rendered. When you submit this form params will looks like:
|
315
|
+
|
316
|
+
```ruby
|
317
|
+
{
|
318
|
+
:user => {
|
319
|
+
:first_name => "FirstName",
|
320
|
+
:last_name => "LastName",
|
321
|
+
:terms => "1",
|
322
|
+
:address_attributes => {
|
323
|
+
:address => "Street"
|
324
|
+
}
|
325
|
+
}
|
326
|
+
}
|
327
|
+
```
|
328
|
+
|
329
|
+
When you pass these `params` to form object you can use `serialized_attriubtes` method. It will return developer-friendly hash with values.
|
330
|
+
|
331
|
+
```ruby
|
332
|
+
UserForm.new(params).serialized_attributes
|
333
|
+
# => {:first_name=>"FirstName", :last_name=>"LastName", :terms=>true, :address=>{:address=>"Street"}}
|
334
|
+
```
|
335
|
+
|
336
|
+
You can use this `Hash` inside your classes, services etc.
|
337
|
+
|
338
|
+
## Many forms in form
|
339
|
+
|
340
|
+
What we should do when we need more than 1 address? We can use `Array` from Virtus.
|
341
|
+
|
342
|
+
```ruby
|
343
|
+
class UserForm < FormObjects::Base
|
344
|
+
include FormObjects::Naming
|
345
|
+
|
346
|
+
field :first_name, String
|
347
|
+
field :last_name, String
|
348
|
+
field :terms, Boolean
|
349
|
+
|
350
|
+
nested_form :addresses, Array[LocationForm]
|
351
|
+
|
352
|
+
validates :first_name, presence: true
|
353
|
+
validates :terms, acceptance: { accept: true }
|
354
|
+
end
|
355
|
+
```
|
356
|
+
|
357
|
+
I changed `address` to `addresses` and instead of simple `LocationForm` we will use `Array[LocationForm]`. But once again problem with default values.
|
358
|
+
You can use `default` attribute from Virtus.
|
359
|
+
|
360
|
+
```ruby
|
361
|
+
Array.new(2, LocationForm.new)
|
362
|
+
# => [#<LocationForm:0x00000004ffe0e8 @address=nil>, #<LocationForm:0x00000004ffe0e8 @address=nil>]
|
363
|
+
```
|
364
|
+
|
365
|
+
So we can apply this to our form.
|
366
|
+
|
367
|
+
```ruby
|
368
|
+
class UserForm < FormObjects::Base
|
369
|
+
include FormObjects::Naming
|
370
|
+
|
371
|
+
NUMBER_OF_LOCATION_FORMS = 2
|
372
|
+
|
373
|
+
field :first_name, String
|
374
|
+
field :last_name, String
|
375
|
+
field :terms, Boolean
|
376
|
+
|
377
|
+
nested_form :addresses, Array[LocationForm], default: proc { Array.new(NUMBER_OF_LOCATION_FORMS, LocationForm.new) }
|
378
|
+
|
379
|
+
validates :first_name, presence: true
|
380
|
+
validates :terms, acceptance: { accept: true }
|
381
|
+
end
|
382
|
+
```
|
383
|
+
|
384
|
+
After this your form will be renderer. But almost for sure you will get exception:
|
385
|
+
|
386
|
+
```
|
387
|
+
undefined method `0=' for #<LocationForm:0x007fdbc002bb80>
|
388
|
+
```
|
389
|
+
|
390
|
+
Now our params looks like this:
|
391
|
+
|
392
|
+
```ruby
|
393
|
+
{
|
394
|
+
:user =>{
|
395
|
+
:first_name => "FirstName",
|
396
|
+
:last_name" => "LastName",
|
397
|
+
:terms => "1",
|
398
|
+
:addresses_attributes => {
|
399
|
+
"0" => {:address=>"Street1"},
|
400
|
+
"1" => {"address=>"Street2"}
|
401
|
+
}
|
402
|
+
}
|
403
|
+
}
|
404
|
+
```
|
405
|
+
|
406
|
+
From now we need to use `FormObjects::ParamsConverter`. Because Virtus models will not accept rails magic.
|
407
|
+
|
408
|
+
```ruby
|
409
|
+
FormObjects::ParamsConverter.new(params).params
|
410
|
+
|
411
|
+
{
|
412
|
+
:user => {
|
413
|
+
:first_name => "FirstName",
|
414
|
+
:last_name => "LastName",
|
415
|
+
:terms => "1",
|
416
|
+
:addresses_attributes=> [
|
417
|
+
{:address => "Street1"},
|
418
|
+
{:address => "Street2"}
|
419
|
+
]
|
420
|
+
}
|
421
|
+
}
|
422
|
+
```
|
423
|
+
|
424
|
+
`FormObjects::ParamsConverter` convert `Hash` created by rails to friendly Array. You can use this Hash to initialize your form.
|
425
|
+
|
426
|
+
```ruby
|
427
|
+
UserForm.new(converted_params[:user])
|
428
|
+
|
429
|
+
private
|
430
|
+
|
431
|
+
def converted_params
|
432
|
+
FormObjects::ParamsConverter.new(params).params
|
433
|
+
end
|
434
|
+
```
|
435
|
+
|
436
|
+
## Summary
|
437
|
+
|
438
|
+
* FormObjects use Virtus for Property API
|
439
|
+
* Nested forms objects are validate together with parent form, errors are being push to parent.
|
440
|
+
* ``` #serialized_attributes ``` method returns attributes hash
|
441
|
+
|
442
|
+
```ruby
|
443
|
+
class AddressForm < FormObjects::Base
|
444
|
+
field :street, String
|
445
|
+
field :city, String
|
446
|
+
|
447
|
+
validates :street, presence: true
|
448
|
+
end
|
449
|
+
|
450
|
+
class PersonalInfoForm < FormObjects::Base
|
451
|
+
field :first_name, String
|
452
|
+
field :last_name, String
|
453
|
+
|
454
|
+
validates :first_name, presence: true
|
455
|
+
end
|
456
|
+
|
457
|
+
class UserForm < FormObjects::Base
|
458
|
+
field :email, String
|
459
|
+
|
460
|
+
nested_form :addresses, Array[AddressForm]
|
461
|
+
nested_form :personal_info, PersonalInfoForm
|
462
|
+
end
|
463
|
+
|
464
|
+
service = UserUpdater.new
|
465
|
+
form = UserForm.new
|
466
|
+
|
467
|
+
form.update({
|
468
|
+
email: 'john.doe@example.com',
|
469
|
+
personal_info_attributes: {first_name: 'John'},
|
470
|
+
addresses_attributes: [{street: 'Golden Street'}]
|
471
|
+
})
|
472
|
+
|
473
|
+
if form.valid?
|
474
|
+
service.update(form.serialized_attributes)
|
475
|
+
end
|
476
|
+
```
|
477
|
+
|
478
|
+
# Params conversion
|
479
|
+
|
480
|
+
## Array parameters
|
481
|
+
|
482
|
+
When you use HTTP there is no ensure that parameters that you receive will be ordered. That why rails wrap Arrays inside Hash.
|
483
|
+
|
484
|
+
```ruby
|
485
|
+
["one", "two", "three"] => {"0" => "one", "1" => "two", "2" => "three"}
|
486
|
+
```
|
487
|
+
|
488
|
+
But form object expects that nested params will be kind of Array
|
489
|
+
|
490
|
+
```ruby
|
491
|
+
class UserForm < FormObjects::Base
|
492
|
+
nested_form :addresses, Array[AddressForm]
|
493
|
+
end
|
494
|
+
|
495
|
+
UserForm.new(:addresses_attributes => [{:name => "Name"}]) # good
|
496
|
+
# instead of
|
497
|
+
UserForm.new(:addresses_attributes => {"0" => {:name => "Name"}}) # bad
|
498
|
+
```
|
499
|
+
|
500
|
+
To avoid these problems you can use `FormObjects::ParamsConverter`.
|
501
|
+
|
502
|
+
```ruby
|
503
|
+
params = { "event_attributes" => {"0" => "one", "1" => "two", "2" => "three"} }
|
504
|
+
converter = FormObjects::ParamsConverter.new(params)
|
505
|
+
converter.params #=> { "event_attributes" => ["one", "two", "three"] }
|
506
|
+
```
|
507
|
+
|
508
|
+
## Date parameters
|
509
|
+
|
510
|
+
Multi-parameter dates can be easily converted to friendly form.
|
511
|
+
|
512
|
+
```ruby
|
513
|
+
params = { "event" => { "date(1i)" => "2014", "date(2i)" => "12", "date(3i)" => "16", "date(4i)" => "12", "date(5i)" => "30", "date(6i)" => "45" } }
|
514
|
+
converter = FormObjects::ParamsConverter.new(params)
|
515
|
+
converter.params #=> { "event" => { "date" => "2014.12.16 12:30:45" } }
|
516
|
+
```
|
517
|
+
|
518
|
+
## Contributing
|
519
|
+
|
520
|
+
1. Fork it
|
521
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
522
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
523
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
524
|
+
5. Create new Pull Request
|