actionpack 3.2.3 → 3.2.4.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.

@@ -1,11 +1,26 @@
1
- ## Rails 3.2.3 (unreleased) ##
1
+ ## Rails 3.2.4 (unreleased) ##
2
2
 
3
- * Remove the leading \n added by textarea on assert_select. *Santiago Pastorino*
3
+ * Deprecate old APIs for highlight, excerpt and word_wrap *Jeremy Walker*
4
+
5
+ * Deprecate `:disable_with` in favor of `'data-disable-with'` option for `button_to`, `button_tag` and `submit_tag` helpers.
6
+
7
+ *Carlos Galdino + Rafael Mendonça França*
8
+
9
+ * Deprecate `:mouseover` option for `image_tag` helper. *Rafael Mendonça França*
10
+
11
+ * Deprecate `button_to_function` and `link_to_function` helpers. *Rafael Mendonça França*
12
+
13
+
14
+ ## Rails 3.2.3 (March 30, 2012) ##
15
+
16
+ * Allow to lazy load `default_form_builder` by passing a `String` instead of a constant. *Piotr Sarnacki*
4
17
 
5
18
  * Fix #5632, render :inline set the proper rendered format. *Santiago Pastorino*
6
19
 
7
20
  * Fix textarea rendering when using plugins like HAML. Such plugins encode the first newline character in the content. This issue was introduced in https://github.com/rails/rails/pull/5191 *James Coleman*
8
21
 
22
+ * Remove the leading \n added by textarea on assert_select. *Santiago Pastorino*
23
+
9
24
  * Add `config.action_view.embed_authenticity_token_in_remote_forms` (defaults to true) which allows to set if authenticity token will be included by default in remote forms. If you change it to false, you can still force authenticity token by passing `:authenticity_token => true` in form options *Piotr Sarnacki*
10
25
 
11
26
  * Do not include the authenticity token in forms where remote: true as ajax forms use the meta-tag value *DHH*
@@ -322,7 +322,7 @@ The latest version of Action Pack can be installed with RubyGems:
322
322
 
323
323
  Source code can be downloaded as part of the Rails project on GitHub
324
324
 
325
- * https://github.com/rails/rails/tree/master/actionpack
325
+ * https://github.com/rails/rails/tree/3-2-stable/actionpack
326
326
 
327
327
 
328
328
  == License
@@ -20,6 +20,7 @@ module ActionController
20
20
  options, status = status, nil if status.is_a?(Hash)
21
21
  status ||= options.delete(:status) || :ok
22
22
  location = options.delete(:location)
23
+ content_type = options.delete(:content_type)
23
24
 
24
25
  options.each do |key, value|
25
26
  headers[key.to_s.dasherize.split('-').each { |v| v[0] = v[0].chr.upcase }.join('-')] = value.to_s
@@ -27,7 +28,7 @@ module ActionController
27
28
 
28
29
  self.status = status
29
30
  self.location = url_for(location) if location
30
- self.content_type = Mime[formats.first] if formats
31
+ self.content_type = content_type || (Mime[formats.first] if formats)
31
32
  self.response_body = " "
32
33
  end
33
34
  end
@@ -167,8 +167,9 @@ module ActionController
167
167
 
168
168
  unless options[:include] || options[:exclude]
169
169
  model ||= _default_wrap_model
170
- if model.respond_to?(:accessible_attributes) && model.accessible_attributes.present?
171
- options[:include] = model.accessible_attributes.to_a
170
+ role = options.has_key?(:as) ? options[:as] : :default
171
+ if model.respond_to?(:accessible_attributes) && model.accessible_attributes(role).present?
172
+ options[:include] = model.accessible_attributes(role).to_a
172
173
  elsif model.respond_to?(:attribute_names) && model.attribute_names.present?
173
174
  options[:include] = model.attribute_names
174
175
  end
@@ -45,6 +45,16 @@ module ActionController
45
45
  # integer, or a symbol representing the downcased, underscored and symbolized description.
46
46
  # Note that the status code must be a 3xx HTTP code, or redirection will not occur.
47
47
  #
48
+ # If you are using XHR requests other than GET or POST and redirecting after the
49
+ # request then some browsers will follow the redirect using the original request
50
+ # method. This may lead to undesirable behavior such as a double DELETE. To work
51
+ # around this you can return a <tt>303 See Other</tt> status code which will be
52
+ # followed using a GET request.
53
+ #
54
+ # Examples:
55
+ # redirect_to posts_url, :status => :see_other
56
+ # redirect_to :action => 'index', :status => 303
57
+ #
48
58
  # It is also possible to assign a flash message as part of the redirection. There are two special accessors for the commonly used flash names
49
59
  # +alert+ and +notice+ as well as a general purpose +flash+ bucket.
50
60
  #
