reform 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +12 -6
- data/README.md +20 -2
- data/database.sqlite3 +0 -0
- data/lib/reform/form/active_model.rb +12 -5
- data/lib/reform/form/active_record.rb +1 -1
- data/lib/reform/form/multi_parameter_attributes.rb +36 -0
- data/lib/reform/form.rb +5 -3
- data/lib/reform/version.rb +1 -1
- data/test/active_model_test.rb +22 -2
- data/test/active_record_test.rb +8 -1
- data/test/dummy/config/application.rb +1 -1
- data/test/nested_form_test.rb +41 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7858098ed982e9c00c56016f1678e26f4c43b9e6
|
4
|
+
data.tar.gz: e518cbde390737b8308ce6aa41d398b6b48b2533
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d4cb6de758aeb2892ee47bb69c8f9bb061f184b8088b9eac294ed3add2e72d364b5425206b9720c671892b1926be13bff7d9a3d7a3ac818381468c9115db695
|
7
|
+
data.tar.gz: 868a33c66a5a2225da3a12596f7c1f703e10403a1ef7353393d237ae368b6be55148d9eb8a2fe3bdda8e1744100d3e6d668b224226001997e19d029269747d2f
|
data/CHANGES.md
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
|
1
|
+
## 0.2.2
|
2
|
+
|
3
|
+
* Fix a bug where `form.save do .. end` would call `model.save` even though a block was given. This no longer happens, if there's a block to `#save`, you have to manually save data (ActiveRecord environment, only).
|
4
|
+
* `#validate` doesn't blow up anymore when input data is missing for a nested property or collection.
|
5
|
+
* Allow `form: SongForm` to specify an explicit form class instead of using an inline form for nested properties.
|
6
|
+
|
7
|
+
## 0.2.1
|
2
8
|
|
3
9
|
* `ActiveRecord::i18n_scope` now returns `activerecord`.
|
4
10
|
* `Form#save` now calls save on the model in `ActiveRecord` context.
|
@@ -9,7 +15,7 @@ h3. 0.2.1
|
|
9
15
|
* Move `setup` and `save` logic into respective representer classes. This might break your code in case you overwrite private reform classes.
|
10
16
|
|
11
17
|
|
12
|
-
|
18
|
+
## 0.2.0
|
13
19
|
|
14
20
|
* Added nested property and collection for `has_one` and `has_many` relationships. . Note that this currently works only 1-level deep.
|
15
21
|
* Renamed `Reform::Form::DSL` to `Reform::Form::Composition` and deprecated `DSL`.
|
@@ -18,21 +24,21 @@ h3. 0.2.0
|
|
18
24
|
* `Form.new` now accepts one argument, only: the model/composition. If you want to create your own representer, inject it by overriding `Form#mapper`. Note that this won't create property accessors for you.
|
19
25
|
* `Form::ActiveModel` no longer creates accessors to your represented models, e.g. having `property :title, on: :song` doesn't allow `form.song` anymore. This is because the actual model and the form's state might differ, so please use `form.title` directly.
|
20
26
|
|
21
|
-
|
27
|
+
## 0.1.3
|
22
28
|
|
23
29
|
* Altered `reform/rails` to conditionally load `ActiveRecord` code and created `reform/active_record`.
|
24
30
|
|
25
|
-
|
31
|
+
## 0.1.2
|
26
32
|
|
27
33
|
* `Form#to_model` is now delegated to model.
|
28
34
|
* Coercion with virtus works.
|
29
35
|
|
30
|
-
|
36
|
+
## 0.1.1
|
31
37
|
|
32
38
|
* Added `reform/rails` that requires everything you need (even in other frameworks :).
|
33
39
|
* Added `Form::ActiveRecord` that gives you `validates_uniqueness_with`. Note that this is strongly coupled to your database, thou.
|
34
40
|
* Merged a lot of cleanups from sweet @parndt <3.
|
35
41
|
|
36
|
-
|
42
|
+
## 0.1.0
|
37
43
|
|
38
44
|
* Oh yeah.
|
data/README.md
CHANGED
@@ -402,8 +402,12 @@ Nesting forms only requires readers for the nested properties as `Album#songs`.
|
|
402
402
|
|
403
403
|
Check out [@gogogarret](https://twitter.com/GoGoGarrett/)'s [sample Rails app](https://github.com/gogogarrett/reform_example) using Reform.
|
404
404
|
|
405
|
-
Rails and Reform work out-of-the-box.
|
405
|
+
Rails and Reform work together out-of-the-box.
|
406
406
|
|
407
|
+
However, you should know about two things.
|
408
|
+
|
409
|
+
1. In case you explicitely _don't_ want to have automatic support for `ActiveRecord` and form builder: `require reform/form`, only.
|
410
|
+
2. In some setups around Rails 4 the `Form::ActiveRecord` module is not loaded properly, usually triggering a `NoMethodError` saying `undefined method 'model'`. If that happened to you, `require 'reform/rails'` manually at the bottom of your `config/application.rb`.
|
407
411
|
|
408
412
|
## ActiveRecord Compatibility
|
409
413
|
|
@@ -451,13 +455,27 @@ class SongForm < Reform::Form
|
|
451
455
|
end
|
452
456
|
```
|
453
457
|
|
454
|
-
|
455
458
|
## Security
|
456
459
|
|
457
460
|
By explicitely defining the form layout using `::property` there is no more need for protecting from unwanted input. `strong_parameter` or `
|
458
461
|
attr_accessible` become obsolete. Reform will simply ignore undefined incoming parameters.
|
459
462
|
|
460
463
|
|
464
|
+
## Additional Features
|
465
|
+
|
466
|
+
### Nesting Without Inline Representers
|
467
|
+
|
468
|
+
When nesting form, you usually use a so-called inline form doing `property :song do .. end`.
|
469
|
+
|
470
|
+
Sometimes you wanna specify an explicit form rather than using an inline form. Use the `form:` option here.
|
471
|
+
|
472
|
+
```ruby
|
473
|
+
property :song, form: SongForm`
|
474
|
+
```
|
475
|
+
|
476
|
+
The nested `SongForm` is a stand-alone form class you have to provide.
|
477
|
+
|
478
|
+
|
461
479
|
## Support
|
462
480
|
|
463
481
|
If you run into any trouble chat with us on irc.freenode.org#trailblazer.
|
data/database.sqlite3
CHANGED
Binary file
|
@@ -24,15 +24,22 @@ module Reform::Form::ActiveModel
|
|
24
24
|
# DISCUSS: #validate should actually expect the complete params hash and then pick the right key as it knows the form name.
|
25
25
|
# however, this would cause confusion?
|
26
26
|
mapper.new(self).nested_forms do |attr, model| # FIXME: make this simpler.
|
27
|
-
|
28
|
-
params[attr.name] = params["#{attr.name}_attributes"].values
|
29
|
-
else
|
30
|
-
params[attr.name] = params["#{attr.name}_attributes"]# DISCUSS: delete old key? override existing?
|
31
|
-
end
|
27
|
+
rename_nested_param_for!(params, attr)
|
32
28
|
end
|
33
29
|
|
34
30
|
super
|
35
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def rename_nested_param_for!(params, attr)
|
35
|
+
nested_name = "#{attr.name}_attributes"
|
36
|
+
return unless params.has_key?(nested_name)
|
37
|
+
|
38
|
+
value = params["#{attr.name}_attributes"]
|
39
|
+
value = value.values if attr.options[:form_collection]
|
40
|
+
|
41
|
+
params[attr.name] = value
|
42
|
+
end
|
36
43
|
end
|
37
44
|
|
38
45
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Reform::Form
|
2
|
+
module MultiParameterAttributes
|
3
|
+
class DateParamsFilter
|
4
|
+
def call(params)
|
5
|
+
date_attributes = {}
|
6
|
+
|
7
|
+
params.each do |attribute, value|
|
8
|
+
if value.is_a?(Hash)
|
9
|
+
call(value) # TODO: #validate should only handle local form params.
|
10
|
+
elsif matches = attribute.match(/^(\w+)\(.i\)$/)
|
11
|
+
date_attribute = matches[1]
|
12
|
+
date_attributes[date_attribute] = params_to_date(
|
13
|
+
params.delete("#{date_attribute}(1i)"),
|
14
|
+
params.delete("#{date_attribute}(2i)"),
|
15
|
+
params.delete("#{date_attribute}(3i)")
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
params.merge!(date_attributes)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def params_to_date(year, month, day)
|
24
|
+
day ||= 1 # FIXME: is that really what we want? test.
|
25
|
+
Date.new(year.to_i, month.to_i, day.to_i) # TODO: test fails.
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate(params)
|
30
|
+
# TODO: make it cleaner to hook into essential reform steps.
|
31
|
+
DateParamsFilter.new.call(params)
|
32
|
+
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/reform/form.rb
CHANGED
@@ -20,7 +20,8 @@ module Reform
|
|
20
20
|
process_options(name, options, &block)
|
21
21
|
|
22
22
|
definition = representer_class.property(name, options, &block)
|
23
|
-
setup_form_definition(definition) if block_given?
|
23
|
+
setup_form_definition(definition) if block_given? or options[:form]
|
24
|
+
|
24
25
|
create_accessor(name)
|
25
26
|
end
|
26
27
|
|
@@ -35,7 +36,7 @@ module Reform
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def setup_form_definition(definition)
|
38
|
-
definition.options[:form]
|
39
|
+
definition.options[:form] ||= definition.options.delete(:extend)
|
39
40
|
|
40
41
|
definition.options[:parse_strategy] = :sync
|
41
42
|
definition.options[:instance] = true # just to make typed? work
|
@@ -82,9 +83,10 @@ module Reform
|
|
82
83
|
errors.merge!(form.errors, prefix)
|
83
84
|
false
|
84
85
|
end
|
85
|
-
|
86
86
|
end
|
87
87
|
include ValidateMethods
|
88
|
+
require 'reform/form/multi_parameter_attributes'
|
89
|
+
include MultiParameterAttributes # TODO: make features dynamic.
|
88
90
|
|
89
91
|
def save
|
90
92
|
# DISCUSS: we should never hit @mapper here (which writes to the models) when a block is passed.
|
data/lib/reform/version.rb
CHANGED
data/test/active_model_test.rb
CHANGED
@@ -45,12 +45,15 @@ class FormBuilderCompatTest < MiniTest::Spec
|
|
45
45
|
|
46
46
|
collection :songs do
|
47
47
|
property :title
|
48
|
+
property :release_date
|
48
49
|
validates :title, :presence => true
|
49
50
|
end
|
50
51
|
end
|
51
52
|
}
|
52
|
-
|
53
|
-
|
53
|
+
|
54
|
+
let (:song) { OpenStruct.new }
|
55
|
+
let (:form) { form_class.new(OpenStruct.new(
|
56
|
+
:artist => Artist.new(:name => "Propagandhi"), :songs => [song])) }
|
54
57
|
|
55
58
|
it "respects _attributes params hash" do
|
56
59
|
form.validate("artist_attributes" => {"name" => "Blink 182"},
|
@@ -60,11 +63,28 @@ class FormBuilderCompatTest < MiniTest::Spec
|
|
60
63
|
form.songs.first.title.must_equal "Damnit"
|
61
64
|
end
|
62
65
|
|
66
|
+
it "allows nested collection and property to be missing" do
|
67
|
+
form.validate({})
|
68
|
+
|
69
|
+
form.artist.name.must_equal "Propagandhi"
|
70
|
+
|
71
|
+
form.songs.size.must_equal 1
|
72
|
+
form.songs[0].model.must_equal song # this is a weird test.
|
73
|
+
end
|
74
|
+
|
63
75
|
it "defines _attributes= setter so Rails' FB works properly" do
|
64
76
|
form.must_respond_to("artist_attributes=")
|
65
77
|
form.must_respond_to("songs_attributes=")
|
66
78
|
end
|
67
79
|
|
80
|
+
it "accepts deconstructed date parameters" do
|
81
|
+
form.validate("artist_attributes" => {"name" => "Blink 182"},
|
82
|
+
"songs_attributes" => {"0" => {"title" => "Damnit", "release_date(1i)" => "1997",
|
83
|
+
"release_date(2i)" => "9", "release_date(3i)" => "27"}})
|
84
|
+
|
85
|
+
form.songs.first.release_date.must_equal Date.new(1997, 9, 27)
|
86
|
+
end
|
87
|
+
|
68
88
|
it "returns flat errors hash" do
|
69
89
|
form.validate("artist_attributes" => {"name" => ""},
|
70
90
|
"songs_attributes" => {"0" => {"title" => ""}})
|
data/test/active_record_test.rb
CHANGED
@@ -57,11 +57,18 @@ class ActiveRecordTest < MiniTest::Spec
|
|
57
57
|
|
58
58
|
describe "#save" do
|
59
59
|
# TODO: test 1-n?
|
60
|
-
it "calls
|
60
|
+
it "calls model.save" do
|
61
61
|
Artist.delete_all
|
62
62
|
form.validate("name" => "Bad Religion")
|
63
63
|
form.save
|
64
64
|
Artist.where(:name => "Bad Religion").size.must_equal 1
|
65
65
|
end
|
66
|
+
|
67
|
+
it "doesn't call model.save when block is given" do
|
68
|
+
Artist.delete_all
|
69
|
+
form.validate("name" => "Bad Religion")
|
70
|
+
form.save {}
|
71
|
+
Artist.where(:name => "Bad Religion").size.must_equal 0
|
72
|
+
end
|
66
73
|
end
|
67
74
|
end
|
data/test/nested_form_test.rb
CHANGED
@@ -57,7 +57,7 @@ class NestedFormTest < MiniTest::Spec
|
|
57
57
|
"hit" =>{"title" => "Sacrifice"},
|
58
58
|
"title" =>"Second Heat",
|
59
59
|
"songs" => [{"title" => "Scarified"}])
|
60
|
-
}
|
60
|
+
}
|
61
61
|
|
62
62
|
it "updates internal Fields" do
|
63
63
|
data = {}
|
@@ -104,6 +104,15 @@ class NestedFormTest < MiniTest::Spec
|
|
104
104
|
song.title.must_equal "Sacrifice"
|
105
105
|
songs.first.title.must_equal "Scarified"
|
106
106
|
end
|
107
|
+
|
108
|
+
describe "with invalid args" do
|
109
|
+
it "allows empty collection values" do
|
110
|
+
form.validate({})
|
111
|
+
|
112
|
+
form.songs.size.must_equal 1
|
113
|
+
form.songs[0].title.must_equal "Scarified"
|
114
|
+
end
|
115
|
+
end
|
107
116
|
end
|
108
117
|
|
109
118
|
# describe "with aliased nested form name" do
|
@@ -119,6 +128,37 @@ class NestedFormTest < MiniTest::Spec
|
|
119
128
|
# end
|
120
129
|
# end
|
121
130
|
|
131
|
+
class ExplicitNestedFormTest < MiniTest::Spec
|
132
|
+
let (:song) { OpenStruct.new(:title => "Downtown") }
|
133
|
+
let (:album) do
|
134
|
+
OpenStruct.new(
|
135
|
+
:title => "Blackhawks Over Los Angeles",
|
136
|
+
:hit => song,
|
137
|
+
)
|
138
|
+
end
|
139
|
+
let (:form) { AlbumForm.new(album) }
|
140
|
+
|
141
|
+
class SongForm < Reform::Form
|
142
|
+
property :title
|
143
|
+
validates_presence_of :title
|
144
|
+
end
|
145
|
+
|
146
|
+
class AlbumForm < Reform::Form
|
147
|
+
property :title
|
148
|
+
|
149
|
+
property :hit, :form => SongForm #, :parse_strategy => :sync, :instance => true
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
it "allows rendering" do
|
154
|
+
form.hit.title.must_equal "Downtown"
|
155
|
+
end
|
156
|
+
|
157
|
+
it { form.validate({"hit" => {"title" => ""}})
|
158
|
+
form.errors[:"hit.title"].must_equal(["can't be blank"])
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
122
162
|
class UnitTest < self
|
123
163
|
it "keeps Forms for form collection" do
|
124
164
|
form.send(:fields).songs.must_be_kind_of Reform::Form::Forms
|
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: 0.2.
|
4
|
+
version: 0.2.2
|
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: 2013-
|
12
|
+
date: 2013-12-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: representable
|
@@ -166,6 +166,7 @@ files:
|
|
166
166
|
- lib/reform/form/active_record.rb
|
167
167
|
- lib/reform/form/coercion.rb
|
168
168
|
- lib/reform/form/composition.rb
|
169
|
+
- lib/reform/form/multi_parameter_attributes.rb
|
169
170
|
- lib/reform/form/virtual_attributes.rb
|
170
171
|
- lib/reform/rails.rb
|
171
172
|
- lib/reform/representer.rb
|