on_form 2.2.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +4 -0
- data/README.md +71 -1
- data/lib/on_form/form.rb +15 -2
- data/lib/on_form/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05e792fbba20f1c4d82034000b2e49f2f5e01586
|
4
|
+
data.tar.gz: d8841bae2c6429b08945385a899d89b64e19f3a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6557351f0b77e782903e27985c77afd88a6a9872fd506acfb26dd80464fc090337962aa5eead731175a9983fbe9c991590dfd16ae3151eff769927dccafb349
|
7
|
+
data.tar.gz: 65bd1b58e606758dce47bf865a7debe2bb602286cf79c7d025fd28472223553f54b0a2322a9a319f806ce027f55775827dcab27b3cf0209992e4663bd0b664de
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -71,7 +71,7 @@ class PreferencesController
|
|
71
71
|
end
|
72
72
|
```
|
73
73
|
|
74
|
-
Now we need to make our form object. At this point we need to tell the form object which attributes on the model we want to expose
|
74
|
+
Now we need to make our form object. At this point we need to tell the form object which attributes on the model we want to `expose`. (In this example we have just one model and a couple of attributes, but you wouldn't bother using this library if this was all you had.)
|
75
75
|
|
76
76
|
```ruby
|
77
77
|
class PreferencesForm < OnForm::Form
|
@@ -130,6 +130,76 @@ end
|
|
130
130
|
|
131
131
|
You can also define your own method over the top of the `attr_reader`. Just remember it will be called more than once, so it must be idempotent.
|
132
132
|
|
133
|
+
### View helpers & acting like ActiveModel/ActiveRecord
|
134
|
+
|
135
|
+
Since OnForm doesn't require a single "main" model, forms don't automatically have any particular identity value (ie. an `id` attribute or a value to return from `to_param`).
|
136
|
+
|
137
|
+
So although by default forms will work fine with all the 'raw' form field helpers and with helpers like `fields_for`, they're not automatically usable with the resource form methods like `form_for`, which assumes you have a one-to-one correspondance between your models and your views (in other words, that you have no form object layer).
|
138
|
+
|
139
|
+
You have several options. First, you can start your form tags completely manually, optionally choosing the name for the params:
|
140
|
+
|
141
|
+
```erb
|
142
|
+
<%= form_tag customer_path(edit_details_form.customer), method: :put do %>
|
143
|
+
<%# if the controller has set an ivar called @edit_details_form %>
|
144
|
+
<%= fields_for :edit_details_form do |f| %>
|
145
|
+
<%# produces a field called edit_details_form[name] %>
|
146
|
+
<%= f.text_field :name %>
|
147
|
+
<% end %>
|
148
|
+
|
149
|
+
<%# or you can give it a different name, to control what the form params will be named %>
|
150
|
+
<%= fields_for :customer, @edit_details_form do |f| %>
|
151
|
+
<%# produces a field called customer[name], which is what a normal resource controller expects %>
|
152
|
+
<%= f.text_field :name %>
|
153
|
+
<% end %>
|
154
|
+
<% end %>
|
155
|
+
```
|
156
|
+
|
157
|
+
Secondly, you can combine these calls into a `form_for` call using some of its optional arguments:
|
158
|
+
|
159
|
+
```erb
|
160
|
+
<%= form_for @edit_details_form, as: :customer, url: customer_path(edit_details_form.customer), method: :put do |f| %>
|
161
|
+
<%# produces a field called customer[name] %>
|
162
|
+
<%= f.text_field :name %>
|
163
|
+
<% end %>
|
164
|
+
```
|
165
|
+
|
166
|
+
Thirdly, you can delegate the identity question to one of the models that backs the form using `takes_identity_from`. When you do this, the form objects start to return that model from `to_model` and the `to_key` and `to_param` values of that model as their own. This is the recommended approach when dealing with standard resource ('RESTful') controllers.
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
class EditPostForm < OnForm::Form
|
170
|
+
take_identity_from :post
|
171
|
+
|
172
|
+
expose %i(title body), on: :post
|
173
|
+
|
174
|
+
def initialize(post)
|
175
|
+
@post = post
|
176
|
+
end
|
177
|
+
end
|
178
|
+
```
|
179
|
+
|
180
|
+
```erb
|
181
|
+
<%= form_for @edit_details_form do |f| %>
|
182
|
+
<%# produces a field called customer[name] %>
|
183
|
+
<%= f.text_field :name %>
|
184
|
+
<% end %>
|
185
|
+
```
|
186
|
+
|
187
|
+
Note that we no longer have to specify the `as` ,`url`, or `method` options, because these will be automatically derived from the `customer` model instead of from the form object itself.
|
188
|
+
|
189
|
+
When you choose an identity model, it will also become the default model for `expose` calls, which helps DRY up single-model form objects.
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
class EditPostForm < OnForm::Form
|
193
|
+
take_identity_from :post
|
194
|
+
|
195
|
+
expose %i(title body)
|
196
|
+
|
197
|
+
def initialize(post)
|
198
|
+
@post = post
|
199
|
+
end
|
200
|
+
end
|
201
|
+
```
|
202
|
+
|
133
203
|
### Renaming attributes
|
134
204
|
|
135
205
|
By default the attribute names exposed on the form object are the same as the attributes on the backing models. Sometimes this leads to unclear meanings, and sometimes you'll have duplicate attribute names in a multi-model form.
|
data/lib/on_form/form.rb
CHANGED
@@ -16,6 +16,10 @@ module OnForm
|
|
16
16
|
@introduced_attribute_types ||= {}
|
17
17
|
end
|
18
18
|
|
19
|
+
def self.identity_model_name
|
20
|
+
@identity_model_name
|
21
|
+
end
|
22
|
+
|
19
23
|
class << self
|
20
24
|
def inherited(child)
|
21
25
|
exposed_attributes.each { |k, v| child.exposed_attributes[k].merge!(v) }
|
@@ -23,11 +27,14 @@ module OnForm
|
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
26
|
-
def self.expose(backing_attribute_names, on
|
30
|
+
def self.expose(backing_attribute_names, on: nil, prefix: nil, suffix: nil, as: nil)
|
27
31
|
backing_attribute_names = Array(backing_attribute_names)
|
28
32
|
raise ArgumentError, "can't expose multiple attributes as the same form attribute!" if as && backing_attribute_names.size != 1
|
29
|
-
|
33
|
+
|
34
|
+
raise ArgumentError, "must choose the model to expose the attributes on" unless on || identity_model_name
|
35
|
+
on = (on || identity_model_name).to_sym
|
30
36
|
expose_backing_model(on)
|
37
|
+
|
31
38
|
backing_attribute_names.each do |backing_name|
|
32
39
|
exposed_name = as || "#{prefix}#{backing_name}#{suffix}"
|
33
40
|
expose_attribute(on, exposed_name, backing_name)
|
@@ -61,6 +68,12 @@ module OnForm
|
|
61
68
|
define_method("#{name}=") { |arg| introduced_attribute_values.delete(name); introduced_attribute_values_before_type_cast[name] = arg }
|
62
69
|
end
|
63
70
|
|
71
|
+
def self.take_identity_from(backing_model_name)
|
72
|
+
@identity_model_name = backing_model_name.to_sym
|
73
|
+
expose_backing_model(@identity_model_name)
|
74
|
+
delegate :to_model, :to_key, :to_param, :persisted?, to: backing_model_name
|
75
|
+
end
|
76
|
+
|
64
77
|
protected
|
65
78
|
def introduced_attribute_values
|
66
79
|
@introduced_attribute_values ||= {}
|
data/lib/on_form/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: on_form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Bryant
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|