actionpack 2.0.2 → 2.0.4

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 (74) hide show
  1. data/CHANGELOG +45 -0
  2. data/Rakefile +5 -3
  3. data/lib/action_controller.rb +0 -0
  4. data/lib/action_controller/assertions/response_assertions.rb +6 -2
  5. data/lib/action_controller/assertions/routing_assertions.rb +5 -2
  6. data/lib/action_controller/base.rb +4 -3
  7. data/lib/action_controller/cgi_ext/cookie.rb +1 -1
  8. data/lib/action_controller/filters.rb +5 -3
  9. data/lib/action_controller/http_authentication.rb +2 -4
  10. data/lib/action_controller/integration.rb +3 -2
  11. data/lib/action_controller/layout.rb +14 -15
  12. data/lib/action_controller/mime_type.rb +4 -1
  13. data/lib/action_controller/polymorphic_routes.rb +90 -15
  14. data/lib/action_controller/record_identifier.rb +4 -4
  15. data/lib/action_controller/request.rb +29 -14
  16. data/lib/action_controller/request_forgery_protection.rb +41 -34
  17. data/lib/action_controller/request_profiler.rb +16 -6
  18. data/lib/action_controller/response.rb +0 -0
  19. data/lib/action_controller/routing.rb +3 -3
  20. data/lib/action_controller/session/active_record_store.rb +7 -8
  21. data/lib/action_controller/session/cookie_store.rb +2 -3
  22. data/lib/action_controller/templates/rescues/_trace.erb +5 -5
  23. data/lib/action_controller/test_case.rb +24 -4
  24. data/lib/action_controller/test_process.rb +3 -3
  25. data/lib/action_controller/url_rewriter.rb +29 -28
  26. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +2 -2
  27. data/lib/action_controller/verification.rb +73 -57
  28. data/lib/action_pack/version.rb +1 -1
  29. data/lib/action_view/base.rb +24 -6
  30. data/lib/action_view/helpers/active_record_helper.rb +1 -1
  31. data/lib/action_view/helpers/asset_tag_helper.rb +12 -6
  32. data/lib/action_view/helpers/atom_feed_helper.rb +21 -17
  33. data/lib/action_view/helpers/date_helper.rb +6 -6
  34. data/lib/action_view/helpers/form_helper.rb +3 -2
  35. data/lib/action_view/helpers/form_options_helper.rb +12 -1
  36. data/lib/action_view/helpers/form_tag_helper.rb +18 -0
  37. data/lib/action_view/helpers/number_helper.rb +1 -1
  38. data/lib/action_view/helpers/prototype_helper.rb +1 -1
  39. data/lib/action_view/helpers/text_helper.rb +1 -1
  40. data/lib/action_view/helpers/url_helper.rb +5 -9
  41. data/lib/action_view/template_error.rb +11 -4
  42. data/test/activerecord/active_record_store_test.rb +1 -1
  43. data/test/activerecord/fixtures_test.rb +24 -0
  44. data/test/controller/action_pack_assertions_test.rb +37 -2
  45. data/test/controller/base_test.rb +4 -1
  46. data/test/controller/cgi_test.rb +4 -3
  47. data/test/controller/filters_test.rb +4 -7
  48. data/test/controller/html-scanner/sanitizer_test.rb +7 -1
  49. data/test/controller/integration_test.rb +0 -1
  50. data/test/controller/mime_type_test.rb +5 -0
  51. data/test/controller/new_render_test.rb +25 -2
  52. data/test/controller/polymorphic_routes_test.rb +106 -75
  53. data/test/controller/redirect_test.rb +11 -0
  54. data/test/controller/render_test.rb +19 -0
  55. data/test/controller/request_forgery_protection_test.rb +9 -0
  56. data/test/controller/request_test.rb +33 -5
  57. data/test/controller/routing_test.rb +4 -4
  58. data/test/controller/session/cookie_store_test.rb +0 -0
  59. data/test/controller/test_test.rb +43 -1
  60. data/test/controller/url_rewriter_test.rb +34 -4
  61. data/test/fixtures/layouts/block_with_layout.erb +3 -0
  62. data/test/fixtures/layouts/partial_with_layout.erb +3 -0
  63. data/test/template/asset_tag_helper_test.rb +17 -13
  64. data/test/template/atom_feed_helper_test.rb +52 -2
  65. data/test/template/compiled_templates_test.rb +5 -1
  66. data/test/template/date_helper_test.rb +1 -1
  67. data/test/template/deprecate_ivars_test.rb +51 -0
  68. data/test/template/form_options_helper_test.rb +29 -0
  69. data/test/template/form_tag_helper_test.rb +18 -0
  70. data/test/template/number_helper_test.rb +1 -0
  71. data/test/template/text_helper_test.rb +32 -14
  72. data/test/template/url_helper_test.rb +1 -1
  73. data/test/testing_sandbox.rb +8 -4
  74. metadata +9 -4
