mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Added FormHelper#form_for and FormHelper#fields_for that makes it easier to work with forms for single objects also if they don't reside in instance variables [DHH]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3003 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
4a5b042fc7
commit
947cec29d5
10 changed files with 338 additions and 24 deletions
|
@ -1,5 +1,23 @@
|
|||
*SVN*
|
||||
|
||||
* Added FormHelper#form_for and FormHelper#fields_for that makes it easier to work with forms for single objects also if they don't reside in instance variables [DHH]. Examples:
|
||||
|
||||
<% form_for :person => @person, :url => { :action => "update" } do |f| %>
|
||||
First name: <%= f.text_field :first_name %>
|
||||
Last name : <%= f.text_field :last_name %>
|
||||
Biography : <%= f.text_area :biography %>
|
||||
Admin? : <%= f.check_box :admin %>
|
||||
<% end %>
|
||||
|
||||
<% form_for :person => @person, :url => { :action => "update" } do |person_form| %>
|
||||
First name: <%= person_form.text_field :first_name %>
|
||||
Last name : <%= person_form.text_field :last_name %>
|
||||
|
||||
<% fields_for :permission => @person.permission do |permission_fields| %>
|
||||
Admin? : <%= permission_fields.check_box :admin %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
* options_for_select allows any objects which respond_to? :first and :last rather than restricting to Array and Range. #2824 [Jacob Robbins <jrobbins@cmj.com>, Jeremy Kemper]
|
||||
|
||||
* The auto_link text helper accepts an optional block to format the link text for each url and email address. Example: auto_link(post.body) { |text| truncate(text, 10) } [Jeremy Kemper]
|
||||
|
|
|
@ -293,5 +293,15 @@ module ActionView
|
|||
datetime_select
|
||||
end
|
||||
end
|
||||
|
||||
class FormBuilder
|
||||
def date_select(method, options = {})
|
||||
@template.date_select(@object_name, method, options.merge(:object => @object))
|
||||
end
|
||||
|
||||
def datetime_select(method, options = {})
|
||||
@template.datetime_select(@object_name, method, options.merge(:object => @object))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -65,6 +65,78 @@ module ActionView
|
|||
# There's also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html,
|
||||
# link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html
|
||||
module FormHelper
|
||||
# Creates a form and a scope around a specific model object, which is then used as a base for questioning about
|
||||
# values for the fields. Examples:
|
||||
#
|
||||
# <% form_for :person => @person, :url => { :action => "update" } do |f| %>
|
||||
# First name: <%= f.text_field :first_name %>
|
||||
# Last name : <%= f.text_field :last_name %>
|
||||
# Biography : <%= f.text_area :biography %>
|
||||
# Admin? : <%= f.check_box :admin %>
|
||||
# <% end %>
|
||||
#
|
||||
# Worth noting is that the form_for tag is called in a ERb evaluation block, not a ERb output block. So that's <tt><% %></tt>,
|
||||
# not <tt><%= %></tt>. Also worth noting is that the form_for yields a form_builder object, in this example as f, which emulates
|
||||
# the API for the stand-alone FormHelper methods, but without the object name. So instead of <tt>text_field :person, :name</tt>,
|
||||
# you get away with <tt>f.text_field :name</tt>.
|
||||
#
|
||||
# That in itself is a modest increase in comfort. The big news is that form_for allows us to more easily escape the instance
|
||||
# variable convention, so while the stand-alone approach would require <tt>text_field :person, :name, :object => person</tt>
|
||||
# to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with
|
||||
# <tt>:person => person</tt> and all subsequent field calls save <tt>:person</tt> and <tt>:object => person</tt>.
|
||||
#
|
||||
# Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods
|
||||
# and methods from FormTagHelper. Example:
|
||||
#
|
||||
# <% form_for :person => @person, :url => { :action => "update" } do |f| %>
|
||||
# First name: <%= f.text_field :first_name %>
|
||||
# Last name : <%= f.text_field :last_name %>
|
||||
# Biography : <%= text_area :person, :biography %>
|
||||
# Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>
|
||||
# <% end %>
|
||||
#
|
||||
# Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base.
|
||||
# Like collection_select and datetime_select.
|
||||
def form_for(options, *parameters_for_url, &proc)
|
||||
keys = [ :url, :method, :multipart ]
|
||||
leftover_keys = (options.keys - keys)
|
||||
|
||||
case leftover_keys.length
|
||||
when 0 then raise 'No object given!'
|
||||
when 1 then
|
||||
object_name = leftover_keys.first
|
||||
object = options[object_name]
|
||||
else
|
||||
raise "Too many options: #{options.inspect}"
|
||||
end
|
||||
|
||||
url_for_options = options[:url]
|
||||
additional_options = options.reject { |k, v| ![ :method, :multipart ].include?(k) }
|
||||
|
||||
concat(form_tag(url_for_options, additional_options, *parameters_for_url), proc.binding)
|
||||
fields_for({ options.keys.first => options.values.first }, &proc)
|
||||
concat(end_form_tag, proc.binding)
|
||||
end
|
||||
|
||||
# Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes
|
||||
# fields_for suitable for specifying additional model objects in the same form. Example:
|
||||
#
|
||||
# <% form_for :person => @person, :url => { :action => "update" } do |person_form| %>
|
||||
# First name: <%= person_form.text_field :first_name %>
|
||||
# Last name : <%= person_form.text_field :last_name %>
|
||||
#
|
||||
# <% fields_for :permission => @person.permission do |permission_fields| %>
|
||||
# Admin? : <%= permission_fields.check_box :admin %>
|
||||
# <% end %>
|
||||
# <% end %>
|
||||
#
|
||||
# Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base.
|
||||
# Like collection_select and datetime_select.
|
||||
def fields_for(object = {}, &proc)
|
||||
form_builder = FormBuilder.new(object.keys.first, object.values.first, self, proc)
|
||||
proc.call(form_builder)
|
||||
end
|
||||
|
||||
# Returns an input tag of the "text" type tailored for accessing a specified attribute (identified by +method+) on an object
|
||||
# assigned to the template (identified by +object+). Additional options on the input tag can be passed as a
|
||||
# hash with +options+.
|
||||
|
@ -72,23 +144,23 @@ module ActionView
|
|||
# Examples (call, result):
|
||||
# text_field("post", "title", "size" => 20)
|
||||
# <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" />
|
||||
def text_field(object, method, options = {})
|
||||
InstanceTag.new(object, method, self).to_input_field_tag("text", options)
|
||||
def text_field(object_name, method, options = {})
|
||||
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("text", options)
|
||||
end
|
||||
|
||||
# Works just like text_field, but returns an input tag of the "password" type instead.
|
||||
def password_field(object, method, options = {})
|
||||
InstanceTag.new(object, method, self).to_input_field_tag("password", options)
|
||||
def password_field(object_name, method, options = {})
|
||||
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("password", options)
|
||||
end
|
||||
|
||||
# Works just like text_field, but returns an input tag of the "hidden" type instead.
|
||||
def hidden_field(object, method, options = {})
|
||||
InstanceTag.new(object, method, self).to_input_field_tag("hidden", options)
|
||||
def hidden_field(object_name, method, options = {})
|
||||
InstanceTag.new(object_name, method, self).to_input_field_tag("hidden", options)
|
||||
end
|
||||
|
||||
# Works just like text_field, but returns an input tag of the "file" type instead, which won't have a default value.
|
||||
def file_field(object, method, options = {})
|
||||
InstanceTag.new(object, method, self).to_input_field_tag("file", options)
|
||||
def file_field(object_name, method, options = {})
|
||||
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("file", options)
|
||||
end
|
||||
|
||||
# Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by +method+)
|
||||
|
@ -100,8 +172,8 @@ module ActionView
|
|||
# <textarea cols="20" rows="40" id="post_body" name="post[body]">
|
||||
# #{@post.body}
|
||||
# </textarea>
|
||||
def text_area(object, method, options = {})
|
||||
InstanceTag.new(object, method, self).to_text_area_tag(options)
|
||||
def text_area(object_name, method, options = {})
|
||||
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_text_area_tag(options)
|
||||
end
|
||||
|
||||
# Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object
|
||||
|
@ -120,8 +192,8 @@ module ActionView
|
|||
# check_box("puppy", "gooddog", {}, "yes", "no")
|
||||
# <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
|
||||
# <input name="puppy[gooddog]" type="hidden" value="no" />
|
||||
def check_box(object, method, options = {}, checked_value = "1", unchecked_value = "0")
|
||||
InstanceTag.new(object, method, self).to_check_box_tag(options, checked_value, unchecked_value)
|
||||
def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
|
||||
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value)
|
||||
end
|
||||
|
||||
# Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object
|
||||
|
@ -134,8 +206,8 @@ module ActionView
|
|||
# <input type="radio" id="post_category" name="post[category]" value="rails" checked="checked" />
|
||||
# <input type="radio" id="post_category" name="post[category]" value="java" />
|
||||
#
|
||||
def radio_button(object, method, tag_value, options = {})
|
||||
InstanceTag.new(object, method, self).to_radio_button_tag(tag_value, options)
|
||||
def radio_button(object_name, method, tag_value, options = {})
|
||||
InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_radio_button_tag(tag_value, options)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -149,9 +221,10 @@ module ActionView
|
|||
DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }.freeze unless const_defined?(:DEFAULT_TEXT_AREA_OPTIONS)
|
||||
DEFAULT_DATE_OPTIONS = { :discard_type => true }.freeze unless const_defined?(:DEFAULT_DATE_OPTIONS)
|
||||
|
||||
def initialize(object_name, method_name, template_object, local_binding = nil)
|
||||
def initialize(object_name, method_name, template_object, local_binding = nil, object = nil)
|
||||
@object_name, @method_name = object_name.to_s, method_name.to_s
|
||||
@template_object, @local_binding = template_object, local_binding
|
||||
@object = object
|
||||
if @object_name.sub!(/\[\]$/,"")
|
||||
@auto_index = @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}").id_before_type_cast
|
||||
end
|
||||
|
@ -240,7 +313,7 @@ module ActionView
|
|||
end
|
||||
|
||||
def object
|
||||
@template_object.instance_variable_get "@#{@object_name}"
|
||||
@object || @template_object.instance_variable_get("@#{@object_name}")
|
||||
end
|
||||
|
||||
def value
|
||||
|
@ -286,5 +359,30 @@ module ActionView
|
|||
"#{@object_name}_#{index}_#{@method_name}"
|
||||
end
|
||||
end
|
||||
|
||||
class FormBuilder
|
||||
def initialize(object_name, object, template, proc)
|
||||
@object_name, @object, @template, @proc = object_name, object, template, proc
|
||||
end
|
||||
|
||||
(FormHelper.instance_methods - [ :check_box, :radio_button ]).each do |selector|
|
||||
next if selector == "form_for"
|
||||
|
||||
src = <<-end_src
|
||||
def #{selector}(method, options = {})
|
||||
@template.send(#{selector.inspect}, @object_name, method, options.merge(:object => @object))
|
||||
end
|
||||
end_src
|
||||
class_eval src, __FILE__, __LINE__
|
||||
end
|
||||
|
||||
def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
|
||||
@template.check_box(@object_name, method, options.merge(:object => @object), checked_value, unchecked_value)
|
||||
end
|
||||
|
||||
def radio_button(method, tag_value, options = {})
|
||||
@template.check_box(@object_name, method, tag_value, options.merge(:object => @object))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -335,5 +335,23 @@ module ActionView
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
class FormBuilder
|
||||
def select(method, choices, options = {}, html_options = {})
|
||||
@template.select(@object_name, method, choices, options.merge(:object => @object), html_options)
|
||||
end
|
||||
|
||||
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
|
||||
@template.collection_select(@object_name, method, collection, value_method, text_method, options.merge(:object => @object), html_options)
|
||||
end
|
||||
|
||||
def country_select(method, priority_countries = nil, options = {}, html_options = {})
|
||||
@template.country_select(@object_name, method, priority_countries, options.merge(:object => @object), html_options)
|
||||
end
|
||||
|
||||
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
|
||||
@template.time_zone_select(@object_name, method, priority_zones, options.merge(:object => @object), html_options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ module ActionView
|
|||
# Options:
|
||||
# * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".
|
||||
# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
|
||||
def form_tag(url_for_options = {}, options = {}, *parameters_for_url)
|
||||
def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &proc)
|
||||
html_options = { "method" => "post" }.merge(options.stringify_keys)
|
||||
|
||||
if html_options["multipart"]
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
||||
$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
|
||||
$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib/active_support')
|
||||
$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers')
|
||||
|
||||
require 'test/unit'
|
||||
require 'action_controller'
|
||||
require 'breakpoint'
|
||||
|
||||
require 'action_controller/test_process'
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
require 'test/unit'
|
||||
require File.dirname(__FILE__) + '/../../lib/action_view/helpers/date_helper'
|
||||
require File.dirname(__FILE__) + "/../abstract_unit"
|
||||
|
||||
class DateHelperTest < Test::Unit::TestCase
|
||||
include ActionView::Helpers::DateHelper
|
||||
include ActionView::Helpers::FormHelper
|
||||
|
||||
silence_warnings do
|
||||
Post = Struct.new("Post", :written_on, :updated_at)
|
||||
end
|
||||
|
||||
def test_distance_in_words
|
||||
from = Time.mktime(2004, 3, 6, 21, 41, 18)
|
||||
|
@ -497,6 +501,38 @@ class DateHelperTest < Test::Unit::TestCase
|
|||
assert_equal expected, select_date(0, :start_year => 2003, :end_year => 2005, :prefix => "date[first]")
|
||||
end
|
||||
|
||||
def test_date_select_within_fields_for
|
||||
@post = Post.new
|
||||
@post.written_on = Date.new(2004, 6, 15)
|
||||
|
||||
_erbout = ''
|
||||
|
||||
fields_for :post => @post do |f|
|
||||
_erbout.concat f.date_select(:written_on)
|
||||
end
|
||||
|
||||
expected = "<select name='post[written_on(1i)]'>\n<option value='1999'>1999</option>\n<option value='2000'>2000</option>\n<option value='2001'>2001</option>\n<option value='2002'>2002</option>\n<option value='2003'>2003</option>\n<option selected='selected' value='2004'>2004</option>\n<option value='2005'>2005</option>\n<option value='2006'>2006</option>\n<option value='2007'>2007</option>\n<option value='2008'>2008</option>\n<option value='2009'>2009</option>\n</select>\n" +
|
||||
"<select name='post[written_on(2i)]'>\n<option value='1'>January</option>\n<option value='2'>February</option>\n<option value='3'>March</option>\n<option value='4'>April</option>\n<option value='5'>May</option>\n<option selected='selected' value='6'>June</option>\n<option value='7'>July</option>\n<option value='8'>August</option>\n<option value='9'>September</option>\n<option value='10'>October</option>\n<option value='11'>November</option>\n<option value='12'>December</option>\n</select>\n" +
|
||||
"<select name='post[written_on(3i)]'>\n<option value='1'>1</option>\n<option value='2'>2</option>\n<option value='3'>3</option>\n<option value='4'>4</option>\n<option value='5'>5</option>\n<option value='6'>6</option>\n<option value='7'>7</option>\n<option value='8'>8</option>\n<option value='9'>9</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option selected='selected' value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n</select>\n"
|
||||
|
||||
assert_dom_equal(expected, _erbout)
|
||||
end
|
||||
|
||||
def test_datetime_select_within_fields_for
|
||||
@post = Post.new
|
||||
@post.updated_at = Time.local(2004, 6, 15, 16, 35)
|
||||
|
||||
_erbout = ''
|
||||
|
||||
fields_for :post => @post do |f|
|
||||
_erbout.concat f.datetime_select(:updated_at)
|
||||
end
|
||||
|
||||
expected = "<select name='post[updated_at(1i)]'>\n<option value='1999'>1999</option>\n<option value='2000'>2000</option>\n<option value='2001'>2001</option>\n<option value='2002'>2002</option>\n<option value='2003'>2003</option>\n<option selected='selected' value='2004'>2004</option>\n<option value='2005'>2005</option>\n<option value='2006'>2006</option>\n<option value='2007'>2007</option>\n<option value='2008'>2008</option>\n<option value='2009'>2009</option>\n</select>\n<select name='post[updated_at(2i)]'>\n<option value='1'>January</option>\n<option value='2'>February</option>\n<option value='3'>March</option>\n<option value='4'>April</option>\n<option value='5'>May</option>\n<option selected='selected' value='6'>June</option>\n<option value='7'>July</option>\n<option value='8'>August</option>\n<option value='9'>September</option>\n<option value='10'>October</option>\n<option value='11'>November</option>\n<option value='12'>December</option>\n</select>\n<select name='post[updated_at(3i)]'>\n<option value='1'>1</option>\n<option value='2'>2</option>\n<option value='3'>3</option>\n<option value='4'>4</option>\n<option value='5'>5</option>\n<option value='6'>6</option>\n<option value='7'>7</option>\n<option value='8'>8</option>\n<option value='9'>9</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option selected='selected' value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n</select>\n — <select name='post[updated_at(4i)]'>\n<option value='00'>00</option>\n<option value='01'>01</option>\n<option value='02'>02</option>\n<option value='03'>03</option>\n<option value='04'>04</option>\n<option value='05'>05</option>\n<option value='06'>06</option>\n<option value='07'>07</option>\n<option value='08'>08</option>\n<option value='09'>09</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option value='15'>15</option>\n<option selected='selected' value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n</select>\n : <select name='post[updated_at(5i)]'>\n<option value='00'>00</option>\n<option value='01'>01</option>\n<option value='02'>02</option>\n<option value='03'>03</option>\n<option value='04'>04</option>\n<option value='05'>05</option>\n<option value='06'>06</option>\n<option value='07'>07</option>\n<option value='08'>08</option>\n<option value='09'>09</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n<option value='32'>32</option>\n<option value='33'>33</option>\n<option value='34'>34</option>\n<option selected='selected' value='35'>35</option>\n<option value='36'>36</option>\n<option value='37'>37</option>\n<option value='38'>38</option>\n<option value='39'>39</option>\n<option value='40'>40</option>\n<option value='41'>41</option>\n<option value='42'>42</option>\n<option value='43'>43</option>\n<option value='44'>44</option>\n<option value='45'>45</option>\n<option value='46'>46</option>\n<option value='47'>47</option>\n<option value='48'>48</option>\n<option value='49'>49</option>\n<option value='50'>50</option>\n<option value='51'>51</option>\n<option value='52'>52</option>\n<option value='53'>53</option>\n<option value='54'>54</option>\n<option value='55'>55</option>\n<option value='56'>56</option>\n<option value='57'>57</option>\n<option value='58'>58</option>\n<option value='59'>59</option>\n</select>\n"
|
||||
|
||||
assert_dom_equal(expected, _erbout)
|
||||
end
|
||||
|
||||
def test_date_select_with_zero_value_and_no_start_year
|
||||
expected = %(<select name="date[first][year]">\n)
|
||||
(Date.today.year-5).upto(Date.today.year+1) { |y| expected << %(<option value="#{y}">#{y}</option>\n) }
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
require 'test/unit'
|
||||
require 'erb'
|
||||
require File.dirname(__FILE__) + '/../../lib/action_view/helpers/form_helper'
|
||||
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/hash' #for stringify keys
|
||||
require File.dirname(__FILE__) + '/../abstract_unit'
|
||||
|
||||
class FormHelperTest < Test::Unit::TestCase
|
||||
include ActionView::Helpers::FormHelper
|
||||
include ActionView::Helpers::FormTagHelper
|
||||
include ActionView::Helpers::UrlHelper
|
||||
include ActionView::Helpers::TagHelper
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
silence_warnings do
|
||||
Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on, :cost)
|
||||
|
@ -27,6 +28,13 @@ class FormHelperTest < Test::Unit::TestCase
|
|||
@post.body = "Back to the hill and over it again!"
|
||||
@post.secret = 1
|
||||
@post.written_on = Date.new(2004, 6, 15)
|
||||
|
||||
@controller = Class.new do
|
||||
def url_for(options, *parameters_for_method_reference)
|
||||
"http://www.example.com"
|
||||
end
|
||||
end
|
||||
@controller = @controller.new
|
||||
end
|
||||
|
||||
def test_text_field
|
||||
|
@ -187,4 +195,65 @@ class FormHelperTest < Test::Unit::TestCase
|
|||
radio_button("post[]", "title", "Goodbye World")
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def test_form_for
|
||||
_erbout = ''
|
||||
|
||||
form_for(:post => @post) do |f|
|
||||
_erbout.concat f.text_field(:title)
|
||||
_erbout.concat f.text_area(:body)
|
||||
_erbout.concat f.check_box(:secret)
|
||||
end
|
||||
|
||||
expected =
|
||||
"<form action='http://www.example.com' method='post'>" +
|
||||
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
|
||||
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
|
||||
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
|
||||
"<input name='post[secret]' type='hidden' value='0' />" +
|
||||
"</form>"
|
||||
|
||||
assert_dom_equal expected, _erbout
|
||||
end
|
||||
|
||||
def test_fields_for
|
||||
_erbout = ''
|
||||
|
||||
fields_for(:post => @post) do |f|
|
||||
_erbout.concat f.text_field(:title)
|
||||
_erbout.concat f.text_area(:body)
|
||||
_erbout.concat f.check_box(:secret)
|
||||
end
|
||||
|
||||
expected =
|
||||
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
|
||||
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
|
||||
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
|
||||
"<input name='post[secret]' type='hidden' value='0' />"
|
||||
|
||||
assert_dom_equal expected, _erbout
|
||||
end
|
||||
|
||||
def test_form_for_and_fields_for
|
||||
_erbout = ''
|
||||
|
||||
form_for(:post => @post) do |post_form|
|
||||
_erbout.concat post_form.text_field(:title)
|
||||
_erbout.concat post_form.text_area(:body)
|
||||
|
||||
fields_for(:parent_post => @post) do |parent_fields|
|
||||
_erbout.concat parent_fields.check_box(:secret)
|
||||
end
|
||||
end
|
||||
|
||||
expected =
|
||||
"<form action='http://www.example.com' method='post'>" +
|
||||
"<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
|
||||
"<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
|
||||
"<input name='parent_post[secret]' checked='checked' type='checkbox' id='parent_post_secret' value='1' />" +
|
||||
"<input name='parent_post[secret]' type='hidden' value='0' />" +
|
||||
"</form>"
|
||||
|
||||
assert_dom_equal expected, _erbout
|
||||
end
|
||||
end
|
|
@ -23,6 +23,7 @@ end
|
|||
ActionView::Helpers::FormOptionsHelper::TimeZone = MockTimeZone
|
||||
|
||||
class FormOptionsHelperTest < Test::Unit::TestCase
|
||||
include ActionView::Helpers::FormHelper
|
||||
include ActionView::Helpers::FormOptionsHelper
|
||||
|
||||
silence_warnings do
|
||||
|
@ -222,6 +223,22 @@ class FormOptionsHelperTest < Test::Unit::TestCase
|
|||
)
|
||||
end
|
||||
|
||||
def test_select_under_fields_for
|
||||
@post = Post.new
|
||||
@post.category = "<mus>"
|
||||
|
||||
_erbout = ''
|
||||
|
||||
fields_for :post => @post do |f|
|
||||
_erbout.concat f.select(:category, %w( abe <mus> hest))
|
||||
end
|
||||
|
||||
assert_dom_equal(
|
||||
"<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"<mus>\" selected=\"selected\"><mus></option>\n<option value=\"hest\">hest</option></select>",
|
||||
_erbout
|
||||
)
|
||||
end
|
||||
|
||||
def test_select_with_blank
|
||||
@post = Post.new
|
||||
@post.category = "<mus>"
|
||||
|
@ -283,6 +300,28 @@ class FormOptionsHelperTest < Test::Unit::TestCase
|
|||
)
|
||||
end
|
||||
|
||||
def test_collection_select_under_fields_for
|
||||
@posts = [
|
||||
Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"),
|
||||
Post.new("Babe went home", "Babe", "To a little house", "shh!"),
|
||||
Post.new("Cabe went home", "Cabe", "To a little house", "shh!")
|
||||
]
|
||||
|
||||
@post = Post.new
|
||||
@post.author_name = "Babe"
|
||||
|
||||
_erbout = ''
|
||||
|
||||
fields_for :post => @post do |f|
|
||||
_erbout.concat f.collection_select(:author_name, @posts, :author_name, :author_name)
|
||||
end
|
||||
|
||||
assert_dom_equal(
|
||||
"<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"<Abe>\"><Abe></option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\">Cabe</option></select>",
|
||||
_erbout
|
||||
)
|
||||
end
|
||||
|
||||
def test_collection_select_with_blank_and_style
|
||||
@posts = [
|
||||
Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"),
|
||||
|
@ -324,6 +363,27 @@ class FormOptionsHelperTest < Test::Unit::TestCase
|
|||
html
|
||||
end
|
||||
|
||||
def test_time_zone_select_under_fields_for
|
||||
@firm = Firm.new("D")
|
||||
|
||||
_erbout = ''
|
||||
|
||||
fields_for :firm => @firm do |f|
|
||||
_erbout.concat f.time_zone_select(:time_zone)
|
||||
end
|
||||
|
||||
assert_dom_equal(
|
||||
"<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" +
|
||||
"<option value=\"A\">A</option>\n" +
|
||||
"<option value=\"B\">B</option>\n" +
|
||||
"<option value=\"C\">C</option>\n" +
|
||||
"<option value=\"D\" selected=\"selected\">D</option>\n" +
|
||||
"<option value=\"E\">E</option>" +
|
||||
"</select>",
|
||||
_erbout
|
||||
)
|
||||
end
|
||||
|
||||
def test_time_zone_select_with_blank
|
||||
@firm = Firm.new("D")
|
||||
html = time_zone_select("firm", "time_zone", nil, :include_blank => true)
|
||||
|
|
|
@ -93,5 +93,9 @@ class FormTagHelperTest < Test::Unit::TestCase
|
|||
expected = %(<input id="admin" name="title" type="text" value="Hello!" />)
|
||||
assert_dom_equal expected, actual
|
||||
end
|
||||
|
||||
def test_pass
|
||||
assert_equal 1, 1
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue