actionpack 3.2.12 → 3.2.13.rc1

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e83232f34b035dc51f73f35c3c8a211ab7622da9
4
- data.tar.gz: 737b807d052385bc722299eeac6a5301135d9a63
3
+ metadata.gz: f6c4864b6c426b8e73b7cffc095f321d692cc8ed
4
+ data.tar.gz: 94688471dd5a5d2df2693fc1e1ffb81b29ea4a89
5
5
  SHA512:
6
- metadata.gz: a28a6df33af3317e3087fa874617081b54f0758abd9545bf743011e68f178e7c4e023162d06ea3be4462071a36459b1a1d4f33a354828ebcb76c8c069b7dec08
7
- data.tar.gz: 82efdd6a5ed47e9a39e1303ce3b026f4856236da3421970e124bc74dbb2cd9ef4ef6d2b662d919f28351fa0585abe0a289f183399d836c5721cef07bf22daf15
6
+ metadata.gz: e05cfe1775d8c3613b9b530a6062312fedf90d2a92dd3447f4829c6b0b3693fc99dbeb4d1afaef2accd451f792ec31cb5b472184d3b73908b6d2d1e16e653e18
7
+ data.tar.gz: a02fa3528e3c996cb07b0a9668e72848b914ade04d9fca43ca0bc657994345e2794baab8af346b48eae7c08f8fa26a36a71fd04e843ac745ffbe28a41818be0d
@@ -1,8 +1,163 @@
1
- ## Rails 3.2.11 ##
1
+ ## unreleased ##
2
2
 
