actionpack 3.0.0.beta2 → 3.0.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +37 -0
- data/lib/abstract_controller/rendering.rb +9 -11
- data/lib/action_controller.rb +0 -1
- data/lib/action_controller/base.rb +45 -44
- data/lib/action_controller/caching/pages.rb +2 -2
- data/lib/action_controller/deprecated/base.rb +21 -5
- data/lib/action_controller/metal/compatibility.rb +0 -2
- data/lib/action_controller/metal/cookies.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +1 -1
- data/lib/action_controller/metal/http_authentication.rb +12 -5
- data/lib/action_controller/metal/responder.rb +3 -2
- data/lib/action_controller/polymorphic_routes.rb +1 -1
- data/lib/action_controller/railtie.rb +6 -1
- data/lib/action_controller/record_identifier.rb +2 -2
- data/lib/action_controller/test_case.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +2 -2
- data/lib/action_dispatch/http/request.rb +39 -21
- data/lib/action_dispatch/middleware/cookies.rb +18 -22
- data/lib/action_dispatch/middleware/params_parser.rb +8 -9
- data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +1 -1
- data/lib/action_dispatch/railtie.rb +1 -0
- data/lib/action_dispatch/routing.rb +24 -12
- data/lib/action_dispatch/routing/deprecated_mapper.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +77 -51
- data/lib/action_dispatch/routing/route_set.rb +9 -5
- data/lib/action_dispatch/routing/url_for.rb +2 -3
- data/lib/action_dispatch/testing/integration.rb +24 -11
- data/lib/action_dispatch/testing/test_request.rb +2 -0
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view/base.rb +8 -2
- data/lib/action_view/helpers.rb +3 -6
- data/lib/action_view/helpers/active_model_helper.rb +20 -265
- data/lib/action_view/helpers/asset_tag_helper.rb +46 -9
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/form_helper.rb +161 -120
- data/lib/action_view/helpers/form_options_helper.rb +0 -2
- data/lib/action_view/helpers/form_tag_helper.rb +76 -13
- data/lib/action_view/helpers/url_helper.rb +48 -21
- data/lib/action_view/locale/en.yml +0 -8
- data/lib/action_view/lookup_context.rb +11 -4
- data/lib/action_view/render/layouts.rb +32 -18
- data/lib/action_view/render/partials.rb +2 -2
- data/lib/action_view/template.rb +10 -1
- data/lib/action_view/test_case.rb +6 -1
- metadata +7 -8
- data/lib/action_controller/metal/verification.rb +0 -130
@@ -501,16 +501,53 @@ module ActionView
|
|
501
501
|
end
|
502
502
|
end
|
503
503
|
|
504
|
+
# Web browsers cache favicons. If you just throw a <tt>favicon.ico</tt> into the document
|
505
|
+
# root of your application and it changes later, clients that have it in their cache
|
506
|
+
# won't see the update. Using this helper prevents that because it appends an asset ID:
|
507
|
+
#
|
508
|
+
# <%= favicon_link_tag %>
|
509
|
+
#
|
510
|
+
# generates
|
511
|
+
#
|
512
|
+
# <link href="/favicon.ico?4649789979" rel="shortcut icon" type="image/vnd.microsoft.icon" />
|
513
|
+
#
|
514
|
+
# You may specify a different file in the first argument:
|
515
|
+
#
|
516
|
+
# <%= favicon_link_tag 'favicon.ico' %>
|
517
|
+
#
|
518
|
+
# That's passed to +path_to_image+ as is, so it gives
|
519
|
+
#
|
520
|
+
# <link href="/images/favicon.ico?4649789979" rel="shortcut icon" type="image/vnd.microsoft.icon" />
|
521
|
+
#
|
522
|
+
# The helper accepts an additional options hash where you can override "rel" and "type".
|
523
|
+
#
|
524
|
+
# For example, Mobile Safari looks for a different LINK tag, pointing to an image that
|
525
|
+
# will be used if you add the page to the home screen of an iPod Touch, iPhone, or iPad.
|
526
|
+
# The following call would generate such a tag:
|
527
|
+
#
|
528
|
+
# <%= favicon_link_tag 'mb-icon.png', :rel => 'apple-touch-icon', :type => 'image/png' %>
|
529
|
+
#
|
530
|
+
def favicon_link_tag(source='/favicon.ico', options={})
|
531
|
+
tag('link', {
|
532
|
+
:rel => 'shortcut icon',
|
533
|
+
:type => 'image/vnd.microsoft.icon',
|
534
|
+
:href => path_to_image(source)
|
535
|
+
}.merge(options.symbolize_keys))
|
536
|
+
end
|
537
|
+
|
504
538
|
# Computes the path to an image asset in the public images directory.
|
505
539
|
# Full paths from the document root will be passed through.
|
506
|
-
# Used internally by +image_tag+ to build the image path
|
540
|
+
# Used internally by +image_tag+ to build the image path:
|
507
541
|
#
|
508
|
-
#
|
509
|
-
# image_path("edit")
|
510
|
-
# image_path("edit.png")
|
511
|
-
# image_path("icons/edit.png")
|
512
|
-
# image_path("/
|
513
|
-
#
|
542
|
+
# image_path("edit") # => "/images/edit"
|
543
|
+
# image_path("edit.png") # => "/images/edit.png"
|
544
|
+
# image_path("icons/edit.png") # => "/images/icons/edit.png"
|
545
|
+
# image_path("/icons/edit.png") # => "/icons/edit.png"
|
546
|
+
# image_path("http://www.railsapplication.com/img/edit.png") # => "http://www.railsapplication.com/img/edit.png"
|
547
|
+
#
|
548
|
+
# If you have images as application resources this method may conflict with their named routes.
|
549
|
+
# The alias +path_to_image+ is provided to avoid that. Rails uses the alias internally, and
|
550
|
+
# plugin authors are encouraged to do so.
|
514
551
|
def image_path(source)
|
515
552
|
compute_public_path(source, 'images')
|
516
553
|
end
|
@@ -590,7 +627,7 @@ module ActionView
|
|
590
627
|
end
|
591
628
|
|
592
629
|
if mouseover = options.delete(:mouseover)
|
593
|
-
options[:onmouseover] = "this.src='#{
|
630
|
+
options[:onmouseover] = "this.src='#{path_to_image(mouseover)}'"
|
594
631
|
options[:onmouseout] = "this.src='#{src}'"
|
595
632
|
end
|
596
633
|
|
@@ -672,7 +709,7 @@ module ActionView
|
|
672
709
|
|
673
710
|
# You can enable or disable the asset tag timestamps cache.
|
674
711
|
# With the cache enabled, the asset tag helper methods will make fewer
|
675
|
-
#
|
712
|
+
# expensive file system calls. However this prevents you from modifying
|
676
713
|
# any asset files while the server is running.
|
677
714
|
#
|
678
715
|
# ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
|
@@ -9,8 +9,8 @@ module ActionView
|
|
9
9
|
#
|
10
10
|
# config/routes.rb:
|
11
11
|
# Basecamp::Application.routes.draw do |map|
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# resources :posts
|
13
|
+
# root :to => "posts#index"
|
14
14
|
# end
|
15
15
|
#
|
16
16
|
# app/controllers/posts_controller.rb:
|
@@ -8,94 +8,96 @@ require 'active_support/core_ext/object/blank'
|
|
8
8
|
|
9
9
|
module ActionView
|
10
10
|
module Helpers
|
11
|
-
# Form helpers are designed to make working with
|
12
|
-
# compared to using
|
13
|
-
# methods for creating forms based on your models. This helper generates
|
14
|
-
# the HTML for forms, providing a method for each sort of input
|
15
|
-
# (e.g., text, password, select, and so on). When the form is submitted
|
16
|
-
# (i.e., when the user hits the submit button or <tt>form.submit</tt> is
|
17
|
-
# called via JavaScript), the form inputs will be bundled into the
|
18
|
-
# <tt>params</tt> object and passed back to the controller.
|
11
|
+
# Form helpers are designed to make working with resources much easier
|
12
|
+
# compared to using vanilla HTML.
|
19
13
|
#
|
20
|
-
#
|
21
|
-
# model
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# documentation.
|
14
|
+
# Forms for models are created with +form_for+. That method yields a form
|
15
|
+
# builder that knows the model the form is about. The form builder is thus
|
16
|
+
# able to generate default values for input fields that correspond to model
|
17
|
+
# attributes, and also convenient names, IDs, endpoints, etc.
|
25
18
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# <tt>Person</tt> and want to create a new instance of it:
|
19
|
+
# Conventions in the generated field names allow controllers to receive form
|
20
|
+
# data nicely structured in +params+ with no effort on your side.
|
29
21
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
# <%= f.text_field :first_name %>
|
34
|
-
# <%= f.text_field :last_name %>
|
35
|
-
# <%= submit_tag 'Create' %>
|
36
|
-
# <% end %>
|
22
|
+
# For example, to create a new person you typically set up a new instance of
|
23
|
+
# +Person+ in the <tt>PeopleController#new</tt> action, <tt>@person</tt>, and
|
24
|
+
# pass it to +form_for+:
|
37
25
|
#
|
38
|
-
#
|
26
|
+
# <%= form_for @person do |f| %>
|
27
|
+
# <%= f.label :first_name %>:
|
28
|
+
# <%= f.text_field :first_name %><br />
|
39
29
|
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
# <input id="person_last_name" name="person[last_name]" size="30" type="text" />
|
43
|
-
# <input name="commit" type="submit" value="Create" />
|
44
|
-
# </form>
|
30
|
+
# <%= f.label :last_name %>:
|
31
|
+
# <%= f.text_field :last_name %><br />
|
45
32
|
#
|
46
|
-
#
|
33
|
+
# <%= f.submit %>
|
34
|
+
# <% end %>
|
47
35
|
#
|
48
|
-
#
|
49
|
-
# <%= render :partial => f %>
|
50
|
-
# <%= submit_tag 'Create' %>
|
51
|
-
# <% end %>
|
36
|
+
# The HTML generated for this would be (modulus formatting):
|
52
37
|
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
38
|
+
# <form action="/people" class="new_person" id="new_person" method="post">
|
39
|
+
# <div style="margin:0;padding:0;display:inline">
|
40
|
+
# <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
|
41
|
+
# </div>
|
42
|
+
# <label for="person_first_name">First name</label>:
|
43
|
+
# <input id="person_first_name" name="person[first_name]" size="30" type="text" /><br />
|
57
44
|
#
|
58
|
-
#
|
45
|
+
# <label for="person_last_name">Last name</label>:
|
46
|
+
# <input id="person_last_name" name="person[last_name]" size="30" type="text" /><br />
|
59
47
|
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
# editing/updating an instance (e.g., <tt>Person.find(1)</tt> rather than
|
63
|
-
# <tt>Person.new</tt> in the controller), the objects attribute values are
|
64
|
-
# filled into the form (e.g., the <tt>person_first_name</tt> field would
|
65
|
-
# have that person's first name in it).
|
48
|
+
# <input id="person_submit" name="commit" type="submit" value="Create Person" />
|
49
|
+
# </form>
|
66
50
|
#
|
67
|
-
#
|
68
|
-
#
|
51
|
+
# As you see, the HTML reflects knowledge about the resource in several spots,
|
52
|
+
# like the path the form should be submitted to, or the names of the input fields.
|
69
53
|
#
|
70
|
-
#
|
54
|
+
# In particular, thanks to the conventions followed in the generated field names, the
|
55
|
+
# controller gets a nested hash <tt>params[:person]</tt> with the person attributes
|
56
|
+
# set in the form. That hash is ready to be passed to <tt>Person.create</tt>:
|
71
57
|
#
|
72
|
-
#
|
58
|
+
# if @person = Person.create(params[:person])
|
59
|
+
# # success
|
60
|
+
# else
|
61
|
+
# # error handling
|
62
|
+
# end
|
73
63
|
#
|
74
|
-
#
|
64
|
+
# Interestingly, the exact same view code in the previous example can be used to edit
|
65
|
+
# a person. If <tt>@person</tt> is an existing record with name "John Smith" and ID 256,
|
66
|
+
# the code above as is would yield instead:
|
75
67
|
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
68
|
+
# <form action="/people/256" class="edit_person" id="edit_person_256" method="post">
|
69
|
+
# <div style="margin:0;padding:0;display:inline">
|
70
|
+
# <input name="_method" type="hidden" value="put" />
|
71
|
+
# <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
|
72
|
+
# </div>
|
73
|
+
# <label for="person_first_name">First name</label>:
|
74
|
+
# <input id="person_first_name" name="person[first_name]" size="30" type="text" value="John" /><br />
|
80
75
|
#
|
81
|
-
#
|
76
|
+
# <label for="person_last_name">Last name</label>:
|
77
|
+
# <input id="person_last_name" name="person[last_name]" size="30" type="text" value="Smith" /><br />
|
82
78
|
#
|
83
|
-
#
|
79
|
+
# <input id="person_submit" name="commit" type="submit" value="Update Person" />
|
80
|
+
# </form>
|
84
81
|
#
|
85
|
-
#
|
82
|
+
# Note that the endpoint, default values, and submit button label are tailored for <tt>@person</tt>.
|
83
|
+
# That works that way because the involved helpers know whether the resource is a new record or not,
|
84
|
+
# and generate HTML accordingly.
|
86
85
|
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
# all the nested fields.
|
86
|
+
# The controller would receive the form data again in <tt>params[:person]</tt>, ready to be
|
87
|
+
# passed to <tt>Person#update_attributes</tt>:
|
90
88
|
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
89
|
+
# if @person.update_attributes(params[:person])
|
90
|
+
# # success
|
91
|
+
# else
|
92
|
+
# # error handling
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# That's how you tipically work with resources.
|
95
96
|
module FormHelper
|
96
97
|
extend ActiveSupport::Concern
|
97
98
|
|
98
99
|
include FormTagHelper
|
100
|
+
include UrlHelper
|
99
101
|
|
100
102
|
# Creates a form and a scope around a specific model object that is used
|
101
103
|
# as a base for questioning about values for the fields.
|
@@ -120,7 +122,7 @@ module ActionView
|
|
120
122
|
# The generic way to call +form_for+ yields a form builder around a
|
121
123
|
# model:
|
122
124
|
#
|
123
|
-
# <%= form_for :person
|
125
|
+
# <%= form_for :person do |f| %>
|
124
126
|
# <%= f.error_messages %>
|
125
127
|
# First name: <%= f.text_field :first_name %><br />
|
126
128
|
# Last name : <%= f.text_field :last_name %><br />
|
@@ -128,9 +130,8 @@ module ActionView
|
|
128
130
|
# Admin? : <%= f.check_box :admin %><br />
|
129
131
|
# <% end %>
|
130
132
|
#
|
131
|
-
# There, the
|
132
|
-
# object the form is about
|
133
|
-
# the object is stored in.
|
133
|
+
# There, the argument is a symbol or string with the name of the
|
134
|
+
# object the form is about.
|
134
135
|
#
|
135
136
|
# The form builder acts as a regular form helper that somehow carries the
|
136
137
|
# model. Thus, the idea is that
|
@@ -141,26 +142,7 @@ module ActionView
|
|
141
142
|
#
|
142
143
|
# <%= text_field :person, :first_name %>
|
143
144
|
#
|
144
|
-
#
|
145
|
-
# record as the second argument:
|
146
|
-
#
|
147
|
-
# <%= form_for :person, person, :url => { :action => "update" } do |f| %>
|
148
|
-
# ...
|
149
|
-
# <% end %>
|
150
|
-
#
|
151
|
-
# In that case you can think
|
152
|
-
#
|
153
|
-
# <%= f.text_field :first_name %>
|
154
|
-
#
|
155
|
-
# gets expanded to
|
156
|
-
#
|
157
|
-
# <%= text_field :person, :first_name, :object => person %>
|
158
|
-
#
|
159
|
-
# You can even display error messages of the wrapped model this way:
|
160
|
-
#
|
161
|
-
# <%= f.error_messages %>
|
162
|
-
#
|
163
|
-
# In any of its variants, the rightmost argument to +form_for+ is an
|
145
|
+
# The rightmost argument to +form_for+ is an
|
164
146
|
# optional hash of options:
|
165
147
|
#
|
166
148
|
# * <tt>:url</tt> - The URL the form is submitted to. It takes the same
|
@@ -176,7 +158,7 @@ module ActionView
|
|
176
158
|
# possible to use both the stand-alone FormHelper methods and methods
|
177
159
|
# from FormTagHelper. For example:
|
178
160
|
#
|
179
|
-
# <%= form_for
|
161
|
+
# <%= form_for @person do |f| %>
|
180
162
|
# First name: <%= f.text_field :first_name %>
|
181
163
|
# Last name : <%= f.text_field :last_name %>
|
182
164
|
# Biography : <%= text_area :person, :biography %>
|
@@ -202,7 +184,7 @@ module ActionView
|
|
202
184
|
#
|
203
185
|
# is equivalent to something like:
|
204
186
|
#
|
205
|
-
# <%= form_for
|
187
|
+
# <%= form_for @post, :as => :post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
|
206
188
|
# ...
|
207
189
|
# <% end %>
|
208
190
|
#
|
@@ -212,9 +194,9 @@ module ActionView
|
|
212
194
|
# ...
|
213
195
|
# <% end %>
|
214
196
|
#
|
215
|
-
#
|
197
|
+
# is equivalent to something like:
|
216
198
|
#
|
217
|
-
# <%= form_for
|
199
|
+
# <%= form_for @post, :as => :post, :url => post_path(@post), :html => { :class => "new_post", :id => "new_post" } do |f| %>
|
218
200
|
# ...
|
219
201
|
# <% end %>
|
220
202
|
#
|
@@ -224,6 +206,13 @@ module ActionView
|
|
224
206
|
# ...
|
225
207
|
# <% end %>
|
226
208
|
#
|
209
|
+
# If you have an object that needs to be represented as a different
|
210
|
+
# parameter, like a Client that acts as a Person:
|
211
|
+
#
|
212
|
+
# <%= form_for(@post, :as => :client do |f| %>
|
213
|
+
# ...
|
214
|
+
# <% end %>
|
215
|
+
#
|
227
216
|
# And for namespaced routes, like +admin_post_url+:
|
228
217
|
#
|
229
218
|
# <%= form_for([:admin, @post]) do |f| %>
|
@@ -244,13 +233,13 @@ module ActionView
|
|
244
233
|
#
|
245
234
|
# Example:
|
246
235
|
#
|
247
|
-
# <%= form_for(
|
236
|
+
# <%= form_for(@post, :remote => true) do |f| %>
|
248
237
|
# ...
|
249
238
|
# <% end %>
|
250
239
|
#
|
251
240
|
# The HTML generated for this would be:
|
252
241
|
#
|
253
|
-
# <form action='http://www.example.com'
|
242
|
+
# <form action='http://www.example.com' method='post' data-remote='true'>
|
254
243
|
# <div style='margin:0;padding:0;display:inline'>
|
255
244
|
# <input name='_method' type='hidden' value='put' />
|
256
245
|
# </div>
|
@@ -264,7 +253,7 @@ module ActionView
|
|
264
253
|
# custom builder. For example, let's say you made a helper to
|
265
254
|
# automatically add labels to form inputs.
|
266
255
|
#
|
267
|
-
# <%= form_for
|
256
|
+
# <%= form_for @person, :url => { :action => "create" }, :builder => LabellingFormBuilder do |f| %>
|
268
257
|
# <%= f.text_field :first_name %>
|
269
258
|
# <%= f.text_field :last_name %>
|
270
259
|
# <%= text_area :person, :biography %>
|
@@ -299,15 +288,16 @@ module ActionView
|
|
299
288
|
|
300
289
|
case record_or_name_or_array
|
301
290
|
when String, Symbol
|
291
|
+
ActiveSupport::Deprecation.warn("Using form_for(:name, @resource) is deprecated. Please use form_for(@resource, :as => :name) instead.", caller) unless args.empty?
|
302
292
|
object_name = record_or_name_or_array
|
303
293
|
when Array
|
304
294
|
object = record_or_name_or_array.last
|
305
|
-
object_name = ActionController::RecordIdentifier.singular_class_name(object)
|
295
|
+
object_name = options[:as] || ActionController::RecordIdentifier.singular_class_name(object)
|
306
296
|
apply_form_for_options!(record_or_name_or_array, options)
|
307
297
|
args.unshift object
|
308
298
|
else
|
309
299
|
object = record_or_name_or_array
|
310
|
-
object_name = ActionController::RecordIdentifier.singular_class_name(object)
|
300
|
+
object_name = options[:as] || ActionController::RecordIdentifier.singular_class_name(object)
|
311
301
|
apply_form_for_options!([object], options)
|
312
302
|
args.unshift object
|
313
303
|
end
|
@@ -325,9 +315,13 @@ module ActionView
|
|
325
315
|
|
326
316
|
html_options =
|
327
317
|
if object.respond_to?(:persisted?) && object.persisted?
|
328
|
-
{ :class =>
|
318
|
+
{ :class => options[:as] ? "#{options[:as]}_edit" : dom_class(object, :edit),
|
319
|
+
:id => options[:as] ? "#{options[:as]}_edit" : dom_id(object, :edit),
|
320
|
+
:method => :put }
|
329
321
|
else
|
330
|
-
{ :class => dom_class(object, :new),
|
322
|
+
{ :class => options[:as] ? "#{options[:as]}_new" : dom_class(object, :new),
|
323
|
+
:id => options[:as] ? "#{options[:as]}_new" : dom_id(object),
|
324
|
+
:method => :post }
|
331
325
|
end
|
332
326
|
|
333
327
|
options[:html] ||= {}
|
@@ -341,7 +335,7 @@ module ActionView
|
|
341
335
|
#
|
342
336
|
# === Generic Examples
|
343
337
|
#
|
344
|
-
# <%= form_for @person
|
338
|
+
# <%= form_for @person do |person_form| %>
|
345
339
|
# First name: <%= person_form.text_field :first_name %>
|
346
340
|
# Last name : <%= person_form.text_field :last_name %>
|
347
341
|
#
|
@@ -403,7 +397,7 @@ module ActionView
|
|
403
397
|
#
|
404
398
|
# This model can now be used with a nested fields_for, like so:
|
405
399
|
#
|
406
|
-
# <%= form_for @person
|
400
|
+
# <%= form_for @person do |person_form| %>
|
407
401
|
# ...
|
408
402
|
# <%= person_form.fields_for :address do |address_fields| %>
|
409
403
|
# Street : <%= address_fields.text_field :street %>
|
@@ -432,7 +426,7 @@ module ActionView
|
|
432
426
|
# with a value that evaluates to +true+, you will destroy the associated
|
433
427
|
# model (eg. 1, '1', true, or 'true'):
|
434
428
|
#
|
435
|
-
# <%= form_for @person
|
429
|
+
# <%= form_for @person do |person_form| %>
|
436
430
|
# ...
|
437
431
|
# <%= person_form.fields_for :address do |address_fields| %>
|
438
432
|
# ...
|
@@ -460,7 +454,7 @@ module ActionView
|
|
460
454
|
# the nested fields_for call will be repeated for each instance in the
|
461
455
|
# collection:
|
462
456
|
#
|
463
|
-
# <%= form_for @person
|
457
|
+
# <%= form_for @person do |person_form| %>
|
464
458
|
# ...
|
465
459
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
466
460
|
# <% if project_fields.object.active? %>
|
@@ -471,7 +465,7 @@ module ActionView
|
|
471
465
|
#
|
472
466
|
# It's also possible to specify the instance to be used:
|
473
467
|
#
|
474
|
-
# <%= form_for @person
|
468
|
+
# <%= form_for @person do |person_form| %>
|
475
469
|
# ...
|
476
470
|
# <% @person.projects.each do |project| %>
|
477
471
|
# <% if project.active? %>
|
@@ -484,7 +478,7 @@ module ActionView
|
|
484
478
|
#
|
485
479
|
# Or a collection to be used:
|
486
480
|
#
|
487
|
-
# <%= form_for @person
|
481
|
+
# <%= form_for @person do |person_form| %>
|
488
482
|
# ...
|
489
483
|
# <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
|
490
484
|
# Name: <%= project_fields.text_field :name %>
|
@@ -513,7 +507,7 @@ module ActionView
|
|
513
507
|
# parameter with a value that evaluates to +true+
|
514
508
|
# (eg. 1, '1', true, or 'true'):
|
515
509
|
#
|
516
|
-
# <%= form_for @person
|
510
|
+
# <%= form_for @person do |person_form| %>
|
517
511
|
# ...
|
518
512
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
519
513
|
# Delete: <%= project_fields.check_box :_destroy %>
|
@@ -533,10 +527,7 @@ module ActionView
|
|
533
527
|
end
|
534
528
|
|
535
529
|
builder = options[:builder] || ActionView::Base.default_form_builder
|
536
|
-
|
537
|
-
with_output_buffer do
|
538
|
-
yield builder.new(object_name, object, self, options, block)
|
539
|
-
end
|
530
|
+
capture(builder.new(object_name, object, self, options, block), &block)
|
540
531
|
end
|
541
532
|
|
542
533
|
# Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object
|
@@ -778,6 +769,56 @@ module ActionView
|
|
778
769
|
def radio_button(object_name, method, tag_value, options = {})
|
779
770
|
InstanceTag.new(object_name, method, self, options.delete(:object)).to_radio_button_tag(tag_value, options)
|
780
771
|
end
|
772
|
+
|
773
|
+
# Returns a text_field of type "search".
|
774
|
+
def search_field(object_name, method, options = {})
|
775
|
+
options = options.stringify_keys
|
776
|
+
|
777
|
+
if options["autosave"]
|
778
|
+
if options["autosave"] == true
|
779
|
+
options["autosave"] = request.host.split(".").reverse.join(".")
|
780
|
+
end
|
781
|
+
options["results"] ||= 10
|
782
|
+
end
|
783
|
+
|
784
|
+
if options["onsearch"]
|
785
|
+
options["incremental"] = true unless options.has_key?("incremental")
|
786
|
+
end
|
787
|
+
|
788
|
+
InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("search", options)
|
789
|
+
end
|
790
|
+
|
791
|
+
# Returns a text_field of type "tel".
|
792
|
+
def telephone_field(object_name, method, options = {})
|
793
|
+
InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("tel", options)
|
794
|
+
end
|
795
|
+
alias phone_field telephone_field
|
796
|
+
|
797
|
+
# Returns a text_field of type "url".
|
798
|
+
def url_field(object_name, method, options = {})
|
799
|
+
InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("url", options)
|
800
|
+
end
|
801
|
+
|
802
|
+
# Returns a text_field of type "email".
|
803
|
+
def email_field(object_name, method, options = {})
|
804
|
+
InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("email", options)
|
805
|
+
end
|
806
|
+
|
807
|
+
# Returns an input tag of type "number".
|
808
|
+
#
|
809
|
+
# ==== Options
|
810
|
+
# * Accepts same options as number_field_tag
|
811
|
+
def number_field(object_name, method, options = {})
|
812
|
+
InstanceTag.new(object_name, method, self, options.delete(:object)).to_number_field_tag("number", options)
|
813
|
+
end
|
814
|
+
|
815
|
+
# Returns an input tag of type "range".
|
816
|
+
#
|
817
|
+
# ==== Options
|
818
|
+
# * Accepts same options as range_field_tag
|
819
|
+
def range_field(object_name, method, options = {})
|
820
|
+
InstanceTag.new(object_name, method, self, options.delete(:object)).to_number_field_tag("range", options)
|
821
|
+
end
|
781
822
|
end
|
782
823
|
|
783
824
|
module InstanceTagMethods #:nodoc:
|
@@ -841,6 +882,14 @@ module ActionView
|
|
841
882
|
tag("input", options)
|
842
883
|
end
|
843
884
|
|
885
|
+
def to_number_field_tag(field_type, options = {})
|
886
|
+
options = options.stringify_keys
|
887
|
+
if range = options.delete("in") || options.delete("within")
|
888
|
+
options.update("min" => range.min, "max" => range.max)
|
889
|
+
end
|
890
|
+
to_input_field_tag(field_type, options)
|
891
|
+
end
|
892
|
+
|
844
893
|
def to_radio_button_tag(tag_value, options = {})
|
845
894
|
options = DEFAULT_RADIO_OPTIONS.merge(options.stringify_keys)
|
846
895
|
options["type"] = "radio"
|
@@ -1041,7 +1090,7 @@ module ActionView
|
|
1041
1090
|
end
|
1042
1091
|
|
1043
1092
|
(field_helpers - %w(label check_box radio_button fields_for hidden_field)).each do |selector|
|
1044
|
-
src,
|
1093
|
+
src, line = <<-end_src, __LINE__ + 1
|
1045
1094
|
def #{selector}(method, options = {}) # def text_field(method, options = {})
|
1046
1095
|
@template.send( # @template.send(
|
1047
1096
|
#{selector.inspect}, # "text_field",
|
@@ -1050,7 +1099,7 @@ module ActionView
|
|
1050
1099
|
objectify_options(options)) # objectify_options(options))
|
1051
1100
|
end # end
|
1052
1101
|
end_src
|
1053
|
-
class_eval src,
|
1102
|
+
class_eval src, __FILE__, line
|
1054
1103
|
end
|
1055
1104
|
|
1056
1105
|
def fields_for(record_or_name_or_array, *args, &block)
|
@@ -1105,14 +1154,6 @@ module ActionView
|
|
1105
1154
|
@template.hidden_field(@object_name, method, objectify_options(options))
|
1106
1155
|
end
|
1107
1156
|
|
1108
|
-
def error_message_on(method, *args)
|
1109
|
-
@template.error_message_on(@object, method, *args)
|
1110
|
-
end
|
1111
|
-
|
1112
|
-
def error_messages(options = {})
|
1113
|
-
@template.error_messages_for(@object_name, objectify_options(options))
|
1114
|
-
end
|
1115
|
-
|
1116
1157
|
# Add the submit button for the given form. When no value is given, it checks
|
1117
1158
|
# if the object is a new resource or not to create the proper label:
|
1118
1159
|
#
|