@@ -147,17 +147,23 @@ module ActionController
147
147
  extra_keys = routes.extra_keys(parameters)
148
148
  non_path_parameters = get? ? query_parameters : request_parameters
149
149
  parameters.each do |key, value|
150
- if value.is_a? Fixnum
151
- value = value.to_s
152
- elsif value.is_a? Array
153
- value = Result.new(value.map { |v| v.is_a?(String) ? v.dup : v })
154
- elsif value.is_a? String
150
+ if value.is_a?(Array) && (value.frozen? || value.any?(&:frozen?))
151
+ value = value.map{ |v| v.duplicable? ? v.dup : v }
152
+ elsif value.is_a?(Hash) && (value.frozen? || value.any?{ |k,v| v.frozen? })
153
+ value = Hash[value.map{ |k,v| [k, v.duplicable? ? v.dup : v] }]
154
+ elsif value.frozen? && value.duplicable?
155
155
  value = value.dup
156
156
  end
157
157
 
158
158
  if extra_keys.include?(key.to_sym)
159
159
  non_path_parameters[key] = value
160
160
  else
161
+ if value.is_a?(Array)
162
+ value = Result.new(value.map(&:to_param))
163
+ else
164
+ value = value.to_param
165
+ end
166
+
161
167
  path_parameters[key.to_s] = value
162
168
  end
163
169
  end
@@ -426,7 +432,7 @@ module ActionController
426
432
  def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
427
433
  # Ensure that numbers and symbols passed as params are converted to
428
434
  # proper params, as is the case when engaging rack.
429
- parameters = paramify_values(parameters)
435
+ parameters = paramify_values(parameters) if html_format?(parameters)
430
436
 
431
437
  # Sanity check for required instance variables so we can give an
432
438
  # understandable error message.
@@ -454,7 +460,6 @@ module ActionController
454
460
 
455
461
  @request.session = ActionController::TestSession.new(session) if session
456
462
  @request.session["flash"] = @request.flash.update(flash || {})
457
- @request.session["flash"].sweep
458
463
 
459
464
  @controller.request = @request
460
465
  build_request_uri(action, parameters)
@@ -507,6 +512,12 @@ module ActionController
507
512
  @request.env["QUERY_STRING"] = query_string || ""
508
513
  end
509
514
  end
515
+
516
+ def html_format?(parameters)
517
+ return true unless parameters.is_a?(Hash)
518
+ format = Mime[parameters[:format]]
519
+ format.nil? || format.html?
520
+ end
510
521
  end
511
522
 
512
523
  # When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline
@@ -35,6 +35,10 @@ module ActionDispatch
35
35
  @env["action_dispatch.request.path_parameters"] ||= {}
36
36
  end
37
37
 
38
+ def reset_parameters #:nodoc:
39
+ @env.delete("action_dispatch.request.parameters")
40
+ end
41
+
38
42
  private
39
43
 
40
44
  # TODO: Validate that the characters are UTF-8. If they aren't,
@@ -4,7 +4,7 @@ module ActionDispatch
4
4
  # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
5
5
  # to put a new one.
6
6
  def flash
7
- @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new)
7
+ @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new).tap(&:sweep)
8
8
  end
9
9
  end
10
10
 
@@ -235,10 +235,6 @@ module ActionDispatch
235
235
  end
236
236
 
237
237
  def call(env)
238
- if (session = env['rack.session']) && (flash = session['flash'])
239
- flash.sweep
240
- end
241
-
242
238
  @app.call(env)
243
239
  ensure
244
240
  session = env['rack.session'] || {}
@@ -255,7 +251,8 @@ module ActionDispatch
255
251
  env[KEY] = new_hash
256
252
  end
257
253
 
258
- if session.key?('flash') && session['flash'].empty?
254
+ if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?)
255
+ session.key?('flash') && session['flash'].empty?
259
256
  session.delete('flash')
260
257
  end
261
258
  end
@@ -1,5 +1,4 @@
1
1
  require 'action_dispatch/middleware/session/abstract_store'
2
- require 'rack/session/memcache'
3
2
 
4
3
  module ActionDispatch
5
4
  module Session
@@ -34,6 +34,8 @@ module ActionDispatch
34
34
  }
35
35
 
36
36
  return true
37
+ ensure
38
+ req.reset_parameters
37
39
  end
38
40
 
39
41
  def call(env)
@@ -1,4 +1,6 @@
1
1
  require 'action_dispatch/http/request'
2
+ require 'active_support/core_ext/uri'
3
+ require 'rack/utils'
2
4
 
3
5
  module ActionDispatch
4
6
  module Routing
@@ -46,8 +48,17 @@ module ActionDispatch
46
48
  :params => request.query_parameters
47
49
  }.merge options
48
50
 