@@ -107,7 +107,7 @@ module HTML
107
107
 
108
108
  # gauntlet
109
109
  if style !~ /^([:,;#%.\sa-zA-Z0-9!]|\w-\w|\'[\s\w]+\'|\"[\s\w]+\"|\([\d,\s]+\))*$/ ||
110
- style !~ /^(\s*[-\w]+\s*:\s*[^:;]*(;|$))*$/
110
+ style !~ /^(\s*[-\w]+\s*:\s*[^:;]*(;|$)\s*)*$/
111
111
  return ''
112
112
  end
113
113
 
@@ -170,4 +170,4 @@ module HTML
170
170
  (value =~ /(^[^\/:]*):|(&#0*58)|(&#x70)|(%|%)3A/ && !allowed_protocols.include?(value.split(protocol_separator).first))
171
171
  end
172
172
  end
173
- end
173
+ end
@@ -43,72 +43,88 @@ module ActionController #:nodoc:
43
43
  # the user is redirected to a different action. The +options+ parameter
44
44
  # is a hash consisting of the following key/value pairs:
45
45
  #
46
- # * <tt>:params</tt> - a single key or an array of keys that must
47
- # be in the <tt>params</tt> hash in order for the action(s) to be safely
48
- # called.
49
- # * <tt>:session</tt> - a single key or an array of keys that must
50
- # be in the <tt>session</tt> in order for the action(s) to be safely called.
51
- # * <tt>:flash</tt> - a single key or an array of keys that must
52
- # be in the flash in order for the action(s) to be safely called.
53
- # * <tt>:method</tt> - a single key or an array of keys--any one of which
54
- # must match the current request method in order for the action(s) to
55
- # be safely called. (The key should be a symbol: <tt>:get</tt> or
56
- # <tt>:post</tt>, for example.)
57
- # * <tt>:xhr</tt> - true/false option to ensure that the request is coming
58
- # from an Ajax call or not.
59
- # * <tt>:add_flash</tt> - a hash of name/value pairs that should be merged
60
- # into the session's flash if the prerequisites cannot be satisfied.
61
- # * <tt>:add_headers</tt> - a hash of name/value pairs that should be
62
- # merged into the response's headers hash if the prerequisites cannot
63
- # be satisfied.
64
- # * <tt>:redirect_to</tt> - the redirection parameters to be used when
65
- # redirecting if the prerequisites cannot be satisfied. You can
66
- # redirect either to named route or to the action in some controller.
67
- # * <tt>:render</tt> - the render parameters to be used when
68
- # the prerequisites cannot be satisfied.
69
- # * <tt>:only</tt> - only apply this verification to the actions specified
70
- # in the associated array (may also be a single value).
71
- # * <tt>:except</tt> - do not apply this verification to the actions
72
- # specified in the associated array (may also be a single value).
46
+ # <tt>:params</tt>::
47
+ # a single key or an array of keys that must be in the <tt>params</tt>
48
+ # hash in order for the action(s) to be safely called.
49
+ # <tt>:session</tt>::
50
+ # a single key or an array of keys that must be in the <tt>session</tt>
51
+ # in order for the action(s) to be safely called.
52
+ # <tt>:flash</tt>::
53
+ # a single key or an array of keys that must be in the flash in order
54
+ # for the action(s) to be safely called.
55
+ # <tt>:method</tt>::
56
+ # a single key or an array of keys--any one of which must match the
57
+ # current request method in order for the action(s) to be safely called.
58
+ # (The key should be a symbol: <tt>:get</tt> or <tt>:post</tt>, for
59
+ # example.)
60
+ # <tt>:xhr</tt>::
61
+ # true/false option to ensure that the request is coming from an Ajax
62
+ # call or not.
63
+ # <tt>:add_flash</tt>::
64
+ # a hash of name/value pairs that should be merged into the session's
65
+ # flash if the prerequisites cannot be satisfied.
66
+ # <tt>:add_headers</tt>::
67
+ # a hash of name/value pairs that should be merged into the response's
68
+ # headers hash if the prerequisites cannot be satisfied.
69
+ # <tt>:redirect_to</tt>::
70
+ # the redirection parameters to be used when redirecting if the
71
+ # prerequisites cannot be satisfied. You can redirect either to named
72
+ # route or to the action in some controller.
73
+ # <tt>:render</tt>::
74
+ # the render parameters to be used when the prerequisites cannot be satisfied.
75
+ # <tt>:only</tt>::
76
+ # only apply this verification to the actions specified in the associated
77
+ # array (may also be a single value).
78
+ # <tt>:except</tt>::
79
+ # do not apply this verification to the actions specified in the associated
80
+ # array (may also be a single value).
73
81
  def verify(options={})
74
- filter_opts = { :only => options[:only], :except => options[:except] }
75
- before_filter(filter_opts) do |c|
82
+ before_filter :only => options[:only], :except => options[:except] do |c|
76
83
  c.send! :verify_action, options
77
84
  end
78
85
  end
79
86
  end
80
87
 
88
+ private
89
+
81
90
  def verify_action(options) #:nodoc:
82
- prereqs_invalid =
83
- [*options[:params] ].find { |v| params[v].nil? } ||
84
- [*options[:session]].find { |v| session[v].nil? } ||
85
- [*options[:flash] ].find { |v| flash[v].nil? }
86
-
87
- if !prereqs_invalid && options[:method]
88
- prereqs_invalid ||=
89
- [*options[:method]].all? { |v| request.method != v.to_sym }
90
- end
91
-
92
- prereqs_invalid ||= (request.xhr? != options[:xhr]) unless options[:xhr].nil?
93
-
94
- if prereqs_invalid
95
- flash.update(options[:add_flash]) if options[:add_flash]
91
+ if prereqs_invalid?(options)
92
+ flash.update(options[:add_flash]) if options[:add_flash]
96
93
  response.headers.update(options[:add_headers]) if options[:add_headers]
97
-
98
- unless performed?
99
- case
100
- when options[:render]
101
- render(options[:render])
102
- when options[:redirect_to]
103
- options[:redirect_to] = self.send!(options[:redirect_to]) if options[:redirect_to].is_a?(Symbol)
104
- redirect_to(options[:redirect_to])
105
- else
106
- head(:bad_request)
107
- end
108
- end
94
+ apply_remaining_actions(options) unless performed?
95
+ end
96
+ end
97
+
98
+ def prereqs_invalid?(options) # :nodoc:
99
+ verify_presence_of_keys_in_hash_flash_or_params(options) ||
100
+ verify_method(options) ||
101
+ verify_request_xhr_status(options)
102
+ end
103
+
104
+ def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc:
105
+ [*options[:params] ].find { |v| params[v].nil? } ||
106
+ [*options[:session]].find { |v| session[v].nil? } ||
107
+ [*options[:flash] ].find { |v| flash[v].nil? }
108
+ end
109
+
110
+ def verify_method(options) # :nodoc:
111
+ [*options[:method]].all? { |v| request.method != v.to_sym } if options[:method]
112
+ end
113
+
114
+ def verify_request_xhr_status(options) # :nodoc:
115
+ request.xhr? != options[:xhr] unless options[:xhr].nil?
116
+ end
117
+
118
+ def apply_redirect_to(redirect_to_option) # :nodoc:
119
+ redirect_to_option.is_a?(Symbol) ? self.send!(redirect_to_option) : redirect_to_option
120
+ end
121
+
122
+ def apply_remaining_actions(options) # :nodoc:
123
+ case
124
+ when options[:render] ; render(options[:render])
125
+ when options[:redirect_to] ; redirect_to(apply_redirect_to(options[:redirect_to]))
126
+ else head(:bad_request)
109
127
  end
110
128
  end
111
-
112
- private :verify_action
113
129
  end
114
130
  end
@@ -2,7 +2,7 @@ module ActionPack #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 2
4
4
  MINOR = 0
5
- TINY = 2
5
+ TINY = 4
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -157,6 +157,8 @@ module ActionView #:nodoc:
157
157
  attr_reader :logger, :response, :headers
158
158
  attr_internal :cookies, :flash, :headers, :params, :request, :response, :session
159
159
 
160
+ delegate :logger, :action_name, :to => :controller
161
+
160
162
  attr_writer :template_format
161
163
 
162
164
  # Specify trim mode for the ERB compiler. Defaults to '-'.
@@ -338,11 +340,13 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
338
340
  path, partial_name = partial_pieces(options.delete(:layout))
339
341
 
340
342
  if block_given?
341
- @content_for_layout = capture(&block)
342
- concat(render(options.merge(:partial => "#{path}/#{partial_name}")), block.binding)
343
+ wrap_content_for_layout capture(&block) do
344
+ concat(render(options.merge(:partial => "#{path}/#{partial_name}")), block.binding)
345
+ end
343
346
  else
344
- @content_for_layout = render(options)
345
- render(options.merge(:partial => "#{path}/#{partial_name}"))
347
+ wrap_content_for_layout render(options) do
348
+ render(options.merge(:partial => "#{path}/#{partial_name}"))
349
+ end
346
350
  end
347
351
  elsif options[:file]
348
352
  render_file(options[:file], options[:use_full_path], options[:locals])
@@ -441,6 +445,12 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
441
445
  end
442
446
 
443
447
  private
448
+ def wrap_content_for_layout(content)
449
+ original_content_for_layout = @content_for_layout
450
+ @content_for_layout = content
451
+ returning(yield) { @content_for_layout = original_content_for_layout }
452
+ end
453
+
444
454
  def find_full_template_path(template_path, extension)
445
455
  file_name = "#{template_path}.#{extension}"
446
456
  base_path = find_base_path_for(file_name)
@@ -516,10 +526,18 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
516
526
  def template_handler_is_compilable?(handler)
517
527
  handler.new(self).respond_to?(:compile)
518
528
  end
519
-
529
+
520
530
  # Assigns instance variables from the controller to the view.
521
531
  def assign_variables_from_controller
522
- @assigns.each { |key, value| instance_variable_set("@#{key}", value) }
532
+ @assigns.each do |key, value|
533
+ if ['logger'].include?(key)
534
+ instance_variable_set("@#{key}", ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, key.to_sym))
535
+ elsif ['action_name'].include?(key)
536
+ instance_variable_set("@#{key}", ActiveSupport::Deprecation::DeprecatedInstanceVariable.new(value, key))
537
+ else
538
+ instance_variable_set("@#{key}", value)
539
+ end
540
+ end
523
541
  end
524
542
 
525
543
 
@@ -149,7 +149,7 @@ module ActionView
149
149
  options[:object_name] ||= params.first
150
150
  options[:header_message] = "#{pluralize(count, 'error')} prohibited this #{options[:object_name].to_s.gsub('_', ' ')} from being saved" unless options.include?(:header_message)
151
151
  options[:message] ||= 'There were problems with the following fields:' unless options.include?(:message)
152
- error_messages = objects.map {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) } }
152
+ error_messages = objects.sum {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) } }.join
153
153
 
