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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc9552629f219a60bdb440b73aeaff5bab8ee8a7
4
- data.tar.gz: 30fe72e471a35b622fd9203899b175a554f85785
3
+ metadata.gz: 05e792fbba20f1c4d82034000b2e49f2f5e01586
4
+ data.tar.gz: d8841bae2c6429b08945385a899d89b64e19f3a1
5
5
  SHA512:
6
- metadata.gz: 31cae4ebd42811962196cc71da3e0b44d549a30d906b4be52cf88f6dfc6342d24bcbeab9971b91025a799732786a427dfbbc4566be1e84643cc1771be6f1718e
7
- data.tar.gz: 1336b1e8f6d98778ab2d836dbbfba0986f3a76e7641676386443a4b1d71f667c015537d602d97964af57857b943976961a2364b0f794ed3cdbdf73c948401941
6
+ metadata.gz: c6557351f0b77e782903e27985c77afd88a6a9872fd506acfb26dd80464fc090337962aa5eead731175a9983fbe9c991590dfd16ae3151eff769927dccafb349
7
+ data.tar.gz: 65bd1b58e606758dce47bf865a7debe2bb602286cf79c7d025fd28472223553f54b0a2322a9a319f806ce027f55775827dcab27b3cf0209992e4663bd0b664de
data/CHANGES.md CHANGED
@@ -1,6 +1,10 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 2.3.0
5
+ -----
6
+ * Add `take_identity_from` to improve interoperability with standard resource ('RESTful') controllers and form helpers
7
+
4
8
  2.2.2
5
9
  -----
6
10
  * Support non-array argument to `expose`.
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. (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.)
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:, prefix: nil, suffix: nil, as: nil)
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
- on = on.to_sym
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 ||= {}
@@ -1,3 +1,3 @@
1
1
  module OnForm
2
- VERSION = "2.2.2"
2
+ VERSION = "2.3.0"
3
3
  end
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.2.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-03 00:00:00.000000000 Z
11
+ date: 2016-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel