actionpack 3.0.0.beta3 → 3.0.0.beta4

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 (83) hide show
  1. data/CHANGELOG +19 -0
  2. data/lib/abstract_controller.rb +1 -1
  3. data/lib/abstract_controller/asset_paths.rb +9 -0
  4. data/lib/abstract_controller/base.rb +5 -13
  5. data/lib/abstract_controller/callbacks.rb +1 -1
  6. data/lib/abstract_controller/helpers.rb +0 -1
  7. data/lib/abstract_controller/layouts.rb +3 -3
  8. data/lib/abstract_controller/logger.rb +1 -1
  9. data/lib/abstract_controller/rendering.rb +1 -0
  10. data/lib/action_controller/base.rb +5 -1
  11. data/lib/action_controller/caching.rb +2 -3
  12. data/lib/action_controller/caching/actions.rb +1 -1
  13. data/lib/action_controller/caching/fragments.rb +1 -1
  14. data/lib/action_controller/caching/pages.rb +8 -8
  15. data/lib/action_controller/caching/sweeping.rb +1 -0
  16. data/lib/action_controller/deprecated/base.rb +10 -36
  17. data/lib/action_controller/metal.rb +45 -3
  18. data/lib/action_controller/metal/compatibility.rb +2 -2
  19. data/lib/action_controller/metal/helpers.rb +3 -3
  20. data/lib/action_controller/metal/http_authentication.rb +158 -0
  21. data/lib/action_controller/metal/instrumentation.rb +5 -5
  22. data/lib/action_controller/metal/rack_delegation.rb +4 -4
  23. data/lib/action_controller/metal/renderers.rb +3 -3
  24. data/lib/action_controller/metal/request_forgery_protection.rb +45 -74
  25. data/lib/action_controller/metal/responder.rb +1 -1
  26. data/lib/action_controller/metal/url_for.rb +8 -0
  27. data/lib/action_controller/railtie.rb +26 -39
  28. data/lib/action_controller/test_case.rb +147 -135
  29. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +1 -0
  30. data/lib/action_dispatch.rb +0 -1
  31. data/lib/action_dispatch/http/parameters.rb +2 -1
  32. data/lib/action_dispatch/http/request.rb +19 -7
  33. data/lib/action_dispatch/http/response.rb +3 -33
  34. data/lib/action_dispatch/middleware/cookies.rb +44 -10
  35. data/lib/action_dispatch/middleware/flash.rb +11 -1
  36. data/lib/action_dispatch/middleware/params_parser.rb +3 -1
  37. data/lib/action_dispatch/middleware/session/abstract_store.rb +47 -83
  38. data/lib/action_dispatch/middleware/session/cookie_store.rb +19 -165
  39. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -2
  40. data/lib/action_dispatch/middleware/show_exceptions.rb +18 -12
  41. data/lib/action_dispatch/middleware/stack.rb +17 -67
  42. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +1 -1
  43. data/lib/action_dispatch/railtie.rb +0 -2
  44. data/lib/action_dispatch/routing/deprecated_mapper.rb +1 -0
  45. data/lib/action_dispatch/routing/mapper.rb +89 -23
  46. data/lib/action_dispatch/routing/route_set.rb +22 -16
  47. data/lib/action_dispatch/routing/url_for.rb +1 -1
  48. data/lib/action_dispatch/testing/assertions/routing.rb +1 -0
  49. data/lib/action_dispatch/testing/assertions/selector.rb +11 -7
  50. data/lib/action_dispatch/testing/test_process.rb +3 -2
  51. data/lib/action_pack/version.rb +1 -1
  52. data/lib/action_view.rb +5 -1
  53. data/lib/action_view/base.rb +10 -4
  54. data/lib/action_view/helpers/active_model_helper.rb +1 -8
  55. data/lib/action_view/helpers/asset_tag_helper.rb +7 -4
  56. data/lib/action_view/helpers/cache_helper.rb +14 -14
  57. data/lib/action_view/helpers/capture_helper.rb +25 -6
  58. data/lib/action_view/helpers/date_helper.rb +33 -44
  59. data/lib/action_view/helpers/form_helper.rb +47 -27
  60. data/lib/action_view/helpers/form_options_helper.rb +26 -3
  61. data/lib/action_view/helpers/form_tag_helper.rb +8 -4
  62. data/lib/action_view/helpers/number_helper.rb +5 -2
  63. data/lib/action_view/helpers/prototype_helper.rb +1 -1
  64. data/lib/action_view/helpers/tag_helper.rb +1 -1
  65. data/lib/action_view/helpers/text_helper.rb +55 -46
  66. data/lib/action_view/helpers/translation_helper.rb +19 -8
  67. data/lib/action_view/helpers/url_helper.rb +2 -4
  68. data/lib/action_view/locale/en.yml +14 -14
  69. data/lib/action_view/lookup_context.rb +52 -22
  70. data/lib/action_view/paths.rb +1 -0
  71. data/lib/action_view/render/layouts.rb +3 -12
  72. data/lib/action_view/render/partials.rb +21 -10
  73. data/lib/action_view/render/rendering.rb +1 -1
  74. data/lib/action_view/template.rb +172 -26
  75. data/lib/action_view/template/error.rb +25 -27
  76. data/lib/action_view/template/handlers.rb +1 -1
  77. data/lib/action_view/template/handlers/erb.rb +92 -45
  78. data/lib/action_view/template/resolver.rb +4 -1
  79. data/lib/action_view/test_case.rb +105 -72
  80. data/lib/action_view/testing/resolvers.rb +43 -0
  81. metadata +62 -20
  82. data/lib/abstract_controller/assigns.rb +0 -21
  83. data/lib/action_dispatch/middleware/cascade.rb +0 -29
