aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb4
-rw-r--r--actionpack/lib/action_controller/metal/head.rb2
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb11
-rw-r--r--actionpack/lib/action_controller/vendor/html-scanner/html/node.rb12
-rw-r--r--actionpack/lib/action_dispatch/http/upload.rb49
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/route.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb23
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb6
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb76
-rw-r--r--actionpack/lib/action_view/test_case.rb6
12 files changed, 104 insertions, 97 deletions
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index 797ad846f6..8930c13a68 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -17,7 +17,7 @@ module ActionController
#
# def show
# @article = Article.find(params[:id])
- # fresh_when(:etag => @article, :last_modified => @article.created_at.utc, :public => true)
+ # fresh_when(:etag => @article, :last_modified => @article.created_at, :public => true)
# end
#
# This will render the show template if the request isn't sending a matching etag or
@@ -48,7 +48,7 @@ module ActionController
# def show
# @article = Article.find(params[:id])
#
- # if stale?(:etag => @article, :last_modified => @article.created_at.utc)
+ # if stale?(:etag => @article, :last_modified => @article.created_at)
# @statistics = @article.really_expensive_call
# respond_to do |format|
# # all the supported formats
diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb
index a5c9910d68..2b4a3b9392 100644
--- a/actionpack/lib/action_controller/metal/head.rb
+++ b/actionpack/lib/action_controller/metal/head.rb
@@ -22,7 +22,7 @@ module ActionController
location = options.delete(:location)
options.each do |key, value|
- headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s
+ headers[key.to_s.dasherize.split('-').each { |v| v[0] = v[0].chr.upcase }.join('-')] = value.to_s
end
self.status = status
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 1d74521e4f..251b1a8a8b 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -30,7 +30,7 @@ module ActionController
#
#
# === Advanced \Basic example
- #
+ #
# Here is a more advanced \Basic example where only Atom feeds and the XML API is protected by HTTP authentication,
# the regular HTML interface is protected by a session approach:
#
@@ -98,7 +98,7 @@ module ActionController
# end
#
# === Notes
- #
+ #
# The +authenticate_or_request_with_http_digest+ block must return the user's password
# or the ha1 digest hash so the framework can appropriately hash to check the user's
# credentials. Returning +nil+ will cause authentication to fail.
@@ -222,11 +222,10 @@ module ActionController
end
def decode_credentials(header)
- header.to_s.gsub(/^Digest\s+/,'').split(',').inject({}) do |hash, pair|
+ Hash[header.to_s.gsub(/^Digest\s+/,'').split(',').map do |pair|
key, value = pair.split('=', 2)
- hash[key.strip.to_sym] = value.to_s.gsub(/^"|"$/,'').gsub(/'/, '')
- hash
- end
+ [key.strip.to_sym, value.to_s.gsub(/^"|"$/,'').gsub(/'/, '')]
+ end]
end
def authentication_header(controller, realm)
diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb
index 0eaad2b911..85250721e7 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/node.rb
@@ -38,18 +38,14 @@ module HTML #:nodoc:
private
def keys_to_strings(hash)
- hash.keys.inject({}) do |h,k|
- h[k.to_s] = hash[k]
- h
- end
+ Hash[hash.keys.map {|k| [k.to_s, hash[k]]}]
end
def keys_to_symbols(hash)
- hash.keys.inject({}) do |h,k|
+ Hash[hash.keys.map do |k|
raise "illegal key #{k.inspect}" unless k.respond_to?(:to_sym)
- h[k.to_sym] = hash[k]
- h
- end
+ [k.to_sym, hash[k]]
+ end]
end
end
diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb
index 8ee4b81cdd..49465d820e 100644
--- a/actionpack/lib/action_dispatch/http/upload.rb
+++ b/actionpack/lib/action_dispatch/http/upload.rb
@@ -2,32 +2,27 @@ require 'active_support/core_ext/object/blank'
module ActionDispatch
module Http
- module UploadedFile
- def self.extended(object)
- object.class_eval do
- attr_accessor :original_path, :content_type
- alias_method :local_path, :path if method_defined?(:path)
- end
- end
+ class UploadedFile < Tempfile
+ attr_accessor :original_filename, :content_type, :tempfile, :headers
- # Take the basename of the upload's original filename.
- # This handles the full Windows paths given by Internet Explorer
- # (and perhaps other broken user agents) without affecting
- # those which give the lone filename.
- # The Windows regexp is adapted from Perl's File::Basename.
- def original_filename
- unless defined? @original_filename
- @original_filename =
- unless original_path.blank?
- if original_path =~ /^(?:.*[:\\\/])?(.*)/m
- $1
- else
- File.basename original_path
- end
- end
+ def initialize(hash)
+ @original_filename = hash[:filename]
+ @content_type = hash[:type]
+ @headers = hash[:head]
+
+ # To the untrained eye, this may appear as insanity. Given the alternatives,
+ # such as busting the method cache on every request or breaking backwards
+ # compatibility with is_a?(Tempfile), this solution is the best available
+ # option.
+ #
+ # TODO: Deprecate is_a?(Tempfile) and define a real API for this parameter
+ tempfile = hash[:tempfile]
+ tempfile.instance_variables.each do |ivar|
+ instance_variable_set(ivar, tempfile.instance_variable_get(ivar))
end
- @original_filename
end
+
+ alias local_path path
end
module Upload
@@ -35,11 +30,7 @@ module ActionDispatch
# file upload hash with UploadedFile objects
def normalize_parameters(value)
if Hash === value && value.has_key?(:tempfile)
- upload = value[:tempfile]
- upload.extend(UploadedFile)
- upload.original_path = value[:filename]
- upload.content_type = value[:type]
- upload
+ UploadedFile.new(value)
else
super
end
@@ -47,4 +38,4 @@ module ActionDispatch
private :normalize_parameters
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 8a161b0837..fe85acb94e 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -149,6 +149,10 @@ module ActionDispatch
controller = [@scope[:module], controller].compact.join("/").presence
end
+ if controller.is_a?(String) && controller =~ %r{\A/}
+ raise ArgumentError, "controller name should not start with a slash"
+ end
+
controller = controller.to_s unless controller.is_a?(Regexp)
action = action.to_s unless action.is_a?(Regexp)
diff --git a/actionpack/lib/action_dispatch/routing/route.rb b/actionpack/lib/action_dispatch/routing/route.rb
index aefebf8f80..f91a48e16c 100644
--- a/actionpack/lib/action_dispatch/routing/route.rb
+++ b/actionpack/lib/action_dispatch/routing/route.rb
@@ -21,11 +21,7 @@ module ActionDispatch
conditions[:path_info] = ::Rack::Mount::Strexp.compile(path, requirements, SEPARATORS, anchor)
end
- @conditions = conditions.inject({}) { |h, (k, v)|
- h[k] = Rack::Mount::RegexpWithNamedGroups.new(v)
- h
- }
-
+ @conditions = Hash[conditions.map { |k,v| [k, Rack::Mount::RegexpWithNamedGroups.new(v)] }]
@conditions.delete_if{ |k,v| k != :path_info && !valid_condition?(k) }
@requirements.delete_if{ |k,v| !valid_condition?(k) }
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 835ba03784..1a5f21bd09 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -217,27 +217,35 @@ module ActionDispatch
self.valid_conditions.delete(:id)
self.valid_conditions.push(:controller, :action)
+ @append = []
@disable_clear_and_finalize = false
clear!
end
def draw(&block)
clear! unless @disable_clear_and_finalize
+ eval_block(block)
+ finalize! unless @disable_clear_and_finalize
+
+ nil
+ end
+
+ def append(&block)
+ @append << block
+ end
+ def eval_block(block)
mapper = Mapper.new(self)
if default_scope
mapper.with_default_scope(default_scope, &block)
else
mapper.instance_exec(&block)
end
-
- finalize! unless @disable_clear_and_finalize
-
- nil
end
def finalize!
return if @finalized
+ @append.each { |blk| eval_block(blk) }
@finalized = true
@set.freeze
end
@@ -558,13 +566,8 @@ module ActionDispatch
keys = options.delete(:_positional_keys)
keys -= options.keys if args.size < keys.size - 1 # take format into account
- args = args.zip(keys).inject({}) do |h, (v, k)|
- h[k] = v
- h
- end
-
# Tell url_for to skip default_url_options
- options.merge!(args)
+ options.merge!(Hash[args.zip(keys).map { |v, k| [k, v] }])
end
def rewrite_authentication(options)
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 590ebbf364..a681c9a5b6 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -257,17 +257,19 @@ module ActionDispatch
end
end
+ port = host.split(':')[1]
+
env = {
:method => method,
:params => parameters,
"SERVER_NAME" => host.split(':')[0],
- "SERVER_PORT" => (https? ? "443" : "80"),
+ "SERVER_PORT" => (port ? port : (https? ? "443" : "80")),
"HTTPS" => https? ? "on" : "off",
"rack.url_scheme" => https? ? "https" : "http",
"REQUEST_URI" => path,
- "HTTP_HOST" => host,
+ "HTTP_HOST" => [host, port].compact.join(':'),
"REMOTE_ADDR" => remote_addr,
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
"HTTP_ACCEPT" => accept
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index fdc40c8f2e..687cb83d75 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -827,7 +827,7 @@ module ActionView
def expand_javascript_sources(sources, recursive = false)
if sources.include?(:all)
- all_javascript_files = collect_asset_files(config.javascripts_dir, ('**' if recursive), '*.js')
+ all_javascript_files = (collect_asset_files(config.javascripts_dir, ('**' if recursive), '*.js') - ['application']) << 'application'
((determine_source(:defaults, @@javascript_expansions).dup & all_javascript_files) + all_javascript_files).uniq
else
expanded_sources = sources.collect do |source|
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 3cc412de63..0937075edf 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -317,8 +317,11 @@ module ActionView
options[:html] ||= {}
options[:html][:remote] = options.delete(:remote)
- output = form_tag(options.delete(:url) || {}, options.delete(:html) || {})
- output << fields_for(object_name, object, options, &proc)
+ builder = options[:parent_builder] = instantiate_builder(object_name, object, options, &proc)
+ fields_for = fields_for(object_name, object, options, &proc)
+ default_options = builder.multipart? ? { :multipart => true } : {}
+ output = form_tag(options.delete(:url) || {}, default_options.merge!(options.delete(:html) || {}))
+ output << fields_for
output.safe_concat('</form>')
end
@@ -339,8 +342,8 @@ module ActionView
options[:html] ||= {}
options[:html].reverse_merge!(html_options)
- options[:url] ||= options[:format] ? \
- polymorphic_path(object_or_array, :format => options.delete(:format)) : \
+ options[:url] ||= options[:format] ?
+ polymorphic_path(object_or_array, :format => options.delete(:format)) :
polymorphic_path(object_or_array)
end
@@ -529,22 +532,7 @@ module ActionView
# <% end %>
# <% end %>
def fields_for(record, record_object = nil, options = nil, &block)
- raise ArgumentError, "Missing block" unless block_given?
-
- options, record_object = record_object, nil if record_object.is_a?(Hash)
- options ||= {}
-
- case record
- when String, Symbol
- object = record_object
- object_name = record
- else
- object = record
- object_name = ActiveModel::Naming.param_key(object)
- end
-
- builder = options[:builder] || ActionView::Base.default_form_builder
- capture(builder.new(object_name, object, self, options, block), &block)
+ capture(instantiate_builder(record, record_object, options, &block), &block)
end
# Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object
@@ -850,6 +838,25 @@ module ActionView
def range_field(object_name, method, options = {})
InstanceTag.new(object_name, method, self, options.delete(:object)).to_number_field_tag("range", options)
end
+
+ private
+
+ def instantiate_builder(record, record_object = nil, options = nil, &block)
+ options, record_object = record_object, nil if record_object.is_a?(Hash)
+ options ||= {}
+
+ case record
+ when String, Symbol
+ object = record_object
+ object_name = record
+ else
+ object = record
+ object_name = ActiveModel::Naming.param_key(object)
+ end
+
+ builder = options[:builder] || ActionView::Base.default_form_builder
+ builder.new(object_name, object, self, options, block)
+ end
end
module InstanceTagMethods #:nodoc:
@@ -858,9 +865,9 @@ module ActionView
attr_reader :method_name, :object_name
- DEFAULT_FIELD_OPTIONS = { "size" => 30 }.freeze
- DEFAULT_RADIO_OPTIONS = { }.freeze
- DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }.freeze
+ DEFAULT_FIELD_OPTIONS = { "size" => 30 }
+ DEFAULT_RADIO_OPTIONS = { }
+ DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }
def initialize(object_name, method_name, template_object, object = nil)
@object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup
@@ -1114,6 +1121,14 @@ module ActionView
attr_accessor :object_name, :object, :options
+ attr_reader :multipart, :parent_builder
+ alias :multipart? :multipart
+
+ def multipart=(multipart)
+ @multipart = multipart
+ parent_builder.multipart = multipart if parent_builder
+ end
+
def self.model_name
@model_name ||= Struct.new(:partial_path).new(name.demodulize.underscore.sub!(/_builder$/, ''))
end
@@ -1125,6 +1140,7 @@ module ActionView
def initialize(object_name, object, template, options, proc)
@nested_child_index = {}
@object_name, @object, @template, @options, @proc = object_name, object, template, options, proc
+ @parent_builder = options[:parent_builder]
@default_options = @options ? @options.slice(:index) : {}
if @object_name.to_s.match(/\[\]$/)
if object ||= @template.instance_variable_get("@#{Regexp.last_match.pre_match}") and object.respond_to?(:to_param)
@@ -1133,9 +1149,10 @@ module ActionView
raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
end
end
+ @multipart = nil
end
- (field_helpers - %w(label check_box radio_button fields_for hidden_field)).each do |selector|
+ (field_helpers - %w(label check_box radio_button fields_for hidden_field file_field)).each do |selector|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{selector}(method, options = {}) # def text_field(method, options = {})
@template.send( # @template.send(
@@ -1157,10 +1174,9 @@ module ActionView
index = ""
end
- if options[:builder]
- args << {} unless args.last.is_a?(Hash)
- args.last[:builder] ||= options[:builder]
- end
+ args << {} unless args.last.is_a?(Hash)
+ args.last[:builder] ||= options[:builder]
+ args.last[:parent_builder] = self
case record_or_name_or_array
when String, Symbol
@@ -1199,6 +1215,10 @@ module ActionView
@template.hidden_field(@object_name, method, objectify_options(options))
end
+ def file_field(method, options = {})
+ self.multipart = true
+ @template.file_field(@object_name, method, objectify_options(options))
+ end
# Add the submit button for the given form. When no value is given, it checks
# if the object is a new resource or not to create the proper label:
#
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 2c2661df26..ff35fb7df4 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -189,11 +189,7 @@ module ActionView
end
def _assigns
- _instance_variables.inject({}) do |hash, var|
- name = var[1..-1].to_sym
- hash[name] = instance_variable_get(var)
- hash
- end
+ _instance_variables.map { |var| [var[1..-1].to_sym, instance_variable_get(var)] }
end
def _routes