3
- * Strip nils from collections on JSON and XML posts. [CVE-2013-0155]
3
+ * No changes.
4
+
5
+
6
+ ## Rails 3.2.13 (Feb 17, 2013) ##
7
+
8
+ * Determine the controller#action from only the matched path when using the
9
+ shorthand syntax. Previously the complete path was used, which led
10
+ to problems with nesting (scopes and namespaces).
11
+ Fixes #7554.
12
+ Backport #9361.
13
+
14
+ Example:
15
+
16
+ # this will route to questions#new
17
+ scope ':locale' do
18
+ get 'questions/new'
19
+ end
20
+
21
+ *Yves Senn*
22
+
23
+ * Fix `assert_template` with `render :stream => true`.
24
+ Fix #1743.
25
+ Backport #5288.
26
+
27
+ *Sergey Nartimov*
28
+
29
+ * Eagerly populate the http method loookup cache so local project inflections do
30
+ not interfere with use of underscore method ( and we don't need locks )
31
+
32
+ *Aditya Sanghi*
33
+
34
+ * `BestStandardsSupport` no longer duplicates `X-UA-Compatible` values on
35
+ each request to prevent header size from blowing up.
36
+
37
+ *Edward Anderson*
38
+
39
+ * Fixed JSON params parsing regression for non-object JSON content.
40
+
41
+ *Dylan Smith*
42
+
43
+ * Prevent unnecessary asset compilation when using `javascript_include_tag` on
44
+ files with non-standard extensions.
45
+
46
+ *Noah Silas*
47
+
48
+ * Fixes issue where duplicate assets can be required with sprockets.
49
+
50
+ *Jeremy Jackson*
51
+
52
+ * Bump `rack` dependency to 1.4.3, eliminate `Rack::File` headers deprecation warning.
53
+
54
+ *Sam Ruby + Carlos Antonio da Silva*
55
+
56
+ * Do not append second slash to `root_url` when using `trailing_slash: true`
57
+
58
+ Fix #8700.
59
+ Backport #8701.
60
+
61
+ Example:
62
+ # before
63
+ root_url # => http://test.host//
64
+
65
+ # after
66
+ root_url # => http://test.host/
67
+
68
+ *Yves Senn*
69
+
70
+ * Fix a bug in `content_tag_for` that prevents it for work without a block.
71
+
72
+ *Jasl*
73
+
74
+ * Clear url helper methods when routes are reloaded by removing the methods
75
+ explicitly rather than just clearing the module because it didn't work
76
+ properly and could be the source of a memory leak.
77
+
78
+ *Andrew White*
79
+
80
+ * Fix a bug in `ActionDispatch::Request#raw_post` that caused `env['rack.input']`
81
+ to be read but not rewound.
82
+
83
+ *Matt Venables*
84
+
85
+ * More descriptive error messages when calling `render :partial` with
86
+ an invalid `:layout` argument.
87
+
88
+ Fixes #8376.
89
+
90
+ render :partial => 'partial', :layout => true
91
+ # results in ActionView::MissingTemplate: Missing partial /true
92
+
93
+ *Yves Senn*
94
+
95
+ * Accept symbols as `#send_data` :disposition value. [Backport #8329] *Elia Schito*
96
+
97
+ * Add i18n scope to `distance_of_time_in_words`. [Backport #7997] *Steve Klabnik*
98
+
99
+ * Fix side effect of `url_for` changing the `:controller` string option. [Backport #6003]
100
+ Before:
101
+
102
+ controller = '/projects'
103
+ url_for :controller => controller, :action => 'status'
104
+
105
+ puts controller #=> 'projects'
106
+
107
+ After
108
+
109
+ puts controller #=> '/projects'
110
+
111
+ *Nikita Beloglazov + Andrew White*
112
+
113
+ * Introduce `ActionView::Template::Handlers::ERB.escape_whitelist`. This is a list
114
+ of mime types where template text is not html escaped by default. It prevents `Jack & Joe`
115
+ from rendering as `Jack & Joe` for the whitelisted mime types. The default whitelist
116
+ contains text/plain. Fix #7976 [Backport #8235]
117
+
118
+ *Joost Baaij*
119
+
120
+ * `BestStandardsSupport` middleware now appends it's `X-UA-Compatible` value to app's
121
+ returned value if any. Fix #8086 [Backport #8093]
122
+
123
+ *Nikita Afanasenko*
124
+
125
+ * prevent double slashes in engine urls when `Rails.application.default_url_options[:trailing_slash] = true` is set
126
+ Fix #7842
127
+
128
+ *Yves Senn*
129
+
130
+ * Fix input name when `:multiple => true` and `:index` are set.
131
+
132
+ Before:
133
+
134
+ check_box("post", "comment_ids", { :multiple => true, :index => "foo" }, 1)
135
+ #=> <input name=\"post[foo][comment_ids]\" type=\"hidden\" value=\"0\" /><input id=\"post_foo_comment_ids_1\" name=\"post[foo][comment_ids]\" type=\"checkbox\" value=\"1\" />
136
+
137
+ After:
138
+
139
+ check_box("post", "comment_ids", { :multiple => true, :index => "foo" }, 1)
140
+ #=> <input name=\"post[foo][comment_ids][]\" type=\"hidden\" value=\"0\" /><input id=\"post_foo_comment_ids_1\" name=\"post[foo][comment_ids][]\" type=\"checkbox\" value=\"1\" />
141
+
142
+ Fix #8108
143
+
144
+ *Daniel Fox, Grant Hutchins & Trace Wax*
145
+
146
+
147
+ ## Rails 3.2.12 (Feb 11, 2013) ##
148
+
149
+ * No changes.
150
+
151
+
152
+ ## Rails 3.2.11 (Jan 8, 2013) ##
153
+
154
+ * Strip nils from collections on JSON and XML posts. [CVE-2013-0155]
155
+
156
+
157
+ ## Rails 3.2.10 (Jan 2, 2013) ##
158
+
159
+ * No changes.
4
160
 
5
- ## Rails 3.2.10 ##
6
161
 
7
162
  ## Rails 3.2.9 (Nov 12, 2012) ##
8
163
 
@@ -58,7 +58,8 @@ module ActionController
58
58
  end
59
59
 
60
60
  def method_for_action(action_name)
61
- super || (respond_to?(:method_missing) && "_handle_method_missing")
61
+ super || ((self.class.public_method_defined?(:method_missing) ||
62
+ self.class.protected_method_defined?(:method_missing)) && "_handle_method_missing")
62
63
  end
63
64
  end
64
65
  end
@@ -141,7 +141,7 @@ module ActionController #:nodoc:
141
141
  raise ArgumentError, ":#{arg} option required" if options[arg].nil?
142
142
  end
143
143
 
144
- disposition = options[:disposition]
144
+ disposition = options[:disposition].to_s
145
145
  disposition += %(; filename="#{options[:filename]}") if options[:filename]
146
146
 
147
147
  content_type = options[:type]
@@ -27,20 +27,14 @@ module ActionController
27
27
  self.hidden_actions = hidden_actions.dup.merge(args.map(&:to_s)).freeze
28
28
  end
29
29
 
30
- def inherited(klass)
31
- klass.class_eval { @visible_actions = {} }
32
- super
33
- end
34
-
35
30
  def visible_action?(action_name)
36
- return @visible_actions[action_name] if @visible_actions.key?(action_name)
37
- @visible_actions[action_name] = !hidden_actions.include?(action_name)
31
+ action_methods.include?(action_name)
38
32
  end
39
33
 
40
34
  # Overrides AbstractController::Base#action_methods to remove any methods
41
35
  # that are listed as hidden methods.
42
36
  def action_methods
43
- @action_methods ||= Set.new(super.reject { |name| hidden_actions.include?(name) })
37
+ @action_methods ||= Set.new(super.reject { |name| hidden_actions.include?(name) }).freeze
44
38
  end
45
39
  end
46
40
  end
@@ -77,7 +77,7 @@ module ActionController
77
77
 
78
78
  private
79
79
  def _extract_redirect_to_status(options, response_status)
80
- status = if options.is_a?(Hash) && options.key?(:status)
80
+ if options.is_a?(Hash) && options.key?(:status)
81
81
  Rack::Utils.status_code(options.delete(:status))
82
82
  elsif response_status.key?(:status)
83
83
  Rack::Utils.status_code(response_status[:status])
@@ -70,6 +70,8 @@ module ActionController
70
70
  #
71
71
  def assert_template(options = {}, message = nil)
72
72
  validate_request!
73
+ # Force body to be read in case the template is being streamed
74
+ response.body
73
75
 
74
76
  case options
75
77
  when NilClass, String, Symbol
@@ -26,8 +26,6 @@ module ActionDispatch
26
26
  module FilterParameters
27
27
  extend ActiveSupport::Concern
28
28
 
29
- @@parameter_filter_for = {}
30
-
31
29
  # Return a hash of parameters with all sensitive data replaced.
32
30
  def filtered_parameters
33
31
  @filtered_parameters ||= parameter_filter.filter(parameters)
@@ -54,7 +52,7 @@ module ActionDispatch
54
52
  end
55
53
 
56
54
  def parameter_filter_for(filters)
57
- @@parameter_filter_for[filters] ||= ParameterFilter.new(filters)
55
+ ParameterFilter.new(filters)
58
56
  end
59
57
 
60
58
  KV_RE = '[^&;=]+'
@@ -56,7 +56,12 @@ module ActionDispatch
56
56
  RFC5789 = %w(PATCH)
57
57
 
58
58
  HTTP_METHODS = RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789
59
- HTTP_METHOD_LOOKUP = Hash.new { |h, m| h[m] = m.underscore.to_sym if HTTP_METHODS.include?(m) }
59
+ HTTP_METHOD_LOOKUP = {}
60
+
61
+ # Populate the HTTP method lookup cache
62
+ HTTP_METHODS.each do |method|
63
+ HTTP_METHOD_LOOKUP[method] = method.underscore.to_sym
64
+ end
60
65
 
61
66
  # Returns the HTTP \method that the application should see.
62
67
  # In the case where the \method was overridden by a middleware
@@ -179,8 +184,9 @@ module ActionDispatch
179
184
  # work with raw requests directly.
180
185
  def raw_post
181
186
  unless @env.include? 'RAW_POST_DATA'
182
- @env['RAW_POST_DATA'] = body.read(@env['CONTENT_LENGTH'].to_i)
183
- body.rewind if body.respond_to?(:rewind)
187
+ raw_post_body = body
188
+ @env['RAW_POST_DATA'] = raw_post_body.read(@env['CONTENT_LENGTH'].to_i)
189
+ raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
184
190
  end
185
191
  @env['RAW_POST_DATA']
186
192
  end
@@ -43,7 +43,11 @@ module ActionDispatch
43
43
  params = options[:params] || {}
44
44
  params.reject! {|k,v| v.to_param.nil? }
45
45
 
46
- rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
46
+ if options[:trailing_slash] && !path.ends_with?('/')
47
+ rewritten_url << path.sub(/(\?|\z)/) { "/" + $& }
48
+ else
49
+ rewritten_url << path
50
+ end
47
51
  rewritten_url << "?#{params.to_query}" unless params.empty?
48
52
  rewritten_url << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
49
53
  rewritten_url
@@ -15,7 +15,15 @@ module ActionDispatch
15
15
 
16
16
  def call(env)
17
17
  status, headers, body = @app.call(env)
18
- headers["X-UA-Compatible"] = @header
18
+
19
+ if headers["X-UA-Compatible"] && @header
20
+ unless headers["X-UA-Compatible"][@header]
21
+ headers["X-UA-Compatible"] << "," << @header.to_s
22
+ end
23
+ else
24
+ headers["X-UA-Compatible"] = @header
25
+ end
26
+
19
27
  [status, headers, body]
20
28
  end
21
29
  end
@@ -44,10 +44,10 @@ module ActionDispatch
44
44
  when :yaml
45
45
  YAML.load(request.raw_post)
46
46
  when :json
47
- data = request.deep_munge ActiveSupport::JSON.decode(request.body)
47
+ data = ActiveSupport::JSON.decode(request.body)
48
48
  request.body.rewind if request.body.respond_to?(:rewind)
49
49
  data = {:_json => data} unless data.is_a?(Hash)
50
- data.with_indifferent_access
50
+ request.deep_munge(data).with_indifferent_access
51
51
  else
52
52
  false
53
53
  end
@@ -22,15 +22,12 @@ module ActionDispatch
22
22
  #
23
23
  # Session options:
24
24
  #
25
- # * <tt>:secret</tt>: An application-wide key string or block returning a
26
- # string called per generated digest. The block is called with the
27
- # CGI::Session instance as an argument. It's important that the secret
28
- # is not vulnerable to a dictionary attack. Therefore, you should choose
29
- # a secret consisting of random numbers and letters and more than 30
30
- # characters. Examples:
25
+ # * <tt>:secret</tt>: An application-wide key string. It's important that
26
+ # the secret is not vulnerable to a dictionary attack. Therefore, you
27
+ # should choose a secret consisting of random numbers and letters and
28
+ # more than 30 characters.
31
29
  #
32
30
  # :secret => '449fe2e7daee471bffae2fd8dc02313d'
33
- # :secret => Proc.new { User.current_user.secret_key }
34
31
  #
35
32
  # * <tt>:digest</tt>: The message digest algorithm used to verify session
36
33
  # integrity defaults to 'SHA1' but may be any digest provided by OpenSSL,
@@ -5,7 +5,8 @@ module ActionDispatch
5
5
  def initialize(root, cache_control)
6
6
  @root = root.chomp('/')
7
7
  @compiled_root = /^#{Regexp.escape(root)}/
8
- @file_server = ::Rack::File.new(@root, cache_control)
8
+ headers = cache_control && { 'Cache-Control' => cache_control }
9
+ @file_server = ::Rack::File.new(@root, headers)
9
10
  end
10
11
 
11
12
  def match?(path)
@@ -51,7 +51,6 @@ module ActionDispatch
51
51
  class Mapping #:nodoc:
52
52
  IGNORE_OPTIONS = [:to, :as, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix]
53
53
  ANCHOR_CHARACTERS_REGEX = %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
54
- SHORTHAND_REGEX = %r{/[\w/]+$}
55
54
  WILDCARD_PATH = %r{\*([^/\)]+)\)?$}
56
55
 
57
56
  def initialize(set, scope, path, options)
@@ -70,12 +69,7 @@ module ActionDispatch
70
69
  def normalize_options!
71
70
  path_without_format = @path.sub(/\(\.:format\)$/, '')
72
71
 
73
- if using_match_shorthand?(path_without_format, @options)
74
- to_shorthand = @options[:to].blank?
75
- @options[:to] ||= path_without_format.gsub(/\(.*\)/, "")[1..-1].sub(%r{/([^/]*)$}, '#\1')
76
- end
77
-
78
- @options.merge!(default_controller_and_action(to_shorthand))
72
+ @options.merge!(default_controller_and_action)
79
73
 
80
74
  requirements.each do |name, requirement|
81
75
  # segment_keys.include?(k.to_s) || k == :controller
@@ -153,7 +147,7 @@ module ActionDispatch
153
147
  end
154
148
  end
155
149
 
156
- def default_controller_and_action(to_shorthand=nil)
150
+ def default_controller_and_action
157
151
  if to.respond_to?(:call)
158
152
  { }
159
153
  else
@@ -166,7 +160,7 @@ module ActionDispatch
166
160
  controller ||= default_controller
167
161
  action ||= default_action
168
162
 
169
- unless controller.is_a?(Regexp) || to_shorthand
163
+ unless controller.is_a?(Regexp)
170
164
  controller = [@scope[:module], controller].compact.join("/").presence
171
165
  end
172
166
 
@@ -451,7 +445,7 @@ module ActionDispatch
451
445
  # we must actually delete prefix segment keys to avoid passing them to next url_for
452
446
  _route.segment_keys.each { |k| options.delete(k) }
453
447
  prefix = _routes.url_helpers.send("#{name}_path", prefix_options)
454
- prefix = '' if prefix == '/'
448
+ prefix = prefix.gsub(%r{/\z}, '')
455
449
  prefix
456
450
  end
457
451
  end
@@ -1261,6 +1255,11 @@ module ActionDispatch
1261
1255
  paths = [path] + rest
1262
1256
  end
1263
1257
 
1258
+ path_without_format = path.to_s.sub(/\(\.:format\)$/, '')
1259
+ if using_match_shorthand?(path_without_format, options)
1260
+ options[:to] ||= path_without_format.gsub(%r{^/}, "").sub(%r{/([^/]*)$}, '#\1')
1261
+ end
1262
+
1264
1263
  options[:anchor] = true unless options.key?(:anchor)
1265
1264
 
1266
1265
  if options[:on] && !VALID_ON_OPTIONS.include?(options[:on])
@@ -1271,6 +1270,10 @@ module ActionDispatch
1271
1270
  self
1272
1271
  end
1273
1272
 
1273
+ def using_match_shorthand?(path, options)
1274
+ path && (options[:to] || options[:action]).nil? && path =~ %r{/[\w/]+$}
1275
+ end
1276
+
1274
1277
  def decomposed_match(path, options) # :nodoc:
1275
1278
  if on = options.delete(:on)
1276
1279
  send(on) { decomposed_match(path, options) }
@@ -1288,9 +1291,10 @@ module ActionDispatch
1288
1291
 
1289
1292
  def add_route(action, options) # :nodoc:
1290
1293
  path = path_for_action(action, options.delete(:path))
1294
+ action = action.to_s.dup
1291
1295
 
1292
- if action.to_s =~ /^[\w\/]+$/
1293
- options[:action] ||= action unless action.to_s.include?("/")
1296
+ if action =~ /^[\w\/]+$/
1297
+ options[:action] ||= action unless action.include?("/")
1294
1298
  else
1295
1299
  action = nil
1296
1300
  end
@@ -78,10 +78,10 @@ module ActionDispatch
78
78
  # params, depending of how many arguments your block accepts. A string is required as a
79
79
  # return value.
80
80
  #
81
- # match 'jokes/:number', :to => redirect do |params, request|
82
- # path = (params[:number].to_i.even? ? "/wheres-the-beef" : "/i-love-lamp")
81
+ # match 'jokes/:number', :to => redirect { |params, request|
82
+ # path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")
83
83
  # "http://#{request.host_with_port}/#{path}"
84
- # end
84
+ # }
85
85
  #
86
86
  # The options version of redirect allows you to supply only the parts of the url which need
87
87
  # to change, it also supports interpolation of the path similar to the first example.
@@ -94,7 +94,12 @@ module ActionDispatch
94
94
  attr_reader :routes, :helpers, :module
95
95
 
96
96
  def initialize
97
- clear!
97
+ @routes = {}
98
+ @helpers = []
99
+
100
+ @module = Module.new do
101
+ instance_methods.each { |selector| remove_method(selector) }
102
+ end
98
103
  end
99
104
 
100
105
  def helper_names
@@ -102,12 +107,14 @@ module ActionDispatch
102
107
  end
103
108
 
104
109
  def clear!
110
+ @helpers.each do |helper|
111
+ @module.module_eval do
112
+ remove_possible_method helper
113
+ end
114
+ end
115
+
105
116
  @routes = {}
106
117
  @helpers = []
107
-
108
- @module ||= Module.new do
109
- instance_methods.each { |selector| remove_method(selector) }
110
- end
111
118
  end
112
119
 
113
120
  def add(name, route)
@@ -291,7 +298,6 @@ module ActionDispatch
291
298
 
292
299
  def clear!
293
300
  @finalized = false
294
- @url_helpers = nil
295
301
  named_routes.clear
296
302
  set.clear
297
303
  formatter.clear
@@ -442,12 +448,12 @@ module ActionDispatch
442
448
  normalize_options!
443
449
  normalize_controller_action_id!
444
450
  use_relative_controller!
445
- controller.sub!(%r{^/}, '') if controller
451
+ normalize_controller!
446
452
  handle_nil_action!
447
453
  end
448
454
 
449
455
  def controller
450
- @controller ||= @options[:controller]
456
+ @options[:controller]
451
457
  end
452
458
 
453
459
  def current_controller
@@ -504,10 +510,15 @@ module ActionDispatch
504
510
  old_parts = current_controller.split('/')
505
511
  size = controller.count("/") + 1
506
512
  parts = old_parts[0...-size] << controller
507
- @controller = @options[:controller] = parts.join("/")
513
+ @options[:controller] = parts.join("/")
508
514
  end
509
515
  end
510
516
 
517
+ # Remove leading slashes from controllers
518
+ def normalize_controller!
519
+ @options[:controller] = controller.sub(%r{^/}, '') if controller
520
+ end
521
+
511
522
  # This handles the case of :action => nil being explicitly passed.
512
523
  # It is identical to :action => "index"
513
524
  def handle_nil_action!
@@ -2,8 +2,8 @@ module ActionPack
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 2
5
- TINY = 12
6
- PRE = nil
5
+ TINY = 13
6
+ PRE = "rc1"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
  end
@@ -65,12 +65,17 @@ module ActionView
65
65
  # distance_of_time_in_words(Time.now, Time.now) # => less than a minute
66
66
  #
67
67
  def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
68
+ options = {
69
+ :scope => :'datetime.distance_in_words',
70
+ }.merge!(options)
71
+
68
72
  from_time = from_time.to_time if from_time.respond_to?(:to_time)
69
73
  to_time = to_time.to_time if to_time.respond_to?(:to_time)
70
- distance_in_minutes = (((to_time - from_time).abs)/60).round
71
- distance_in_seconds = ((to_time - from_time).abs).round
74
+ distance = (to_time.to_f - from_time.to_f).abs
75
+ distance_in_minutes = (distance / 60.0).round
76
+ distance_in_seconds = distance.round
72
77
 
73
- I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
78
+ I18n.with_options :locale => options[:locale], :scope => options[:scope] do |locale|
74
79
  case distance_in_minutes
75
80
  when 0..1
76
81
  return distance_in_minutes == 0 ?
@@ -129,8 +134,8 @@ module ActionView
129
134
  # from_time = Time.now - 3.days - 14.minutes - 25.seconds
130
135
  # time_ago_in_words(from_time) # => 3 days
131
136
  #
132
- def time_ago_in_words(from_time, include_seconds = false)
133
- distance_of_time_in_words(from_time, Time.now, include_seconds)
137
+ def time_ago_in_words(from_time, include_seconds = false, options = {})
138
+ distance_of_time_in_words(from_time, Time.now, include_seconds, options)
134
139
  end
135
140
 
136
141
  alias_method :distance_of_time_in_words_to_now, :time_ago_in_words
@@ -331,9 +331,9 @@ module ActionView
331
331
  # In many cases you will want to wrap the above in another helper, so you
332
332
  # could do something like the following:
333
333
  #
334
- # def labelled_form_for(record_or_name_or_array, *args, &proc)
334
+ # def labelled_form_for(record_or_name_or_array, *args, &block)
335
335
  # options = args.extract_options!
336
- # form_for(record_or_name_or_array, *(args << options.merge(:builder => LabellingFormBuilder)), &proc)
336
+ # form_for(record_or_name_or_array, *(args << options.merge(:builder => LabellingFormBuilder)), &block)
337
337
  # end
338
338
  #
339
339
  # If you don't need to attach a form to a model instance, then check out
@@ -355,7 +355,7 @@ module ActionView
355
355
  # <%= form_for @invoice, :url => external_url, :authenticity_token => false do |f|
356
356
  # ...
357
357
  # <% end %>
358
- def form_for(record, options = {}, &proc)
358
+ def form_for(record, options = {}, &block)
359
359
  raise ArgumentError, "Missing block" unless block_given?
360
360
 
361
361
  options[:html] ||= {}
@@ -374,12 +374,10 @@ module ActionView
374
374
  options[:html][:method] = options.delete(:method) if options.has_key?(:method)
375
375
  options[:html][:authenticity_token] = options.delete(:authenticity_token)
376
376
 
377
- builder = options[:parent_builder] = instantiate_builder(object_name, object, options, &proc)
378
- fields_for = fields_for(object_name, object, options, &proc)
377
+ builder = options[:parent_builder] = instantiate_builder(object_name, object, options, &block)
378
+ output = capture(builder, &block)
379
379
  default_options = builder.multipart? ? { :multipart => true } : {}
380
- output = form_tag(options.delete(:url) || {}, default_options.merge!(options.delete(:html)))
381
- output << fields_for
382
- output.safe_concat('</form>')
380
+ form_tag(options.delete(:url) || {}, default_options.merge!(options.delete(:html))) { output }
383
381
  end
384
382
 
385
383
  def apply_form_for_options!(object_or_array, options) #:nodoc:
@@ -1205,9 +1203,11 @@ module ActionView
1205
1203
  options["name"] ||= tag_name_with_index(@auto_index)
1206
1204
  options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) }