@@ -1,20 +1,18 @@
1
1
  require 'rack/mount'
2
2
  require 'forwardable'
3
+ require 'active_support/core_ext/object/to_query'
3
4
  require 'action_dispatch/routing/deprecated_mapper'
4
5
 
5
6
  module ActionDispatch
6
7
  module Routing
7
8
  class RouteSet #:nodoc:
8
- NotFound = lambda { |env|
9
- raise ActionController::RoutingError, "No route matches #{env['PATH_INFO'].inspect}"
10
- }
11
-
12
9
  PARAMETERS_KEY = 'action_dispatch.request.path_parameters'
13
10
 
14
11
  class Dispatcher #:nodoc:
15
12
  def initialize(options={})
16
13
  @defaults = options[:defaults]
17
14
  @glob_param = options.delete(:glob)
15
+ @controllers = {}
18
16
  end
19
17
 
20
18
  def call(env)
@@ -32,19 +30,18 @@ module ActionDispatch
32
30
  def prepare_params!(params)
33
31
  merge_default_action!(params)
34
32
  split_glob_param!(params) if @glob_param
35
-
36
- params.each do |key, value|
37
- if value.is_a?(String)
38
- value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
39
- params[key] = URI.unescape(value)
40
- end
41
- end
42
33
  end
43
34
 
44
35
  def controller(params, raise_error=true)
45
- if params && params.has_key?(:controller)
46
- controller = "#{params[:controller].camelize}Controller"
47
- ActiveSupport::Inflector.constantize(controller)
36
+ if params && params.key?(:controller)
37
+ controller_param = params[:controller]
38
+ unless controller = @controllers[controller_param]
39
+ controller_name = "#{controller_param.camelize}Controller"
40
+ controller = @controllers[controller_param] =
41
+ ActiveSupport::Dependencies.ref(controller_name)
42
+ end
43
+
44
+ controller.get
48
45
  end
49
46
  rescue NameError => e
50
47
  raise ActionController::RoutingError, e.message, e.backtrace if raise_error
@@ -71,6 +68,10 @@ module ActionDispatch
71
68
  clear!
72
69
  end
73
70
 
71
+ def helper_names
72
+ self.module.instance_methods.map(&:to_s)
73
+ end
74
+
74
75
  def clear!
75
76
  @routes = {}
76
77
  @helpers = []
@@ -179,7 +180,6 @@ module ActionDispatch
179
180
 
180
181
  url_for(options)
181
182
  end
182
- protected :#{selector}
183
183
  END_EVAL
184
184
  helpers << selector
185
185
  end
@@ -223,7 +223,6 @@ module ActionDispatch
223
223
  def finalize!
