Added tests for form_for and an authenticity_token option. Added docs for for_for and authenticity_token option. Added section to form helpers guide about forms for external resources and new authenticity_token option for form_tag and form_for helpers.

[#6228 state:committed]

Signed-off-by: Santiago Pastorino <santiago@wyeworks.com>
This commit is contained in:
Timothy N. Tsvetkov 2011-02-05 18:37:53 +03:00 committed by Santiago Pastorino
parent 5af31f37fb
commit b9309b47cd
3 changed files with 72 additions and 0 deletions

@ -298,6 +298,24 @@ module FormHelper
#
# If you don't need to attach a form to a model instance, then check out
# FormTagHelper#form_tag.
#
# === Form to external resources
#
# When you build forms to external resources sometimes you need to set an authenticity token or just render a form
# without it, for example when you submit data to a payment gateway number and types of fields could be limited.
#
# To set an authenticity token you need to pass an <tt>:authenticity_token</tt> parameter in the <tt>:html</tt>
# options section:
#
# <%= form_for @invoice, :url => external_url, :html => { :authenticity_token => 'external_token' } do |f|
# ...
# <% end %>
#
# If you don't want to an authenticity token field be rendered at all just pass <tt>false</tt>:
#
# <%= form_for @invoice, :url => external_url, :html => { :authenticity_token => false } do |f|
# ...
# <% end %>
def form_for(record, options = {}, &proc)
raise ArgumentError, "Missing block" unless block_given?

@ -28,6 +28,14 @@ def meta
render :inline => "<%= csrf_meta_tags %>"
end
def external_form_for
render :inline => "<%= form_for(:some_resource, :html => { :authenticity_token => 'external_token' }) {} %>"
end
def form_for_without_protection
render :inline => "<%= form_for(:some_resource, :html => { :authenticity_token => false }) {} %>"
end
def rescue_action(e) raise e end
end
@ -68,6 +76,16 @@ def test_should_render_form_with_token_tag
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
end
def test_should_render_external_form_for_with_external_token
get :external_form_for
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', 'external_token'
end
def test_should_render_form_for_without_token_tag
get :form_for_without_protection
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
end
def test_should_render_button_to_with_token_tag
get :show_button
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token

@ -9,6 +9,7 @@ In this guide you will:
* Generate select boxes from multiple types of data
* Understand the date and time helpers Rails provides
* Learn what makes a file upload form different
* Learn some cases of building forms to external resources
* Find out where to look for complex forms
endprologue.
@ -763,6 +764,40 @@ As a shortcut you can append [] to the name and omit the +:index+ option. This i
produces exactly the same output as the previous example.
h3. Forms to external resources
If you need to post some data to an external resource it is still great to build your from using rails form helpers. But sometimes you need to set an +authenticity_token+ for this resource. You can do it by passing an +:authenticity_token => 'your_external_token'+ parameter to the +form_tag+ options:
<erb>
<%= form_tag 'http://farfar.away/form', :authenticity_token => 'external_token') do %>
Form contents
<% end %>
</erb>
Sometimes when you submit data to an external resource, like payment gateway, fields you can use in your form are limited by an external API. So you may want not to generate an +authenticity_token+ hidden field at all. For doing this just pass +false+ to the +:authenticity_token+ option:
<erb>
<%= form_tag 'http://farfar.away/form', :authenticity_token => 'external_token') do %>
Form contents
<% end %>
</erb>
The same technique is available for the +form_for+ too. You need just to set an +authenticity_token+ through +html+ options:
<erb>
<%= form_for @invoice, :url => external_url, :html => { :authenticity_token => 'external_token' } do |f|
Form contents
<% end %>
</erb>
Or if you don't want to render an +authenticity_token+ field:
<erb>
<%= form_for @invoice, :url => external_url, :html => { :authenticity_token => false } do |f|
Form contents
<% end %>
</erb>
h3. Building Complex Forms
Many apps grow beyond simple forms editing a single object. For example when creating a Person you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary. While this guide has shown you all the pieces necessary to handle this, Rails does not yet have a standard end-to-end way of accomplishing this, but many have come up with viable approaches. These include:
@ -776,6 +811,7 @@ Many apps grow beyond simple forms editing a single object. For example when cre
h3. Changelog
* February 5, 2011: Added 'Forms to external resources' section. Timothy N. Tsvetkov <timothy.tsvetkov@gmail.com>
* April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
h3. Authors