1207
1205
  else
1208
- options["name"] ||= tag_name + (options['multiple'] ? '[]' : '')
1206
+ options["name"] ||= tag_name
1209
1207
  options["id"] = options.fetch("id"){ tag_id }
1210
1208
  end
1209
+
1210
+ options["name"] += "[]" if options["multiple"]
1211
1211
  options["id"] = [options.delete('namespace'), options["id"]].compact.join("_").presence
1212
1212
  end
1213
1213
 
@@ -508,9 +508,9 @@ module ActionView
508
508
  convert_zones = lambda { |list| list.map { |z| [ z.to_s, z.name ] } }
509
509
 
510
510
  if priority_zones
511
- if priority_zones.is_a?(Regexp)
511
+ if priority_zones.is_a?(Regexp)
512
512
  priority_zones = model.all.find_all {|z| z =~ priority_zones}
513
- end
513
+ end
514
514
  zone_options += options_for_select(convert_zones[priority_zones], selected)
515
515
  zone_options += "<option value=\"\" disabled=\"disabled\">-------------</option>\n"
516
516
 
@@ -45,7 +45,7 @@ module ActionView
45
45
  # # => <form action="/posts" method="post">
46
46
  #
47
47
  # form_tag('/posts/1', :method => :put)
48
- # # => <form action="/posts/1" method="put">
48
+ # # => <form action="/posts/1" method="post"> ... <input name="_method" type="hidden" value="put" /> ...
49
49
  #
