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.

Files changed (47) hide show
  1. data/CHANGELOG +37 -0
  2. data/lib/abstract_controller/rendering.rb +9 -11
  3. data/lib/action_controller.rb +0 -1
  4. data/lib/action_controller/base.rb +45 -44
  5. data/lib/action_controller/caching/pages.rb +2 -2
  6. data/lib/action_controller/deprecated/base.rb +21 -5
  7. data/lib/action_controller/metal/compatibility.rb +0 -2
  8. data/lib/action_controller/metal/cookies.rb +1 -1
  9. data/lib/action_controller/metal/helpers.rb +1 -1
  10. data/lib/action_controller/metal/http_authentication.rb +12 -5
  11. data/lib/action_controller/metal/responder.rb +3 -2
  12. data/lib/action_controller/polymorphic_routes.rb +1 -1
  13. data/lib/action_controller/railtie.rb +6 -1
  14. data/lib/action_controller/record_identifier.rb +2 -2
  15. data/lib/action_controller/test_case.rb +2 -0
  16. data/lib/action_dispatch/http/mime_negotiation.rb +2 -2
  17. data/lib/action_dispatch/http/request.rb +39 -21
  18. data/lib/action_dispatch/middleware/cookies.rb +18 -22
  19. data/lib/action_dispatch/middleware/params_parser.rb +8 -9
  20. data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
  21. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +1 -1
  22. data/lib/action_dispatch/railtie.rb +1 -0
  23. data/lib/action_dispatch/routing.rb +24 -12
  24. data/lib/action_dispatch/routing/deprecated_mapper.rb +1 -1
  25. data/lib/action_dispatch/routing/mapper.rb +77 -51
  26. data/lib/action_dispatch/routing/route_set.rb +9 -5
  27. data/lib/action_dispatch/routing/url_for.rb +2 -3
  28. data/lib/action_dispatch/testing/integration.rb +24 -11
  29. data/lib/action_dispatch/testing/test_request.rb +2 -0
  30. data/lib/action_pack/version.rb +1 -1
  31. data/lib/action_view/base.rb +8 -2
  32. data/lib/action_view/helpers.rb +3 -6
  33. data/lib/action_view/helpers/active_model_helper.rb +20 -265
  34. data/lib/action_view/helpers/asset_tag_helper.rb +46 -9
  35. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  36. data/lib/action_view/helpers/form_helper.rb +161 -120
  37. data/lib/action_view/helpers/form_options_helper.rb +0 -2
  38. data/lib/action_view/helpers/form_tag_helper.rb +76 -13
  39. data/lib/action_view/helpers/url_helper.rb +48 -21
  40. data/lib/action_view/locale/en.yml +0 -8
  41. data/lib/action_view/lookup_context.rb +11 -4
  42. data/lib/action_view/render/layouts.rb +32 -18
  43. data/lib/action_view/render/partials.rb +2 -2
  44. data/lib/action_view/template.rb +10 -1
  45. data/lib/action_view/test_case.rb +6 -1
  46. metadata +7 -8
  47. 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
- # ==== Examples
509
- # image_path("edit") # => /images/edit
510
- # image_path("edit.png") # => /images/edit.png
511
- # image_path("icons/edit.png") # => /images/icons/edit.png
512
- # image_path("/icons/edit.png") # => /icons/edit.png
513
- # image_path("http://www.railsapplication.com/img/edit.png") # => http://www.railsapplication.com/img/edit.png
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='#{image_path(mouseover)}'"
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
- # expense file system calls. However this prevents you from modifying
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
- # map.resources :posts
13
- # map.root :controller => "posts"
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 models much easier
12
- # compared to using just standard HTML elements by providing a set of
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
- # There are two types of form helpers: those that specifically work with
21
- # model attributes and those that don't. This helper deals with those that
22
- # work with model attributes; to see an example of form helpers that don't
23
- # work with model attributes, check the ActionView::Helpers::FormTagHelper
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
- # The core method of this helper, form_for, gives you the ability to create
27
- # a form for a model instance; for example, let's say that you have a model
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
- # # Note: a @person variable will have been created in the controller.
31
- # # For example: @person = Person.new
32
- # <%= form_for :person, @person, :url => { :action => "create" } do |f| %>
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
- # The HTML generated for this would be:
26
+ # <%= form_for @person do |f| %>
27
+ # <%= f.label :first_name %>:
28
+ # <%= f.text_field :first_name %><br />
39
29
  #