154
154
  contents = ''
155
155
  contents << content_tag(options[:header_tag] || :h2, options[:header_message]) unless options[:header_message].blank?
@@ -217,7 +217,7 @@ module ActionView
217
217
  # <script type="text/javascript" src="/javascripts/cart.js"></script>
218
218
  # <script type="text/javascript" src="/javascripts/checkout.js"></script>
219
219
  #
220
- # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when ActionController::Base.perform_caching is false =>
220
+ # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when ActionController::Base.perform_caching is true =>
221
221
  # <script type="text/javascript" src="/javascripts/shop.js"></script>
222
222
  def javascript_include_tag(*sources)
223
223
  options = sources.extract_options!.stringify_keys
@@ -435,9 +435,11 @@ module ActionView
435
435
  else
436
436
  source = "/#{dir}/#{source}" unless source[0] == ?/
437
437
  if has_request
438
- source = "#{@controller.request.relative_url_root}#{source}"
438
+ unless source =~ %r{^#{@controller.request.relative_url_root}/}
439
+ source = "#{@controller.request.relative_url_root}#{source}"
440
+ end
439
441
  end
440
- rewrite_asset_path!(source)
442
+ source = rewrite_asset_path(source)
441
443
 
442
444
  if include_host
443
445
  host = compute_asset_host(source)
@@ -484,11 +486,15 @@ module ActionView
484
486
  end
485
487
  end
486
488
 
487
- # Break out the asset path rewrite so you wish to put the asset id
489
+ # Break out the asset path rewrite in case plugins wish to put the asset id
488
490
  # someplace other than the query string.
489
- def rewrite_asset_path!(source)
491
+ def rewrite_asset_path(source)
490
492
  asset_id = rails_asset_id(source)
491
- source << "?#{asset_id}" if !asset_id.blank?
493
+ if asset_id.blank?
494
+ source
495
+ else
496
+ source + "?#{asset_id}"
497
+ end
492
498
  end
493
499
 
494
500
  def javascript_src_tag(source, options)
@@ -26,7 +26,7 @@ module ActionView
26
26
  # end
27
27
  #
28
28
  # app/views/posts/index.atom.builder:
29
- # atom_feed do |feed|
29
+ # atom_feed(:tag_uri => "2008") do |feed|
30
30
  # feed.title("My great blog!")
31
31
  # feed.updated((@posts.first.created_at))
32
32
  #
@@ -44,31 +44,35 @@ module ActionView
44
44
  #
45
45
  # The options are for atom_feed are:
46
46
  #
47
+ # * <tt>:schema_date</tt>: Required. The date at which the tag scheme for the feed was first used. A good default is the year you created the feed. See http://feedvalidator.org/docs/error/InvalidTAG.html for more information.
47
48
  # * <tt>:language</tt>: Defaults to "en-US".
48
49
  # * <tt>:root_url</tt>: The HTML alternative that this feed is doubling for. Defaults to / on the current host.
49
50
  # * <tt>:url</tt>: The URL for this feed. Defaults to the current URL.
50
51
  #
51
- # atom_feed yields a AtomFeedBuilder instance.
52
+ # atom_feed yields an AtomFeedBuilder instance.
52
53
  def atom_feed(options = {}, &block)
54
+ if options[:schema_date].blank?
55
+ logger.warn("You must provide the :schema_date option to atom_feed for your feed to be valid. A good default is the year you first created this feed.") unless logger.nil?
56
+ else
57
+ options[:schema_date] = options[:schema_date].strftime("%Y-%m-%d") if options[:schema_date].respond_to?(:strftime)
58
+ end
59
+
53
60
  xml = options[:xml] || eval("xml", block.binding)
54
61
  xml.instruct!
55
62
 
56
63
  xml.feed "xml:lang" => options[:language] || "en-US", "xmlns" => 'http://www.w3.org/2005/Atom' do
57
- xml.id("tag:#{request.host}:#{request.request_uri.split(".")[0].gsub("/", "")}")
64
+ xml.id("tag:#{request.host},#{options[:schema_date]}:#{request.request_uri.split(".")[0]}")
58
65
  xml.link(:rel => 'alternate', :type => 'text/html', :href => options[:root_url] || (request.protocol + request.host_with_port))
59
-
60
- if options[:url]
61
- xml.link(:rel => 'self', :type => 'application/atom+xml', :href => options[:url] || request.url)
62
- end
63
-
64
- yield AtomFeedBuilder.new(xml, self)
66
+ xml.link(:rel => 'self', :type => 'application/atom+xml', :href => options[:url] || request.url)
67
+
68
+ yield AtomFeedBuilder.new(xml, self, options)
65
69
  end
66
70
  end
67
71
 
68
72
 
69
73
  class AtomFeedBuilder
70
- def initialize(xml, view)
71
- @xml, @view = xml, view
74
+ def initialize(xml, view, feed_options = {})
75
+ @xml, @view, @feed_options = xml, view, feed_options
72
76
  end
73
77
 
74
78
  # Accepts a Date or Time object and inserts it in the proper format. If nil is passed, current time in UTC is used.
@@ -80,12 +84,12 @@ module ActionView
80
84
  #
81
85
  # Options:
82
86
  #
83
- # * <tt>:updated</tt>: Time of update. Defaults to the created_at attribute on the record if one such exists.
84
- # * <tt>:published</tt>: Time first published. Defaults to the updated_at attribute on the record if one such exists.
87
+ # * <tt>:published</tt>: Time first published. Defaults to the created_at attribute on the record if one such exists.
88
+ # * <tt>:updated</tt>: Time of update. Defaults to the updated_at attribute on the record if one such exists.
85
89
  # * <tt>:url</tt>: The URL for this entry. Defaults to the polymorphic_url for the record.
86
90
  def entry(record, options = {})
87
91
  @xml.entry do
88
- @xml.id("tag:#{@view.request.host_with_port}:#{record.class}#{record.id}")
92
+ @xml.id("tag:#{@view.request.host},#{@feed_options[:schema_date]}:#{record.class}/#{record.id}")
89
93
 
90
94
  if options[:published] || (record.respond_to?(:created_at) && record.created_at)
91
95
  @xml.published((options[:published] || record.created_at).xmlschema)
@@ -102,10 +106,10 @@ module ActionView
102
106
  end
103
107
 
104
108
  private
105
- def method_missing(method, *arguments)
106
- @xml.__send__(method, *arguments)
109
+ def method_missing(method, *arguments, &block)
110
+ @xml.__send__(method, *arguments, &block)
107
111
  end
108
112
  end
109
113
  end
110
114
  end
111
- end
115
+ end
@@ -341,7 +341,7 @@ module ActionView
341
341
  %(<option value="#{leading_zero_on_single_digits(second)}">#{leading_zero_on_single_digits(second)}</option>\n)
342
342
  )
343
343
  end
344
- select_html(options[:field_name] || 'second', second_options, options)
344
+ select_html(options[:field_name] || 'second', second_options.join, options)
345
345
  end
346
346
  end
347
347
 
@@ -375,7 +375,7 @@ module ActionView
375
375
  %(<option value="#{leading_zero_on_single_digits(minute)}">#{leading_zero_on_single_digits(minute)}</option>\n)
376
376
  )
377
377
  end
378
- select_html(options[:field_name] || 'minute', minute_options, options)
378
+ select_html(options[:field_name] || 'minute', minute_options.join, options)
379
379
  end
380
380
  end
381
381
 
@@ -408,7 +408,7 @@ module ActionView
408
408
  %(<option value="#{leading_zero_on_single_digits(hour)}">#{leading_zero_on_single_digits(hour)}</option>\n)
409
409
  )
410
410
  end
411
- select_html(options[:field_name] || 'hour', hour_options, options)
411
+ select_html(options[:field_name] || 'hour', hour_options.join, options)
412
412
  end
413
413
  end
414
414
 
@@ -441,7 +441,7 @@ module ActionView
441
441
  %(<option value="#{day}">#{day}</option>\n)
442
442
  )
443
443
  end
444
- select_html(options[:field_name] || 'day', day_options, options)
444
+ select_html(options[:field_name] || 'day', day_options.join, options)
445
445
  end
446
446
  end
447
447
 
@@ -501,7 +501,7 @@ module ActionView
501
501
  %(<option value="#{month_number}">#{month_name}</option>\n)
502
502
  )
503
503
  end
504
- select_html(options[:field_name] || 'month', month_options, options)
504
+ select_html(options[:field_name] || 'month', month_options.join, options)
505
505
  end
506
506
  end
507
507
 
@@ -543,7 +543,7 @@ module ActionView
543
543
  %(<option value="#{year}">#{year}</option>\n)
544
544
  )
545
545
  end
546
- select_html(options[:field_name] || 'year', year_options, options)
546
+ select_html(options[:field_name] || 'year', year_options.join, options)
547
547
  end
548
548
  end
549
549
 
@@ -155,8 +155,9 @@ module ActionView
155
155
  #
156
156
  # In many cases you will want to wrap the above in another helper, so you could do something like the following:
157
157
  #
158
- # def labelled_form_for(name, object, options, &proc)
159
- # form_for(name, object, options.merge(:builder => LabellingFormBuiler), &proc)
158
+ # def labelled_form_for(record_or_name_or_array, *args, &proc)
159
+ # options = args.extract_options!
160
+ # form_for(record_or_name_or_array, *(args << options.merge(:builder => LabellingFormBuilder)), &proc)
160
161
  # end
161
162
  #
162
163
  # If you don't need to attach a form to a model instance, then check out FormTagHelper#form_tag.
@@ -131,6 +131,17 @@ module ActionView
131
131
  # to TimeZone. This may be used by users to specify a different time
132
132
  # zone model object. (See #time_zone_options_for_select for more
133
133
  # information.)
134
+ # Finally, this method supports a <tt>:default</tt> option, which selects
135
+ # a default TimeZone if the object's time zone is nil.
136
+ #
137
+ # Examples:
138
+ # time_zone_select( "user", "time_zone", nil, :include_blank => true)
139
+ #
140
+ # time_zone_select( "user", "time_zone", nil, :default => "Pacific Time (US & Canada)" )
141
+ #
142
+ # time_zone_select( "user", 'time_zone', TimeZone.us_zones, :default => "Pacific Time (US & Canada)")
143
+ #
144
+ # time_zone_select( "user", "time_zone", TZInfo::Timezone.all.sort, :model => TZInfo::Timezone)
134
145
  def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
135
146
  InstanceTag.new(object, method, self, nil, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options)
136
147
  end
@@ -385,7 +396,7 @@ module ActionView
385
396
  value = value(object)
386
397
  content_tag("select",
387
398
  add_options(
388
- time_zone_options_for_select(value, priority_zones, options[:model] || TimeZone),
399
+ time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || TimeZone),
389
400
  options, value
390
401
  ), html_options
391
402
  )