50
50
  # form_tag('/upload', :multipart => true)
51
51
  # # => <form action="/upload" method="post" enctype="multipart/form-data">
@@ -53,7 +53,7 @@ module ActionView
53
53
  # <%= form_tag('/posts') do -%>
54
54
  # <div><%= submit_tag 'Save' %></div>
55
55
  # <% end -%>
56
- # # => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>
56
+ # # => <form action="/posts" method="post"><div><input type="submit" name="commit" value="Save" /></div></form>
57
57
  #
58
58
  # <%= form_tag('/posts', :remote => true) %>
59
59
  # # => <form action="/posts" method="post" data-remote="true">
@@ -181,7 +181,7 @@ module ActionView
181
181
  # # => <label for="name">Name</label>
182
182
  #
183
183
  # label_tag 'name', 'Your name'
184
- # # => <label for="name">Your Name</label>
184
+ # # => <label for="name">Your name</label>
185
185
  #
186
186
  # label_tag 'name', nil, :class => 'small_label'
187
187
  # # => <label for="name" class="small_label">Name</label>
@@ -1,5 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'active_support/core_ext/hash/keys'
4
+ require 'active_support/core_ext/hash/reverse_merge'
3
5
  require 'active_support/core_ext/big_decimal/conversions'
4
6
  require 'active_support/core_ext/float/rounding'