224
224
  return if @finalized
225
225
  @finalized = true
226
- @set.add_route(NotFound)
227
226
  @set.freeze
228
227
  end
229
228
 
@@ -470,6 +469,13 @@ module ActionDispatch
470
469
 
471
470
  req = Rack::Request.new(env)
472
471
  @set.recognize(req) do |route, matches, params|
472
+ params.each do |key, value|
473
+ if value.is_a?(String)
474
+ value = value.dup.force_encoding(Encoding::BINARY) if value.encoding_aware?
475
+ params[key] = URI.unescape(value)
476
+ end
477
+ end
478
+
473
479
  dispatcher = route.app
474
480
  if dispatcher.is_a?(Dispatcher) && dispatcher.controller(params, false)
475
481
  dispatcher.prepare_params!(params)
@@ -128,7 +128,7 @@ module ActionDispatch
128
128
  when String
129
129
  options
130
130
  when nil, Hash
131
- _router.url_for(url_options.merge(options || {}))
131
+ _router.url_for(url_options.merge((options || {}).symbolize_keys))
132
132
  else
133
133
  polymorphic_url(options)
134
134
  end
@@ -1,4 +1,5 @@
1
1
  require 'active_support/core_ext/hash/diff'
2
+ require 'active_support/core_ext/hash/indifferent_access'
2
3
 
3
4
  module ActionDispatch
4
5
  module Assertions
@@ -267,14 +267,12 @@ module ActionDispatch
267
267
  if match_with = equals[:text]
268
268
  matches.delete_if do |match|
269
269
  text = ""
270
- text.force_encoding(match_with.encoding) if text.respond_to?(:force_encoding)
271
270
  stack = match.children.reverse
272
271
  while node = stack.pop
273
272
  if node.tag?
274
273
  stack.concat node.children.reverse
275
274
  else
276
275
  content = node.content
277
- content.force_encoding(match_with.encoding) if content.respond_to?(:force_encoding)
278
276
  text << content
279
277
  end
280
278
  end
@@ -298,10 +296,14 @@ module ActionDispatch
298
296
  # found one but expecting two.
299
297
  message ||= content_mismatch if matches.empty?
300
298
  # Test minimum/maximum occurrence.
