diff options
Diffstat (limited to 'actionpack/lib')
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 |