5
7
  require 'active_support/core_ext/object/blank'
@@ -98,7 +98,9 @@ module ActionView
98
98
  options, prefix = prefix, nil if prefix.is_a?(Hash)
99
99
  options = options ? options.dup : {}
100
100
  options.merge!(:class => "#{dom_class(record, prefix)} #{options[:class]}".strip, :id => dom_id(record, prefix))
101
- if block.arity == 0
101
+ if !block_given?
102
+ content_tag(tag_name, "", options)
103
+ elsif block.arity == 0
102
104
  content_tag(tag_name, capture(&block), options)
103
105
  else
104
106
  content_tag(tag_name, capture(record, &block), options)
@@ -256,7 +256,7 @@ module ActionView
256
256
  object, as = @object, @variable
257
257
 
258
258
  if !block && (layout = @options[:layout])
259
- layout = find_template(layout)
259
+ layout = find_template(layout.to_s)
260
260
  end
261
261
 
262
262
  object ||= locals[as]
@@ -15,6 +15,17 @@ module ActionView
15
15
  src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
16
16
  end
17
17
 
18
+ # Erubis toggles <%= and <%== behavior when escaping is enabled.
19
+ # We override to always treat <%== as escaped.
20
+ def add_expr(src, code, indicator)
21
+ case indicator
22
+ when '=='
23
+ add_expr_escaped(src, code)
24
+ else
25
+ super
26
+ end
27
+ end
28
+
18
29
  BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