301
- min, max = equals[:minimum], equals[:maximum]
302
- message = message || %(Expected #{count_description(min, max)} matching "#{selector.to_s}", found #{matches.size}.)
303
- assert matches.size >= min, message if min
304
- assert matches.size <= max, message if max
299
+ min, max, count = equals[:minimum], equals[:maximum], equals[:count]
300
+ message = message || %(Expected #{count_description(min, max, count)} matching "#{selector.to_s}", found #{matches.size}.)
301
+ if count
302
+ assert matches.size == count, message
303
+ else
304
+ assert matches.size >= min, message if min
305
+ assert matches.size <= max, message if max
306
+ end
305
307
 
306
308
  # If a block is given call that block. Set @selected to allow
307
309
  # nested assert_select, which can be nested several levels deep.
@@ -318,11 +320,13 @@ module ActionDispatch
318
320
  matches
319
321
  end
320
322
 
321
- def count_description(min, max) #:nodoc:
323
+ def count_description(min, max, count) #:nodoc:
322
324
  pluralize = lambda {|word, quantity| word << (quantity == 1 ? '' : 's')}
323
325
 
324
326
  if min && max && (max != min)
325
327
  "between #{min} and #{max} elements"
328
+ elsif min && max && max == min && count
329
+ "exactly #{count} #{pluralize['element', min]}"
326
330
  elsif min && !(min == 1 && max == 1)
327
331
  "at least #{min} #{pluralize['element', min]}"
328
332
  elsif max
@@ -1,15 +1,16 @@
1
1
  require 'action_dispatch/middleware/flash'
2
+ require 'active_support/core_ext/hash/indifferent_access'
2
3
 
3
4
  module ActionDispatch
4
5
  module TestProcess
5
6
  def assigns(key = nil)
6
- assigns = {}
7
+ assigns = {}.with_indifferent_access
7
8
  @controller.instance_variable_names.each do |ivar|
8
9
  next if ActionController::Base.protected_instance_variables.include?(ivar)
9
10
  assigns[ivar[1..-1]] = @controller.instance_variable_get(ivar)
10
11
  end
11
12
 
12
- key.nil? ? assigns : assigns[key.to_s]
13
+ key.nil? ? assigns : assigns[key]
13
14
  end
14
15
 
15
16
  def session
@@ -3,7 +3,7 @@ module ActionPack
3
3
  MAJOR = 3
4
4
  MINOR = 0
5
5
  TINY = 0
6
- BUILD = "beta3"
6
+ BUILD = "beta4"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
9
9
  end
data/lib/action_view.rb CHANGED
@@ -51,13 +51,17 @@ module ActionView
51
51
 
52
52
  autoload :MissingTemplate, 'action_view/template/error'
53
53
  autoload :ActionViewError, 'action_view/template/error'
54
- autoload :TemplateError, 'action_view/template/error'
54
+ autoload :EncodingError, 'action_view/template/error'
55
+ autoload :TemplateError, 'action_view/template/error'
56
+ autoload :WrongEncodingError, 'action_view/template/error'
55
57
 
56
58
  autoload :TemplateHandler, 'action_view/template'
57
59
  autoload :TemplateHandlers, 'action_view/template'
58
60
  end
59
61
 
60
62
  autoload :TestCase, 'action_view/test_case'
63
+
64
+ ENCODING_FLAG = '#.*coding[:=]\s*(\S+)[ \t]*'
61
65
  end
62
66
 
63
67
  require 'active_support/i18n'
@@ -165,6 +165,10 @@ module ActionView #:nodoc:
165
165
  cattr_accessor :debug_rjs
166
166
  @@debug_rjs = false
167
167
 
168
+ # Specify the proc used to decorate input tags that refer to attributes with errors.
169
+ cattr_accessor :field_error_proc
170
+ @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe }
171
+
168
172
  class_attribute :helpers
169
173
  remove_method :helpers
170
174
  attr_reader :helpers
@@ -176,13 +180,11 @@ module ActionView #:nodoc:
176
180
  delegate :logger, :to => 'ActionController::Base', :allow_nil => true
177
181
  end
178
182
 
179
- ActiveSupport.run_load_hooks(:action_view, self)
180
-
181
183
  attr_accessor :base_path, :assigns, :template_extension, :lookup_context
182
184
  attr_internal :captures, :request, :controller, :template, :config
183
185
 
184
186
  delegate :find_template, :template_exists?, :formats, :formats=, :locale, :locale=,
185
- :view_paths, :view_paths=, :with_fallbacks, :update_details, :to => :lookup_context
187
+ :view_paths, :view_paths=, :with_fallbacks, :update_details, :with_layout_format, :to => :lookup_context
186
188
 
187
189
  delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers,
188
190
  :flash, :action_name, :controller_name, :to => :controller
@@ -199,11 +201,12 @@ module ActionView #:nodoc:
199
201
  end
200
202
 
201
203
  def self.process_view_paths(value)
204
+ return value.dup if value.is_a?(PathSet)
202
205
  ActionView::PathSet.new(Array.wrap(value))
203
206
  end
204
207
 
205
208
  def initialize(lookup_context = nil, assigns_for_first_render = {}, controller = nil, formats = nil) #:nodoc:
206
- @config = nil
209
+ @config = nil
207
210
  @assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) }
208
211
  @helpers = self.class.helpers || Module.new
209
212
 
@@ -214,6 +217,7 @@ module ActionView #:nodoc:
214
217
  @_config = ActiveSupport::InheritableOptions.new(controller.config) if controller && controller.respond_to?(:config)
215
218
  @_content_for = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
216
219
  @_virtual_path = nil
220
+ @output_buffer = nil
217
221
 
218
222
  @lookup_context = lookup_context.is_a?(ActionView::LookupContext) ?
219
223
  lookup_context : ActionView::LookupContext.new(lookup_context)
@@ -229,5 +233,7 @@ module ActionView #:nodoc:
229
233
  response.body_parts << part
230
234
  nil
231
235
  end
236
+
237
+ ActiveSupport.run_load_hooks(:action_view, self)
232
238
  end
233
239
  end