51
+ if !params.empty? && url_options[:path].match(/%\{\w*\}/)
52
+ url_options[:path] = (url_options[:path] % escape_path(params))
53
+ end
54
+
49
55
  ActionDispatch::Http::URL.url_for url_options
50
56
  end
57
+
58
+ private
59
+ def escape_path(params)
60
+ Hash[params.map{ |k,v| [k, URI.parser.escape(v)] }]
61
+ end
51
62
  end
52
63
 
53
64
  module Redirection
@@ -93,7 +104,7 @@ module ActionDispatch
93
104
  path = args.shift
94
105
 
95
106
  block = lambda { |params, request|
96
- (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % params)
107
+ (params.empty? || !path.match(/%\{\w*\}/)) ? path : (path % escape(params))
97
108
  } if String === path
98
109
 
99
110
  block = path if path.respond_to? :call
@@ -102,13 +113,19 @@ module ActionDispatch
102
113
  if block && block.respond_to?(:arity) && block.arity < 2
103
114
  msg = "redirect blocks with arity of #{block.arity} are deprecated. Your block must take 2 parameters: the environment, and a request object"
104
115
  ActiveSupport::Deprecation.warn msg
105
- block = lambda { |params, _| block.call(params) }
116
+ deprecated_block = block
117
+ block = lambda { |params, _| deprecated_block.call(params) }
106
118
  end
107
119
 
108
120
  raise ArgumentError, "redirection argument not supported" unless block
109
121
 
110
122
  Redirect.new status, block
111
123
  end
124
+
125
+ private
126
+ def escape(params)
127
+ Hash[params.map{ |k,v| [k, Rack::Utils.escape(v)] }]
128
+ end
112
129
  end
113
130
  end
114
131
  end
@@ -178,7 +178,7 @@ module ActionDispatch
178
178
  options = args.extract_options!
179
179
  result = #{options.inspect}
180
180
 
181
- if args.any?
181
+ if args.size > 0
182
182
  result[:_positional_args] = args
183
183
  result[:_positional_keys] = #{route.segment_keys.inspect}
184
184
  end
@@ -184,9 +184,16 @@ module ActionDispatch
184
184
  reset!
185
185
  end
186
186
 
187
- remove_method :default_url_options
188
- def default_url_options
189
- { :host => host, :protocol => https? ? "https" : "http" }
187
+ def url_options
188
+ @url_options ||= default_url_options.dup.tap do |url_options|
189
+ url_options.reverse_merge!(controller.url_options) if controller
190
+
191
+ if @app.respond_to?(:routes) && @app.routes.respond_to?(:default_url_options)
192
+ url_options.reverse_merge!(@app.routes.default_url_options)
193
+ end
194
+
195
+ url_options.reverse_merge!(:host => host, :protocol => https? ? "https" : "http")
196
+ end
190
197
  end
191
198
 
192
199
  # Resets the instance. This can be used to reset the state information
@@ -199,6 +206,7 @@ module ActionDispatch
199
206
  @controller = @request = @response = nil
200
207
  @_mock_session = nil
201
208
  @request_count = 0
209
+ @url_options = nil
202
210
 
203
211
  self.host = DEFAULT_HOST
204
212
  self.remote_addr = "127.0.0.1"
@@ -293,6 +301,7 @@ module ActionDispatch
293
301
  response = _mock_session.last_response
294
302
  @response = ActionDispatch::TestResponse.new(response.status, response.headers, response.body)
295
303
  @html_document = nil
304
+ @url_options = nil
296
305
 
297
306
  @controller = session.last_request.env['action_controller.instance']
298
307
 
@@ -350,12 +359,14 @@ module ActionDispatch
350
359
  end
351
360
  end
352
361
 
353
- extend ActiveSupport::Concern
354
- include ActionDispatch::Routing::UrlFor
355
-
356
- def url_options
362
+ def default_url_options
357
363
  reset! unless integration_session
364
+ integration_session.default_url_options
365
+ end
366
+
367
+ def default_url_options=(options)
358
368
  integration_session.url_options
369
+ integration_session.default_url_options = options
359
370
  end
360
371
 
361
372
  def respond_to?(method, include_private = false)
@@ -459,6 +470,7 @@ module ActionDispatch
459
470
  class IntegrationTest < ActiveSupport::TestCase
460
471
  include Integration::Runner
461
472
  include ActionController::TemplateAssertions
473
+ include ActionDispatch::Routing::UrlFor
462
474
 
463
475
  @@app = nil
464
476
 
@@ -475,5 +487,10 @@ module ActionDispatch
475
487
  def app
476
488
  super || self.class.app
477
489
  end
490
+
491
+ def url_options
492
+ reset! unless integration_session
493
+ integration_session.url_options
494
+ end
478
495
  end
479
496
  end
@@ -2,8 +2,8 @@ module ActionPack
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 2
5
- TINY = 3
6
- PRE = nil
5
+ TINY = 4
6
+ PRE = "rc1"
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
  end