19
30
 
20
31
  def add_expr_literal(src, code)
@@ -48,6 +59,10 @@ module ActionView
48
59
  class_attribute :erb_implementation
49
60
  self.erb_implementation = Erubis
50
61
 
62
+ # Do not escape templates of these mime types.
63
+ class_attribute :escape_whitelist
64
+ self.escape_whitelist = ["text/plain"]
65
+
51
66
  ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
52
67
 
53
68
  def self.call(template)
@@ -83,6 +98,7 @@ module ActionView
83
98
 
84
99
  self.class.erb_implementation.new(
85
100
  erb,
101
+ :escape => (self.class.escape_whitelist.include? template.mime_type),
86
102
  :trim => (self.class.erb_trim_mode == "-")
87
103
  ).src
88
104
  end
@@ -31,7 +31,7 @@ module Sprockets
31
31
  else
32
32
  super(source.to_s, { :src => path_to_asset(source, :ext => 'js', :body => body, :digest => digest) }.merge!(options))
33
33
  end
34
- end.uniq.join("\n").html_safe
34
+ end.flatten.uniq.join("\n").html_safe
35
35
  end
36
36
 
37
37
  def stylesheet_link_tag(*sources)
@@ -48,7 +48,7 @@ module Sprockets
48
48
  else
49
49
  super(source.to_s, { :href => path_to_asset(source, :ext => 'css', :body => body, :protocol => :request, :digest => digest) }.merge!(options))