@@ -4,13 +4,6 @@ require 'active_support/core_ext/enumerable'
4
4
  require 'active_support/core_ext/object/blank'
5
5
 
6
6
  module ActionView
7
- ActiveSupport.on_load(:action_view) do
8
- class ActionView::Base
9
- @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe }
10
- cattr_accessor :field_error_proc
11
- end
12
- end
13
-
14
7
  module Helpers
15
8
  module ActiveModelHelper
16
9
  %w(input form error_messages_for error_message_on).each do |method|
@@ -43,7 +36,7 @@ module ActionView
43
36
  end
44
37
 
45
38
  %w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth|
46
- module_eval "def #{meth}(*) error_wrapping(super) end"
39
+ module_eval "def #{meth}(*) error_wrapping(super) end", __FILE__, __LINE__
47
40
  end
48
41
 
49
42
  def error_wrapping(html_tag)
@@ -62,9 +62,9 @@ module ActionView
62
62
  # "http://assets#{source.hash % 2 + 1}.example.com"
63
63
  # }
64
64
  # image_tag("rails.png")
65
- # # => <img alt="Rails" src="http://assets0.example.com/images/rails.png?1230601161" />
65
+ # # => <img alt="Rails" src="http://assets1.example.com/images/rails.png?1230601161" />
66
66
  # stylesheet_link_tag("application")
67
- # # => <link href="http://assets1.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
67
+ # # => <link href="http://assets2.example.com/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
68
68
  #
69
69
  # The example above generates "http://assets1.example.com" and
70
70
  # "http://assets2.example.com". This option is useful for example if
@@ -620,7 +620,10 @@ module ActionView
620
620
  options.symbolize_keys!
621
621
 
622
622
  src = options[:src] = path_to_image(source)
623
- options[:alt] ||= File.basename(src, '.*').capitalize
623
+
624
+ unless src =~ /^cid:/
625
+ options[:alt] = options.fetch(:alt){ File.basename(src, '.*').capitalize }
626
+ end
624
627
 
625
628
  if size = options.delete(:size)
626
629
  options[:width], options[:height] = size.split("x") if size =~ %r{^\d+x\d+$}
@@ -754,7 +757,7 @@ module ActionView
754
757
  end
755
758
 
756
759
  def is_uri?(path)