@@ -37,7 +37,7 @@ module ActionView
37
37
  end
38
38
 
39
39
  def is_uri?(path)
40
- path =~ %r{^[-a-z]+://|^cid:|^//}
40
+ path =~ %r{^[-a-z]+://|^(?:cid|data):|^//}
41
41
  end
42
42
 
43
43
  private
@@ -272,7 +272,7 @@ module ActionView
272
272
  # The alias +path_to_image+ is provided to avoid that. Rails uses the alias internally, and
273
273
  # plugin authors are encouraged to do so.
274
274
  def image_path(source)
275
- asset_paths.compute_public_path(source, 'images')
275
+ source.present? ? asset_paths.compute_public_path(source, 'images') : ""
276
276
  end
277
277
  alias_method :path_to_image, :image_path # aliased to avoid conflicts with an image_path named route
278
278
 
@@ -358,7 +358,7 @@ module ActionView
358
358
 
359
359
  src = options[:src] = path_to_image(source)
360
360
 
361
- unless src =~ /^cid:/
361
+ unless src =~ /^(?:cid|data):/ || src.blank?
362
362
  options[:alt] = options.fetch(:alt){ image_alt(src) }
363
363
  end
364
364
 
@@ -367,6 +367,8 @@ module ActionView
367
367
  end
368
368
 
369
369
  if mouseover = options.delete(:mouseover)
370
+ ActiveSupport::Deprecation.warn ":mouseover option is deprecated and will be removed from Rails 4.0"
371
+
370
372
  options[:onmouseover] = "this.src='#{path_to_image(mouseover)}'"
371
373
  options[:onmouseout] = "this.src='#{src}'"
372
374
  end
@@ -1,5 +1,6 @@
1
1
  require 'thread'
2
2
  require 'active_support/core_ext/file'
3
+ require 'active_support/core_ext/module/attribute_accessors'
3
4
 
4
5
  module ActionView
5
6
  module Helpers
@@ -9,6 +9,7 @@ require 'active_support/core_ext/module/method_names'
9
9
  require 'active_support/core_ext/object/blank'
10
10
  require 'active_support/core_ext/string/output_safety'
11
11
  require 'active_support/core_ext/array/extract_options'
12
+ require 'active_support/core_ext/string/inflections'
12
13
 
13
14
  module ActionView
14
15
  # = Action View Form Helpers
@@ -656,15 +657,16 @@ module ActionView
656
657
  # 'Accept <a href="/terms">Terms</a>.'.html_safe
657
658
  # end
658
659
  def label(object_name, method, content_or_options = nil, options = nil, &block)
660
+ options ||= {}
661
+
659
662
  content_is_options = content_or_options.is_a?(Hash)
660
663
  if content_is_options || block_given?
661
- options = content_or_options if content_is_options
664
+ options.merge!(content_or_options) if content_is_options
662
665
  text = nil
663
666
  else
664
667
  text = content_or_options
665
668
  end
666
669
 
667
- options ||= {}
668
670
  InstanceTag.new(object_name, method, self, options.delete(:object)).to_label_tag(text, options, &block)
669
671
  end
670
672
 
@@ -958,9 +960,14 @@ module ActionView
958
960
  object_name = ActiveModel::Naming.param_key(object)
959
961
  end
960
962
 
961
- builder = options[:builder] || ActionView::Base.default_form_builder
963
+ builder = options[:builder] || default_form_builder
962
964
  builder.new(object_name, object, self, options, block)
963
965
  end
966
+
967
+ def default_form_builder
968
+ builder = ActionView::Base.default_form_builder
969
+ builder.respond_to?(:constantize) ? builder.constantize : builder
970
+ end
964
971
  end
965
972
 
966
973
  class InstanceTag
@@ -417,6 +417,8 @@ module ActionView
417
417
  options = options.stringify_keys
418
418
 
419
419
  if disable_with = options.delete("disable_with")
420
+ ActiveSupport::Deprecation.warn ":disable_with option is deprecated and will be removed from Rails 4.0. Use 'data-disable-with' instead"
421
+
420
422
  options["data-disable-with"] = disable_with
421
423
  end
422
424
 
@@ -467,6 +469,8 @@ module ActionView
467
469
  options = options.stringify_keys
468
470
 
469
471
  if disable_with = options.delete("disable_with")
472
+ ActiveSupport::Deprecation.warn ":disable_with option is deprecated and will be removed from Rails 4.0. Use 'data-disable-with' instead"
473
+
470
474
  options["data-disable-with"] = disable_with
471
475
  end
472
476
 
@@ -82,6 +82,8 @@ module ActionView
82
82
  # # => <input class="ok" onclick="alert('Hello world!');" type="button" value="Greeting" />
83
83
  #
84
84
  def button_to_function(name, function=nil, html_options={})
85
+ ActiveSupport::Deprecation.warn("button_to_function is deprecated and will be removed from Rails 4.0")
86
+
85
87
  onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
86
88
 
87
89
  tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
@@ -100,6 +102,8 @@ module ActionView
100
102
  # # => <a class="nav_link" href="#" onclick="alert('Hello world!'); return false;">Greeting</a>
101
103
  #
102
104
  def link_to_function(name, function, html_options={})
105
+ ActiveSupport::Deprecation.warn("link_to_function is deprecated and will be removed from Rails 4.0")
106
+
103
107
  onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
104
108
  href = html_options[:href] || '#'
105
109
 
@@ -427,10 +427,10 @@ module ActionView
427
427
  # * *integers*: <tt>:unit</tt>, <tt>:ten</tt>, <tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>, <tt>:billion</tt>, <tt>:trillion</tt>, <tt>:quadrillion</tt>
428
428
  # * *fractionals*: <tt>:deci</tt>, <tt>:centi</tt>, <tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>, <tt>:pico</tt>, <tt>:femto</tt>
429
429
  # * <tt>:format</tt> - Sets the format of the output string (defaults to "%n %u"). The field types are:
430
- # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid.
431
- #
432
430
  # %u The quantifier (ex.: 'thousand')
433
431
  # %n The number
432
+ # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when the argument is invalid.
433
+ #
434
434
  #
435
435
  # ==== Examples
436
436
  # number_to_human(123) # => "123"
@@ -96,8 +96,8 @@ module ActionView
96
96
  # for each record.
97
97
  def content_tag_for_single_record(tag_name, record, prefix, options, &block)
98
98
  options, prefix = prefix, nil if prefix.is_a?(Hash)
99
- options ||= {}
100
- options.merge!({ :class => "#{dom_class(record, prefix)} #{options[:class]}".strip, :id => dom_id(record, prefix) })
99
+ options = options ? options.dup : {}
100
+ options.merge!(:class => "#{dom_class(record, prefix)} #{options[:class]}".strip, :id => dom_id(record, prefix))
101
101
  if block.arity == 0
102
102
  content_tag(tag_name, capture(&block), options)
103
103
  else
@@ -138,7 +138,7 @@ module ActionView
138
138
  options.each_pair do |key, value|
139
139
  if key.to_s == 'data' && value.is_a?(Hash)
140
140
  value.each do |k, v|
141
- if !v.is_a?(String) && !v.is_a?(Symbol)
141
+ unless v.is_a?(String) || v.is_a?(Symbol) || v.is_a?(BigDecimal)
142
142
  v = v.to_json
143
143
  end
144
144
  v = ERB::Util.html_escape(v) if escape
@@ -111,6 +111,9 @@ module ActionView
111
111
  def highlight(text, phrases, *args)
112
112
  options = args.extract_options!
113
113
  unless args.empty?
114
+ ActiveSupport::Deprecation.warn "Calling highlight with a highlighter as an argument is deprecated. " \
115
+ "Please call with :highlighter => '#{args[0]}' instead.", caller
116
+
114
117
  options[:highlighter] = args[0] || '<strong class="highlight">\1</strong>'
115
118
  end
116
119
  options.reverse_merge!(:highlighter => '<strong class="highlight">\1</strong>')
@@ -156,6 +159,9 @@ module ActionView
156
159
 
157
160
  options = args.extract_options!
158
161
  unless args.empty?
162
+ ActiveSupport::Deprecation.warn "Calling excerpt with radius and omission as arguments is deprecated. " \
163
+ "Please call with :radius => #{args[0]}#{", :omission => '#{args[1]}'" if args[1]} instead.", caller
164
+
159
165
  options[:radius] = args[0] || 100
160
166
  options[:omission] = args[1] || "..."
161
167
  end
@@ -217,6 +223,9 @@ module ActionView
217
223
  def word_wrap(text, *args)
218
224
  options = args.extract_options!
219
225
  unless args.blank?
226
+ ActiveSupport::Deprecation.warn "Calling word_wrap with line_width as an argument is deprecated. " \
227
+ "Please call with :line_width => #{args[0]} instead.", caller
228
+
220
229
  options[:line_width] = args[0] || 80
221
230
  end
222
231
  options.reverse_merge!(:line_width => 80)
@@ -301,7 +301,7 @@ module ActionView
301
301
  # # <div><input value="Create" type="submit" /></div>
302
302
  # # </form>"
303
303
  #
304
- #
304
+ #
305
305
  # <%= button_to "Delete Image", { :action => "delete", :id => @image.id },
306
306
  # :confirm => "Are you sure?", :method => :delete %>
307
307
  # # => "<form method="post" action="/images/delete/1" class="button_to">
@@ -317,7 +317,7 @@ module ActionView
317
317
  # # => "<form class='button_to' method='post' action='http://www.example.com' data-remote='true'>
318
318
  # # <div>
319
319
  # # <input name='_method' value='delete' type='hidden' />
320
- # # <input value='Destroy' type='submit' disable_with='loading...' data-confirm='Are you sure?' />
320
+ # # <input value='Destroy' type='submit' data-disable-with='loading...' data-confirm='Are you sure?' />
321
321
  # # </div>
322
322
  # # </form>"
323
323
  # #
@@ -333,9 +333,9 @@ module ActionView
333
333
  form_method = method.to_s == 'get' ? 'get' : 'post'
334
334
  form_options = html_options.delete('form') || {}
335
335
  form_options[:class] ||= html_options.delete('form_class') || 'button_to'
336
-
336
+
337
337
  remote = html_options.delete('remote')
338
-
338
+
339
339
  request_token_tag = ''
340
340
  if form_method == 'post' && protect_against_forgery?
341
341
  request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
@@ -350,7 +350,7 @@ module ActionView
350
350
 
351
351
  form_options.merge!(:method => form_method, :action => url)
352
352
  form_options.merge!("data-remote" => "true") if remote
353
-
353
+
354
354
  "#{tag(:form, form_options, true)}<div>#{method_tag}#{tag("input", html_options)}#{request_token_tag}</div></form>".html_safe
355
355
  end
356
356
 
@@ -622,7 +622,12 @@ module ActionView
622
622
  confirm = html_options.delete('confirm')
623
623
  method = html_options.delete('method')
624
624
 
625
- html_options["data-disable-with"] = disable_with if disable_with
625
+ if disable_with
626
+ ActiveSupport::Deprecation.warn ":disable_with option is deprecated and will be removed from Rails 4.0. Use 'data-disable-with' instead"
627
+
628
+ html_options["data-disable-with"] = disable_with
629
+ end
630
+
626
631
  html_options["data-confirm"] = confirm if confirm
627
632
  add_method_to_attributes!(html_options, method) if method
628
633
 
@@ -407,7 +407,7 @@ module ActionView
407
407
  end
408
408
 
409
409
  def retrieve_variable(path)
410
- variable = @options[:as].try(:to_sym) || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym
410
+ variable = @options.fetch(:as) { path[%r'_?(\w+)(\.\w+)*$', 1] }.try(:to_sym)
411
411
  variable_counter = :"#{variable}_counter" if @collection
412
412
  [variable, variable_counter]
413
413
  end
@@ -2,6 +2,7 @@ require 'active_support/core_ext/array/wrap'
2
2
  require 'active_support/core_ext/object/blank'
3
3
  require 'active_support/core_ext/object/try'
4
4
  require 'active_support/core_ext/kernel/singleton_class'
5
+ require 'thread'
5
6
 
6
7
  module ActionView
7
8
  # = Action View Template
@@ -123,6 +124,7 @@ module ActionView
123
124
  @virtual_path = details[:virtual_path]
124
125
  @updated_at = details[:updated_at] || Time.now
125
126
  @formats = Array.wrap(format).map { |f| f.is_a?(Mime::Type) ? f.ref : f }
127
+ @compile_mutex = Mutex.new
126
128
  end
127
129
 
128
130
  # Returns if the underlying handler supports streaming. If so,
@@ -224,18 +226,28 @@ module ActionView
224
226
  def compile!(view) #:nodoc:
225
227
  return if @compiled
226
228
 
227
- if view.is_a?(ActionView::CompiledTemplates)
228
- mod = ActionView::CompiledTemplates
229
- else
230
- mod = view.singleton_class
231
- end
229
+ # Templates can be used concurrently in threaded environments
230
+ # so compilation and any instance variable modification must
231
+ # be synchronized
232
+ @compile_mutex.synchronize do
233
+ # Any thread holding this lock will be compiling the template needed
234
+ # by the threads waiting. So re-check the @compiled flag to avoid
235
+ # re-compilation
236
+ return if @compiled
237
+
238
+ if view.is_a?(ActionView::CompiledTemplates)
239
+ mod = ActionView::CompiledTemplates
240
+ else
241
+ mod = view.singleton_class
242
+ end
232
243
 
233
- compile(view, mod)
244
+ compile(view, mod)
234
245
 
235
- # Just discard the source if we have a virtual path. This
236
- # means we can get the template back.
237
- @source = nil if @virtual_path
238
- @compiled = true
246
+ # Just discard the source if we have a virtual path. This
247
+ # means we can get the template back.
248
+ @source = nil if @virtual_path
249
+ @compiled = true
250
+ end
239
251
  end
240
252
 
241
253
  # Among other things, this method is responsible for properly setting
@@ -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.join("\n").html_safe
34
+ end.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.join("\n").html_safe
51
+ end.uniq.join("\n").html_safe
52
52
  end
53
53
 
54
54
  def asset_path(source, options = {})
@@ -155,8 +155,13 @@ module Sprockets
155
155
  end
156
156
 
157
157
  def rewrite_extension(source, dir, ext)
158
- if ext && File.extname(source) != ".#{ext}"
159
- "#{source}.#{ext}"
158
+ source_ext = File.extname(source)
159
+ if ext && source_ext != ".#{ext}"
160
+ if !source_ext.empty? && asset_environment[source]
161
+ source
162
+ else
163
+ "#{source}.#{ext}"
164
+ end
160
165
  else
161
166
  source
162
167
  end
@@ -16,6 +16,9 @@ module Sprockets
16
16
  def compile
17
17
  manifest = {}
18
18
  env.each_logical_path do |logical_path|
19
+ if File.basename(logical_path)[/[^\.]+/, 0] == 'index'
20
+ logical_path.sub!(/\/index\./, '.')
21
+ end
19
22
  next unless compile_path?(logical_path)
20
23
  if asset = env.find_asset(logical_path)
21
24
  manifest[logical_path] = write_asset(asset)
metadata CHANGED
@@ -1,13 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionpack
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
5
- prerelease: false
4
+ hash: -1667650488
5
+ prerelease: 6
6
6
  segments:
7
7
  - 3
8
8
  - 2
9
- - 3
10
- version: 3.2.3
9
+ - 4
10
+ - rc
11
+ - 1
12
+ version: 3.2.4.rc1
11
13
  platform: ruby
12
14
  authors:
13
15
  - David Heinemeier Hansson
@@ -15,43 +17,48 @@ autorequire:
15
17
  bindir: bin
16
18
  cert_chain: []
17
19
 
18
- date: 2012-03-30 00:00:00 -03:00
19
- default_executable:
20
+ date: 2012-05-28 00:00:00 Z
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
22
- version_requirements: &id001 !ruby/object:Gem::Requirement
23
+ name: activesupport
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
23
26
  none: false
24
27
  requirements:
25
28
  - - "="
26
29
  - !ruby/object:Gem::Version
27
- hash: 9
30
+ hash: -1667650488
28
31
  segments:
29
32
  - 3
30
33
  - 2
31
- - 3
32
- version: 3.2.3
33
- requirement: *id001
34
+ - 4
35
+ - rc
36
+ - 1
37
+ version: 3.2.4.rc1
34
38
  type: :runtime
35
- name: activesupport
36
- prerelease: false
39
+ version_requirements: *id001
37
40
  - !ruby/object:Gem::Dependency
38
- version_requirements: &id002 !ruby/object:Gem::Requirement
41
+ name: activemodel
42
+ prerelease: false
43
+ requirement: &id002 !ruby/object:Gem::Requirement
39
44
  none: false
40
45
  requirements:
41
46
  - - "="
42
47
  - !ruby/object:Gem::Version
43
- hash: 9
48
+ hash: -1667650488
44
49
  segments:
45
50
  - 3
46
51
  - 2
47
- - 3
48
- version: 3.2.3
49
- requirement: *id002
52
+ - 4
53
+ - rc
54
+ - 1
55
+ version: 3.2.4.rc1
50
56
  type: :runtime
51
- name: activemodel
52
- prerelease: false
57
+ version_requirements: *id002
53
58
  - !ruby/object:Gem::Dependency
54
- version_requirements: &id003 !ruby/object:Gem::Requirement
59
+ name: rack-cache
60
+ prerelease: false
61
+ requirement: &id003 !ruby/object:Gem::Requirement
55
62
  none: false
56
63
  requirements:
57
64
  - - ~>
@@ -61,12 +68,12 @@ dependencies:
61
68
  - 1
62
69
  - 2
63
70
  version: "1.2"
64
- requirement: *id003
65
71
  type: :runtime
66
- name: rack-cache
67
- prerelease: false
72
+ version_requirements: *id003
68
73
  - !ruby/object:Gem::Dependency
69
- version_requirements: &id004 !ruby/object:Gem::Requirement
74
+ name: builder
75
+ prerelease: false
76
+ requirement: &id004 !ruby/object:Gem::Requirement
70
77
  none: false
71
78
  requirements:
72
79
  - - ~>
@@ -77,12 +84,12 @@ dependencies:
77
84
  - 0
78
85
  - 0
79
86
  version: 3.0.0
80
- requirement: *id004
81
87
  type: :runtime
82
- name: builder
83
- prerelease: false
88
+ version_requirements: *id004
84
89
  - !ruby/object:Gem::Dependency
85
- version_requirements: &id005 !ruby/object:Gem::Requirement
90
+ name: rack
91
+ prerelease: false
92
+ requirement: &id005 !ruby/object:Gem::Requirement
86
93
  none: false
87
94
  requirements:
88
95
  - - ~>
@@ -93,12 +100,12 @@ dependencies:
93
100
  - 4
94
101
  - 0
95
102
  version: 1.4.0
96
- requirement: *id005
97
103
  type: :runtime
98
- name: rack
99
- prerelease: false
104
+ version_requirements: *id005
100
105
  - !ruby/object:Gem::Dependency
101
- version_requirements: &id006 !ruby/object:Gem::Requirement
106
+ name: rack-test
107
+ prerelease: false
108
+ requirement: &id006 !ruby/object:Gem::Requirement
102
109
  none: false
103
110
  requirements:
104
111
  - - ~>
@@ -109,12 +116,12 @@ dependencies:
109
116
  - 6
110
117
  - 1
111
118
  version: 0.6.1
112
- requirement: *id006
113
119
  type: :runtime
114
- name: rack-test
115
- prerelease: false
120
+ version_requirements: *id006
116
121
  - !ruby/object:Gem::Dependency
117
- version_requirements: &id007 !ruby/object:Gem::Requirement
122
+ name: journey
123
+ prerelease: false
124
+ requirement: &id007 !ruby/object:Gem::Requirement
118
125
  none: false
119
126
  requirements:
120
127
  - - ~>
@@ -125,28 +132,28 @@ dependencies:
125
132
  - 0
126
133
  - 1
127
134
  version: 1.0.1
128
- requirement: *id007
129
135
  type: :runtime
130
- name: journey
131
- prerelease: false
136
+ version_requirements: *id007
132
137
  - !ruby/object:Gem::Dependency
133
- version_requirements: &id008 !ruby/object:Gem::Requirement
138
+ name: sprockets
139
+ prerelease: false
140
+ requirement: &id008 !ruby/object:Gem::Requirement
134
141
  none: false
135
142
  requirements:
136
143
  - - ~>
137
144
  - !ruby/object:Gem::Version
138
- hash: 15
145
+ hash: 13
139
146
  segments:
140
147
  - 2
141
148
  - 1
142
- - 2
143
- version: 2.1.2
144
- requirement: *id008
149
+ - 3
150
+ version: 2.1.3
145
151
  type: :runtime
146
- name: sprockets
147
- prerelease: false
152
+ version_requirements: *id008
148
153
  - !ruby/object:Gem::Dependency
149
- version_requirements: &id009 !ruby/object:Gem::Requirement
154
+ name: erubis
155
+ prerelease: false
156
+ requirement: &id009 !ruby/object:Gem::Requirement
150
157
  none: false
151
158
  requirements:
152
159
  - - ~>
@@ -157,12 +164,12 @@ dependencies:
157
164
  - 7
158
165
  - 0
159
166
  version: 2.7.0
160
- requirement: *id009
161
167
  type: :runtime
162
- name: erubis
163
- prerelease: false
168
+ version_requirements: *id009
164
169
  - !ruby/object:Gem::Dependency
165
- version_requirements: &id010 !ruby/object:Gem::Requirement
170
+ name: tzinfo
171
+ prerelease: false
172
+ requirement: &id010 !ruby/object:Gem::Requirement
166
173
  none: false
167
174
  requirements:
168
175
  - - ~>
@@ -173,10 +180,8 @@ dependencies:
173
180
  - 3
174
181
  - 29
175
182
  version: 0.3.29
176
- requirement: *id010
177
183
  type: :development
178
- name: tzinfo
179
- prerelease: false
184
+ version_requirements: *id010
180
185
  description: Web apps on Rails. Simple, battle-tested conventions for building and testing MVC web applications. Works with any Rack-compatible server.
181
186
  email: david@loudthinking.com
182
187
  executables: []
@@ -377,7 +382,6 @@ files:
377
382
  - lib/sprockets/helpers.rb
378
383
  - lib/sprockets/railtie.rb
379
384
  - lib/sprockets/static_compiler.rb
380
- has_rdoc: true
381
385
  homepage: http://www.rubyonrails.org
382
386
  licenses: []
383
387
 
@@ -400,16 +404,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
400
404
  required_rubygems_version: !ruby/object:Gem::Requirement
401
405
  none: false
402
406
  requirements:
403
- - - ">="
407
+ - - ">"
404
408
  - !ruby/object:Gem::Version
405
- hash: 3
409
+ hash: 25
406
410
  segments:
407
- - 0
408
- version: "0"
411
+ - 1
412
+ - 3
413
+ - 1
414
+ version: 1.3.1
409
415
  requirements:
410
416
  - none
411
417
  rubyforge_project:
412
- rubygems_version: 1.3.7
418
+ rubygems_version: 1.8.22
413
419
  signing_key:
414
420
  specification_version: 3
415
421
  summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).