50
50
  end
51
- end.uniq.join("\n").html_safe
51
+ end.flatten.uniq.join("\n").html_safe
52
52
  end
53
53
 
54
54
  def asset_path(source, options = {})
@@ -157,18 +157,25 @@ module Sprockets
157
157
  end
158
158
 
159
159
  def rewrite_extension(source, dir, ext)
160
- source_ext = File.extname(source)
161
- if ext && source_ext != ".#{ext}"
162
- if !source_ext.empty? && (asset = asset_environment[source]) &&
163
- asset.pathname.to_s =~ /#{source}\Z/
164
- source
165
- else
166
- "#{source}.#{ext}"
167
- end
168
- else
160
+ source_ext = File.extname(source)[1..-1]
161
+
162
+ if !ext || ext == source_ext
163
+ source
164
+ elsif source_ext.blank?
165
+ "#{source}.#{ext}"
166
+ elsif exact_match_present?(source)
169
167
  source
168
+ else
169
+ "#{source}.#{ext}"
170
170
  end
171
171
  end
172
+
173
+ def exact_match_present?(source)
174
+ pathname = asset_environment.resolve(source)
175
+ pathname.to_s =~ /#{Regexp.escape(source)}\Z/
176
+ rescue Sprockets::FileNotFound
177
+ false
178
+ end
172
179
  end