757
- path =~ %r{^[-a-z]+://}
760
+ path =~ %r{^[-a-z]+://|^cid:}
758
761
  end
759
762
 
760
763
  # Pick an asset host for this source. Returns +nil+ if no host is set,
@@ -32,27 +32,27 @@ module ActionView
32
32
  # <i>Topics listed alphabetically</i>
33
33
  # <% end %>
34
34
  def cache(name = {}, options = nil, &block)
35
- safe_concat fragment_for(name, options, &block)
35
+ if controller.perform_caching
36
+ safe_concat(fragment_for(name, options, &block))
37
+ else
38
+ yield
39
+ end
40
+
36
41
  nil
37
42
  end
38
43
 
39
44
  private
40
45
  # TODO: Create an object that has caching read/write on it
41
46
  def fragment_for(name = {}, options = nil, &block) #:nodoc:
42
- if controller.perform_caching
43
- if controller.fragment_exist?(name, options)
44
- controller.read_fragment(name, options)
45
- else
46
- # VIEW TODO: Make #capture usable outside of ERB
47
- # This dance is needed because Builder can't use capture
48
- pos = output_buffer.length
49
- yield
50
- fragment = output_buffer.slice!(pos..-1)
51
- controller.write_fragment(name, fragment, options)
52
- end
47
+ if controller.fragment_exist?(name, options)
48
+ controller.read_fragment(name, options)
53
49
  else
54
- ret = yield
55
- ActiveSupport::SafeBuffer.new(ret) if ret.is_a?(String)
50
+ # VIEW TODO: Make #capture usable outside of ERB
51
+ # This dance is needed because Builder can't use capture
52
+ pos = output_buffer.length
53
+ yield
54
+ fragment = output_buffer.slice!(pos..-1)
55
+ controller.write_fragment(name, fragment, options)
56
56
  end
57
57
  end
58
58
  end
@@ -41,8 +41,11 @@ module ActionView
41
41
  end
42
42
 
43
43
  # Calling content_for stores a block of markup in an identifier for later use.
44
- # You can make subsequent calls to the stored content in other templates or the layout
45
- # by passing the identifier as an argument to <tt>yield</tt>.
44
+ # You can make subsequent calls to the stored content in other templates, helper modules
45
+ # or the layout by passing the identifier as an argument to <tt>content_for</tt>.
46
+ #
47
+ # Note: <tt>yield</tt> can still be used to retrieve the stored content, but calling
48
+ # <tt>yield</tt> doesn't work in helper modules, while <tt>content_for</tt> does.
46
49
  #
47
50
  # ==== Examples
48
51
  #
@@ -50,11 +53,27 @@ module ActionView
50
53
  # alert('You are not authorized to do that!')
51
54
  # <% end %>
52
55
  #
53
- # You can then use <tt>yield :not_authorized</tt> anywhere in your templates.
56
+ # You can then use <tt>content_for :not_authorized</tt> anywhere in your templates.
57
+ #
58
+ # <%= content_for :not_authorized if current_user.nil? %>
59
+ #
60
+ # This is equivalent to:
54
61
  #
55
62
  # <%= yield :not_authorized if current_user.nil? %>
56
63
  #
57
- # You can also use this syntax alongside an existing call to <tt>yield</tt> in a layout. For example:
64
+ # <tt>content_for</tt>, however, can also be used in helper modules.
65
+ #
66
+ # module StorageHelper
67
+ # def stored_content
68
+ # content_for(:storage) || "Your storage is empty"
69
+ # end
70
+ # end
71
+ #
72
+ # This helper works just like normal helpers.
73
+ #
74
+ # <%= stored_content %>
75
+ #
76
+ # You can use the <tt>yield</tt> syntax alongside an existing call to <tt>yield</tt> in a layout. For example:
58
77
  #
59
78
  # <%# This is the layout %>
60
79
  # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
@@ -67,7 +86,7 @@ module ActionView
67
86
  # </body>
68
87
  # </html>
69
88
  #
70
- # And now, we'll create a view that has a content_for call that
89
+ # And now, we'll create a view that has a <tt>content_for</tt> call that
71
90
  # creates the <tt>script</tt> identifier.
72
91
  #
73
92
  # <%# This is our view %>
@@ -103,7 +122,7 @@ module ActionView
103
122
  #
104
123
  # Then, in another template or layout, this code would render both links in order:
105
124
  #
106
- # <ul><%= yield :navigation %></ul>
125
+ # <ul><%= content_for :navigation %></ul>
107
126
  #
108
127
  # Lastly, simple content can be passed as a parameter:
109
128
  #
@@ -589,56 +589,50 @@ module ActionView
589
589
  @options = options.dup
590
590
  @html_options = html_options.dup
591
591
  @datetime = datetime
592
+ @options[:datetime_separator] ||= ' &mdash; '
593
+ @options[:time_separator] ||= ' : '
592
594
  end
593
595
 
594
596
  def select_datetime
595
- # TODO: Remove tag conditional
596
- # Ideally we could just join select_date and select_date for the tag case
597
+ order = date_order.dup
598
+ order -= [:hour, :minute, :second]
599
+ @options[:discard_year] ||= true unless order.include?(:year)
600
+ @options[:discard_month] ||= true unless order.include?(:month)
601
+ @options[:discard_day] ||= true if @options[:discard_month] || !order.include?(:day)
602
+ @options[:discard_minute] ||= true if @options[:discard_hour]
603
+ @options[:discard_second] ||= true unless @options[:include_seconds] && !@options[:discard_minute]
604
+
605
+ # If the day is hidden and the month is visible, the day should be set to the 1st so all month choices are
606
+ # valid (otherwise it could be 31 and february wouldn't be a valid date)
607
+ if @datetime && @options[:discard_day] && !@options[:discard_month]
608
+ @datetime = @datetime.change(:day => 1)
609
+ end
610
+
597
611
  if @options[:tag] && @options[:ignore_date]
598
612
  select_time
599
- elsif @options[:tag]
600
- order = date_order.dup
601
- order -= [:hour, :minute, :second]
602
-
603
- @options[:discard_year] ||= true unless order.include?(:year)
604
- @options[:discard_month] ||= true unless order.include?(:month)
605
- @options[:discard_day] ||= true if @options[:discard_month] || !order.include?(:day)
606
- @options[:discard_minute] ||= true if @options[:discard_hour]
607
- @options[:discard_second] ||= true unless @options[:include_seconds] && !@options[:discard_minute]
608
-
609
- # If the day is hidden and the month is visible, the day should be set to the 1st so all month choices are
610
- # valid (otherwise it could be 31 and february wouldn't be a valid date)
611
- if @datetime && @options[:discard_day] && !@options[:discard_month]
612
- @datetime = @datetime.change(:day => 1)
613
- end
614
-
613
+ else
615
614
  [:day, :month, :year].each { |o| order.unshift(o) unless order.include?(o) }
616
615
  order += [:hour, :minute, :second] unless @options[:discard_hour]
617
616
 
618
617
  build_selects_from_types(order)
619
- else
620
- "#{select_date}#{@options[:datetime_separator]}#{select_time}".html_safe
621
618
  end
622
619
  end
623
620
 
624
621
  def select_date
625
622
  order = date_order.dup
626
623
 
627
- # TODO: Remove tag conditional
628
- if @options[:tag]
629
- @options[:discard_hour] = true
630
- @options[:discard_minute] = true
631
- @options[:discard_second] = true
624
+ @options[:discard_hour] = true
625
+ @options[:discard_minute] = true
626
+ @options[:discard_second] = true
632
627
 
633
- @options[:discard_year] ||= true unless order.include?(:year)
634
- @options[:discard_month] ||= true unless order.include?(:month)
635
- @options[:discard_day] ||= true if @options[:discard_month] || !order.include?(:day)
628
+ @options[:discard_year] ||= true unless order.include?(:year)
629
+ @options[:discard_month] ||= true unless order.include?(:month)
630
+ @options[:discard_day] ||= true if @options[:discard_month] || !order.include?(:day)
636
631
 
637
- # If the day is hidden and the month is visible, the day should be set to the 1st so all month choices are
638
- # valid (otherwise it could be 31 and february wouldn't be a valid date)
639
- if @datetime && @options[:discard_day] && !@options[:discard_month]
640
- @datetime = @datetime.change(:day => 1)
641
- end
632
+ # If the day is hidden and the month is visible, the day should be set to the 1st so all month choices are
633
+ # valid (otherwise it could be 31 and february wouldn't be a valid date)
634
+ if @datetime && @options[:discard_day] && !@options[:discard_month]
635
+ @datetime = @datetime.change(:day => 1)
642
636
  end
643
637
 
644
638
  [:day, :month, :year].each { |o| order.unshift(o) unless order.include?(o) }
@@ -649,15 +643,12 @@ module ActionView
649
643
  def select_time
650
644
  order = []
651
645
 
652
- # TODO: Remove tag conditional
653
- if @options[:tag]
654
- @options[:discard_month] = true
655
- @options[:discard_year] = true
656
- @options[:discard_day] = true
657
- @options[:discard_second] ||= true unless @options[:include_seconds]
646
+ @options[:discard_month] = true
647
+ @options[:discard_year] = true
648
+ @options[:discard_day] = true
649
+ @options[:discard_second] ||= true unless @options[:include_seconds]
658
650
 
659
- order += [:year, :month, :day] unless @options[:ignore_date]
660
- end
651
+ order += [:year, :month, :day] unless @options[:ignore_date]
661
652
 
662
653
  order += [:hour, :minute]
663
654
  order << :second if @options[:include_seconds]
@@ -937,10 +928,8 @@ module ActionView
937
928
  options[:include_position] = true
938
929
  options[:prefix] ||= @object_name
939
930
  options[:index] = @auto_index if @auto_index && !options.has_key?(:index)
940
- options[:datetime_separator] ||= ' &mdash; '
941
- options[:time_separator] ||= ' : '
942
931
 
943
- DateTimeSelector.new(datetime, options.merge(:tag => true), html_options)
932
+ DateTimeSelector.new(datetime, options, html_options)
944
933
  end
945
934
 
946
935
  def default_datetime(options)