40
- # <form action="/persons/create" method="post">
41
- # <input id="person_first_name" name="person[first_name]" size="30" type="text" />
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
- # If you are using a partial for your form fields, you can use this shortcut:
33
+ # <%= f.submit %>
34
+ # <% end %>
47
35
  #
48
- # <%= form_for :person, @person, :url => { :action => "create" } do |f| %>
49
- # <%= render :partial => f %>
50
- # <%= submit_tag 'Create' %>
51
- # <% end %>
36
+ # The HTML generated for this would be (modulus formatting):
52
37
  #
53
- # This example will render the <tt>people/_form</tt> partial, setting a
54
- # local variable called <tt>form</tt> which references the yielded
55
- # FormBuilder. The <tt>params</tt> object created when this form is
56
- # submitted would look like:
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
- # {"action"=>"create", "controller"=>"persons", "person"=>{"first_name"=>"William", "last_name"=>"Smith"}}
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
- # The params hash has a nested <tt>person</tt> value, which can therefore
61
- # be accessed with <tt>params[:person]</tt> in the controller. If were
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
- # If the object name contains square brackets the id for the object will be
68
- # inserted. For example:
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
- # <%= text_field "person[]", "name" %>
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
- # ...will generate the following ERb.
58
+ # if @person = Person.create(params[:person])
59
+ # # success
60
+ # else
61
+ # # error handling
62
+ # end
73
63
  #
74
- # <input type="text" id="person_<%= @person.id %>_name" name="person[<%= @person.id %>][name]" value="<%= @person.name %>" />
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
- # If the helper is being used to generate a repetitive sequence of similar
77
- # form elements, for example in a partial used by
78
- # <tt>render_collection_of_partials</tt>, the <tt>index</tt> option may
79
- # come in handy. Example:
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
- # <%= text_field "person", "name", "index" => 1 %>
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
- # ...becomes...
79
+ # <input id="person_submit" name="commit" type="submit" value="Update Person" />
80
+ # </form>
84
81
  #
85
- # <input type="text" id="person_1_name" name="person[1][name]" value="<%= @person.name %>" />
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
- # An <tt>index</tt> option may also be passed to <tt>form_for</tt> and
88
- # <tt>fields_for</tt>. This automatically applies the <tt>index</tt> to
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
- # There are also methods for helping to build form tags in
92
- # link:classes/ActionView/Helpers/FormOptionsHelper.html,
93
- # link:classes/ActionView/Helpers/DateHelper.html, and
94
- # link:classes/ActionView/Helpers/ActiveRecordHelper.html
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, :url => { :action => "update" } do |f| %>
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 first argument is a symbol or string with the name of the
132
- # object the form is about, and also the name of the instance variable
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
- # If the instance variable is not <tt>@person</tt> you can pass the actual
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 :person, @person, :url => { :action => "update" } do |f| %>
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 :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
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
- # expands to
197
+ # is equivalent to something like:
216
198
  #
217
- # <%= form_for :post, Post.new, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %>
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(:post, @post, :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| %>
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' id='create-post' method='post' data-remote='true'>
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 :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %>
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 => dom_class(object, :edit), :id => dom_id(object, :edit), :method => :put }
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), :id => dom_id(object), :method => :post }
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, :url => { :action => "update" } do |person_form| %>
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, :url => { :action => "update" } do |person_form| %>
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, :url => { :action => "update" } do |person_form| %>
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, :url => { :action => "update" } do |person_form| %>
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, :url => { :action => "update" } do |person_form| %>
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, :url => { :action => "update" } do |person_form| %>
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, :url => { :action => "update" } do |person_form| %>
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, file, line = <<-end_src, __FILE__, __LINE__ + 1
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, file, line
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
  #