173
180
  end
174
181
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.12
4
+ version: 3.2.13.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-02-11 00:00:00.000000000 Z
11
+ date: 2013-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,138 +16,138 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 3.2.12
19
+ version: 3.2.13.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 3.2.12
26
+ version: 3.2.13.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 3.2.12
33
+ version: 3.2.13.rc1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 3.2.12
40
+ version: 3.2.13.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rack-cache
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: builder
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: 3.0.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: 3.0.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rack
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ~>
74
74
  - !ruby/object:Gem::Version
75
75
  version: 1.4.5
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ~>
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.4.5
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rack-test
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ~>
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.6.1
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.6.1
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: journey
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ~>
102
102
  - !ruby/object:Gem::Version
103
103
  version: 1.0.4
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ~>
109
109
  - !ruby/object:Gem::Version
110
110
  version: 1.0.4
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: sprockets
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ~>
116
116
  - !ruby/object:Gem::Version
117
117
  version: 2.2.1
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ~>
123
123
  - !ruby/object:Gem::Version
124
124
  version: 2.2.1
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: erubis
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ~>
130
130
  - !ruby/object:Gem::Version
131
131
  version: 2.7.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - "~>"
136
+ - - ~>
137
137
  - !ruby/object:Gem::Version
138
138
  version: 2.7.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: tzinfo
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - "~>"
143
+ - - ~>
144
144
  - !ruby/object:Gem::Version
145
145
  version: 0.3.29
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - "~>"
150
+ - - ~>
151
151
  - !ruby/object:Gem::Version
152
152
  version: 0.3.29
153
153
  description: Web apps on Rails. Simple, battle-tested conventions for building and
@@ -357,18 +357,18 @@ require_paths:
357
357
  - lib
358
358
  required_ruby_version: !ruby/object:Gem::Requirement
359
359
  requirements:
360
- - - ">="
360
+ - - '>='
361
361
  - !ruby/object:Gem::Version
362
362
  version: 1.8.7
363
363
  required_rubygems_version: !ruby/object:Gem::Requirement
364
364
  requirements:
365
- - - ">="
365
+ - - '>'
366
366
  - !ruby/object:Gem::Version
367
- version: '0'
367
+ version: 1.3.1
368
368
  requirements:
369
369
  - none
370
370
  rubyforge_project:
371
- rubygems_version: 2.0.0.rc.2
371
+ rubygems_version: 2.0.0
372
372
  signing_key:
373
373
  specification_version: 4
374
374
  summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).