diff options
author | Xavier Noria <fxn@hashref.com> | 2010-07-22 01:29:18 +0200 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2010-07-22 01:29:18 +0200 |
commit | 919eb200a9a0969c444b938d08eb4661d41ba986 (patch) | |
tree | 329cbe815d549275cc0dc6aa0f75c18d8954f105 /actionpack | |
parent | 56669ec3048de316918ec5ad554fff83d757911b (diff) | |
parent | b456877cfb7e0cb0bab9ffd5674abd23caba0ab4 (diff) | |
download | rails-919eb200a9a0969c444b938d08eb4661d41ba986.tar.gz rails-919eb200a9a0969c444b938d08eb4661d41ba986.tar.bz2 rails-919eb200a9a0969c444b938d08eb4661d41ba986.zip |
Merge remote branch 'rails/master'
Diffstat (limited to 'actionpack')
44 files changed, 436 insertions, 466 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 32aba2091a..6e07516a58 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0.0 [Release Candidate] (unreleased)* +* Allow stylesheet/javascript extensions to be changed through railties. [Josh Kalderimis] + * link_to, button_to, and tag/tag_options now rely on html_escape instead of escape_once. [fxn] * url_for returns always unescaped strings, and the :escape option is gone. [fxn] diff --git a/actionpack/README b/actionpack/README.rdoc index 1a59f728cc..272feb63d0 100644 --- a/actionpack/README +++ b/actionpack/README.rdoc @@ -19,15 +19,6 @@ the HTML. To avoid cluttering the templates with code, a bunch of helper classes provide common behavior for forms, dates, and strings. And it's easy to add specific helpers to keep the separation as the application evolves. -Note: Some of the features, such as scaffolding and form building, are tied to -ActiveRecord[http://activerecord.rubyonrails.org] (an object-relational -mapping package), but that doesn't mean that Action Pack depends on Active -Record. Action Pack is an independent package that can be used with any sort -of backend (Instiki[http://www.instiki.org], which is based on an older version -of Action Pack, used Madeleine for example). Read more about the role Action -Pack can play when used together with Active Record on -http://www.rubyonrails.org. - A short rundown of the major features: * Actions grouped in controller as methods instead of separate command objects @@ -366,22 +357,13 @@ an URL such as /weblog/5 (where 5 is the id of the post). == Download -The latest version of Action Pack can be found at - -* http://rubyforge.org/project/showfiles.php?group_id=249 - -Documentation can be found at - -* http://api.rubyonrails.com - - -== Installation +The latest version of Action Pack can be installed with Rubygems: -You can install Action Pack with the following command. +* gem install actionpack - % [sudo] ruby install.rb +Documentation can be found at -from its distribution directory. +* http://api.rubyonrails.org == License diff --git a/actionpack/Rakefile b/actionpack/Rakefile index aed5278e38..3a988d832d 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -47,7 +47,7 @@ Rake::RDocTask.new { |rdoc| if ENV['DOC_FILES'] rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/)) else - rdoc.rdoc_files.include('README', 'RUNNING_UNIT_TESTS', 'CHANGELOG') + rdoc.rdoc_files.include('README.rdoc', 'RUNNING_UNIT_TESTS', 'CHANGELOG') rdoc.rdoc_files.include(Dir['lib/**/*.rb'] - Dir['lib/*/vendor/**/*.rb']) rdoc.rdoc_files.exclude('lib/actionpack.rb') diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 9ce7ba5f02..99deff234c 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -13,7 +13,7 @@ Gem::Specification.new do |s| s.homepage = 'http://www.rubyonrails.org' s.rubyforge_project = 'actionpack' - s.files = Dir['CHANGELOG', 'README', 'MIT-LICENSE', 'lib/**/*'] + s.files = Dir['CHANGELOG', 'README.rdoc', 'MIT-LICENSE', 'lib/**/*'] s.require_path = 'lib' s.requirements << 'none' diff --git a/actionpack/install.rb b/actionpack/install.rb deleted file mode 100644 index d3b83c3b00..0000000000 --- a/actionpack/install.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'rbconfig' -require 'find' -require 'ftools' - -include Config - -# this was adapted from rdoc's install.rb by way of Log4r - -$sitedir = CONFIG["sitelibdir"] -unless $sitedir - version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"] - $libdir = File.join(CONFIG["libdir"], "ruby", version) - $sitedir = $:.find {|x| x =~ /site_ruby/ } - if !$sitedir - $sitedir = File.join($libdir, "site_ruby") - elsif $sitedir !~ Regexp.quote(version) - $sitedir = File.join($sitedir, version) - end -end - -# the actual gruntwork -Dir.chdir("lib") - -Find.find("action_controller", "action_controller.rb", "action_view", "action_view.rb") { |f| - if f[-3..-1] == ".rb" - File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true) - else - File::makedirs(File.join($sitedir, *f.split(/\//))) - end -}
\ No newline at end of file diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index 5990a1bbd0..c565c940a1 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -1,6 +1,7 @@ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) +require 'action_pack' require 'active_support/ruby/shim' require 'active_support/dependencies/autoload' require 'active_support/core_ext/class/attribute' diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 1bd4572a47..ca0e5d6ff6 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -6,7 +6,6 @@ module ActionController autoload :Base autoload :Caching - autoload :PolymorphicRoutes autoload :Metal autoload :Middleware diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 1a2cbaab65..1c6896d362 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -28,7 +28,6 @@ module ActionController SessionManagement, Caching, MimeResponds, - PolymorphicRoutes, ImplicitRender, Cookies, @@ -69,4 +68,4 @@ module ActionController end end -require "action_controller/deprecated/base"
\ No newline at end of file +require "action_controller/deprecated/base" diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb index b2c119d7e4..b08d9a8434 100644 --- a/actionpack/lib/action_controller/metal/instrumentation.rb +++ b/actionpack/lib/action_controller/metal/instrumentation.rb @@ -1,3 +1,4 @@ +require 'benchmark' require 'abstract_controller/logger' module ActionController diff --git a/actionpack/lib/action_controller/metal/rescue.rb b/actionpack/lib/action_controller/metal/rescue.rb index bbca1b2179..eb037aa1b0 100644 --- a/actionpack/lib/action_controller/metal/rescue.rb +++ b/actionpack/lib/action_controller/metal/rescue.rb @@ -3,6 +3,15 @@ module ActionController #:nodoc: extend ActiveSupport::Concern include ActiveSupport::Rescuable + def rescue_with_handler(exception) + if (exception.respond_to?(:original_exception) && + (orig_exception = exception.original_exception) && + handler_for_rescue(orig_exception)) + exception = orig_exception + end + super(exception) + end + private def process_action(*args) super diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb index 753af3dc58..d75b46dace 100644 --- a/actionpack/lib/action_controller/metal/streaming.rb +++ b/actionpack/lib/action_controller/metal/streaming.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/file/path' + module ActionController #:nodoc: # Methods for sending arbitrary data and for streaming files to the browser, # instead of rendering. diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/polymorphic_routes.rb deleted file mode 100644 index bee50a7a3b..0000000000 --- a/actionpack/lib/action_controller/polymorphic_routes.rb +++ /dev/null @@ -1,183 +0,0 @@ -module ActionController - # Polymorphic URL helpers are methods for smart resolution to a named route call when - # given an Active Record model instance. They are to be used in combination with - # ActionController::Resources. - # - # These methods are useful when you want to generate correct URL or path to a RESTful - # resource without having to know the exact type of the record in question. - # - # Nested resources and/or namespaces are also supported, as illustrated in the example: - # - # polymorphic_url([:admin, @article, @comment]) - # - # results in: - # - # admin_article_comment_url(@article, @comment) - # - # == Usage within the framework - # - # Polymorphic URL helpers are used in a number of places throughout the Rails framework: - # - # * <tt>url_for</tt>, so you can use it with a record as the argument, e.g. - # <tt>url_for(@article)</tt>; - # * ActionView::Helpers::FormHelper uses <tt>polymorphic_path</tt>, so you can write - # <tt>form_for(@article)</tt> without having to specify <tt>:url</tt> parameter for the form - # action; - # * <tt>redirect_to</tt> (which, in fact, uses <tt>url_for</tt>) so you can write - # <tt>redirect_to(post)</tt> in your controllers; - # * ActionView::Helpers::AtomFeedHelper, so you don't have to explicitly specify URLs - # for feed entries. - # - # == Prefixed polymorphic helpers - # - # In addition to <tt>polymorphic_url</tt> and <tt>polymorphic_path</tt> methods, a - # number of prefixed helpers are available as a shorthand to <tt>:action => "..."</tt> - # in options. Those are: - # - # * <tt>edit_polymorphic_url</tt>, <tt>edit_polymorphic_path</tt> - # * <tt>new_polymorphic_url</tt>, <tt>new_polymorphic_path</tt> - # - # Example usage: - # - # edit_polymorphic_path(@post) # => "/posts/1/edit" - # polymorphic_path(@post, :format => :pdf) # => "/posts/1.pdf" - module PolymorphicRoutes - # Constructs a call to a named RESTful route for the given record and returns the - # resulting URL string. For example: - # - # # calls post_url(post) - # polymorphic_url(post) # => "http://example.com/posts/1" - # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1" - # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1" - # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1" - # polymorphic_url(Comment) # => "http://example.com/comments" - # - # ==== Options - # - # * <tt>:action</tt> - Specifies the action prefix for the named route: - # <tt>:new</tt> or <tt>:edit</tt>. Default is no prefix. - # * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>. - # Default is <tt>:url</tt>. - # - # ==== Examples - # - # # an Article record - # polymorphic_url(record) # same as article_url(record) - # - # # a Comment record - # polymorphic_url(record) # same as comment_url(record) - # - # # it recognizes new records and maps to the collection - # record = Comment.new - # polymorphic_url(record) # same as comments_url() - # - # # the class of a record will also map to the collection - # polymorphic_url(Comment) # same as comments_url() - # - def polymorphic_url(record_or_hash_or_array, options = {}) - if record_or_hash_or_array.kind_of?(Array) - record_or_hash_or_array = record_or_hash_or_array.compact - record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1 - end - - record = extract_record(record_or_hash_or_array) - record = record.to_model if record.respond_to?(:to_model) - - args = case record_or_hash_or_array - when Hash; [ record_or_hash_or_array ] - when Array; record_or_hash_or_array.dup - else [ record_or_hash_or_array ] - end - - inflection = if options[:action].to_s == "new" - args.pop - :singular - elsif (record.respond_to?(:persisted?) && !record.persisted?) - args.pop - :plural - elsif record.is_a?(Class) - args.pop - :plural - else - :singular - end - - args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)} - named_route = build_named_route_call(record_or_hash_or_array, inflection, options) - - url_options = options.except(:action, :routing_type) - unless url_options.empty? - args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options - end - - __send__(named_route, *args) - end - - # Returns the path component of a URL for the given record. It uses - # <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>. - def polymorphic_path(record_or_hash_or_array, options = {}) - polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path)) - end - - %w(edit new).each do |action| - module_eval <<-EOT, __FILE__, __LINE__ + 1 - def #{action}_polymorphic_url(record_or_hash, options = {}) # def edit_polymorphic_url(record_or_hash, options = {}) - polymorphic_url( # polymorphic_url( - record_or_hash, # record_or_hash, - options.merge(:action => "#{action}")) # options.merge(:action => "edit")) - end # end - # - def #{action}_polymorphic_path(record_or_hash, options = {}) # def edit_polymorphic_path(record_or_hash, options = {}) - polymorphic_url( # polymorphic_url( - record_or_hash, # record_or_hash, - options.merge(:action => "#{action}", :routing_type => :path)) # options.merge(:action => "edit", :routing_type => :path)) - end # end - EOT - end - - private - def action_prefix(options) - options[:action] ? "#{options[:action]}_" : '' - end - - def routing_type(options) - options[:routing_type] || :url - end - - def build_named_route_call(records, inflection, options = {}) - unless records.is_a?(Array) - record = extract_record(records) - route = '' - else - record = records.pop - route = records.inject("") do |string, parent| - if parent.is_a?(Symbol) || parent.is_a?(String) - string << "#{parent}_" - else - string << RecordIdentifier.__send__("plural_class_name", parent).singularize - string << "_" - end - end - end - - if record.is_a?(Symbol) || record.is_a?(String) - route << "#{record}_" - else - route << RecordIdentifier.__send__("plural_class_name", record) - route = route.singularize if inflection == :singular - route << "_" - route << "index_" if RecordIdentifier.uncountable?(record) && inflection == :plural - end - - action_prefix(options) + route + routing_type(options).to_s - end - - def extract_record(record_or_hash_or_array) - case record_or_hash_or_array - when Array; record_or_hash_or_array.last - when Hash; record_or_hash_or_array[:id] - else record_or_hash_or_array - end - end - end -end diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb index d20c3b64c5..3de40b0de3 100644 --- a/actionpack/lib/action_controller/record_identifier.rb +++ b/actionpack/lib/action_controller/record_identifier.rb @@ -46,7 +46,7 @@ module ActionController # dom_class(post, :edit) # => "edit_post" # dom_class(Person, :edit) # => "edit_person" def dom_class(record_or_class, prefix = nil) - singular = singular_class_name(record_or_class) + singular = ActiveModel::Naming.singular(record_or_class) prefix ? "#{prefix}#{JOIN}#{singular}" : singular end @@ -67,6 +67,8 @@ module ActionController end end + protected + # Returns a string representation of the key attribute(s) that is suitable for use in an HTML DOM id. # This can be overwritten to customize the default generated string representation if desired. # If you need to read back a key from a dom_id in order to query for the underlying database record, @@ -85,34 +87,5 @@ module ActionController def sanitize_dom_id(candidate_id) candidate_id # TODO implement conversion to valid DOM id values end - - # Returns the plural class name of a record or class. Examples: - # - # plural_class_name(post) # => "posts" - # plural_class_name(Highrise::Person) # => "highrise_people" - def plural_class_name(record_or_class) - model_name_from_record_or_class(record_or_class).plural - end - - # Returns the singular class name of a record or class. Examples: - # - # singular_class_name(post) # => "post" - # singular_class_name(Highrise::Person) # => "highrise_person" - def singular_class_name(record_or_class) - model_name_from_record_or_class(record_or_class).singular - end - - # Identifies whether the class name of a record or class is uncountable. Examples: - # - # uncountable?(Sheep) # => true - # uncountable?(Post) => false - def uncountable?(record_or_class) - plural_class_name(record_or_class) == singular_class_name(record_or_class) - end - - private - def model_name_from_record_or_class(record_or_class) - (record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name - end end end diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index cdf81c6648..50d8e91c47 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -24,9 +24,14 @@ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) +activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__) +$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path) + require 'active_support' require 'active_support/dependencies/autoload' +require 'action_pack' +require 'active_model' require 'rack' module Rack @@ -63,6 +68,7 @@ module ActionDispatch autoload :Headers autoload :MimeNegotiation autoload :Parameters + autoload :ParameterFilter autoload :FilterParameters autoload :Upload autoload :UploadedFile, 'action_dispatch/http/upload' diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 152aaa2e67..1ab48ae04d 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -26,88 +26,32 @@ module ActionDispatch module FilterParameters extend ActiveSupport::Concern - @@compiled_parameter_filter_for = {} + @@parameter_filter_for = {} # Return a hash of parameters with all sensitive data replaced. def filtered_parameters - @filtered_parameters ||= if filtering_parameters? - process_parameter_filter(parameters) - else - parameters.dup - end + @filtered_parameters ||= parameter_filter.filter(parameters) end - alias :fitered_params :filtered_parameters # Return a hash of request.env with all sensitive data replaced. def filtered_env - filtered_env = @env.dup - filtered_env.each do |key, value| - if (key =~ /RAW_POST_DATA/i) - filtered_env[key] = '[FILTERED]' - elsif value.is_a?(Hash) - filtered_env[key] = process_parameter_filter(value) - end - end - filtered_env + @filtered_env ||= env_filter.filter(@env) end protected - def filtering_parameters? #:nodoc: - @env["action_dispatch.parameter_filter"].present? + def parameter_filter + parameter_filter_for(@env["action_dispatch.parameter_filter"]) end - def process_parameter_filter(params) #:nodoc: - compiled_parameter_filter_for(@env["action_dispatch.parameter_filter"]).call(params) + def env_filter + parameter_filter_for(Array.wrap(@env["action_dispatch.parameter_filter"]) << /RAW_POST_DATA/) end - def compile_parameter_filter(filters) #:nodoc: - strings, regexps, blocks = [], [], [] - - filters.each do |item| - case item - when NilClass - when Proc - blocks << item - when Regexp - regexps << item - else - strings << item.to_s - end - end - - regexps << Regexp.new(strings.join('|'), true) unless strings.empty? - [regexps, blocks] - end - - def compiled_parameter_filter_for(filters) #:nodoc: - @@compiled_parameter_filter_for[filters] ||= begin - regexps, blocks = compile_parameter_filter(filters) - - lambda do |original_params| - filtered_params = {} - - original_params.each do |key, value| - if regexps.find { |r| key =~ r } - value = '[FILTERED]' - elsif value.is_a?(Hash) - value = process_parameter_filter(value) - elsif value.is_a?(Array) - value = value.map { |v| v.is_a?(Hash) ? process_parameter_filter(v) : v } - elsif blocks.present? - key = key.dup - value = value.dup if value.duplicable? - blocks.each { |b| b.call(key, value) } - end - - filtered_params[key] = value - end - - filtered_params - end - end + def parameter_filter_for(filters) + @@parameter_filter_for[filters] ||= ParameterFilter.new(filters) end end end -end
\ No newline at end of file +end diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb new file mode 100644 index 0000000000..1480e8f77c --- /dev/null +++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb @@ -0,0 +1,72 @@ +module ActionDispatch + module Http + class ParameterFilter + + def initialize(filters) + @filters = filters + end + + def filter(params) + if enabled? + compiled_filter.call(params) + else + params.dup + end + end + + private + + def enabled? + @filters.present? + end + + def compiled_filter + @compiled_filter ||= begin + regexps, blocks = compile_filter + + lambda do |original_params| + filtered_params = {} + + original_params.each do |key, value| + if regexps.find { |r| key =~ r } + value = '[FILTERED]' + elsif value.is_a?(Hash) + value = filter(value) + elsif value.is_a?(Array) + value = value.map { |v| v.is_a?(Hash) ? filter(v) : v } + elsif blocks.present? + key = key.dup + value = value.dup if value.duplicable? + blocks.each { |b| b.call(key, value) } + end + + filtered_params[key] = value + end + + filtered_params + end + end + end + + def compile_filter + strings, regexps, blocks = [], [], [] + + @filters.each do |item| + case item + when NilClass + when Proc + blocks << item + when Regexp + regexps << item + else + strings << item.to_s + end + end + + regexps << Regexp.new(strings.join('|'), true) unless strings.empty? + [regexps, blocks] + end + + end + end +end diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 64f4d1d532..ad98249468 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -24,9 +24,9 @@ module ActionDispatch def [](key) if key == :id - load_session_id! unless super(:id) || has_session_id? + load_session_id! unless key?(:id) || has_session_id? end - super(key) + super end private @@ -191,8 +191,11 @@ module ActionDispatch def load_session(env) stale_session_check! do - sid = current_session_id(env) - sid, session = get_session(env, sid) + if sid = current_session_id(env) + sid, session = get_session(env, sid) + else + sid, session = generate_sid, {} + end [sid, session] end end diff --git a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb index 28e3dbd732..5304440418 100644 --- a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb @@ -25,7 +25,6 @@ module ActionDispatch private def get_session(env, sid) - sid ||= generate_sid begin session = @pool.get(sid) || {} rescue MemCache::MemCacheError, Errno::ECONNREFUSED diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 4618f3befc..41078eced7 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -46,7 +46,7 @@ module ActionDispatch end def insert(index, *args, &block) - index = self.index(index) unless index.is_a?(Integer) + index = assert_index(index, :before) middleware = self.class::Middleware.new(*args, &block) super(index, middleware) end @@ -54,9 +54,8 @@ module ActionDispatch alias_method :insert_before, :insert def insert_after(index, *args, &block) - i = index.is_a?(Integer) ? index : self.index(index) - raise "No such middleware to insert after: #{index.inspect}" unless i - insert(i + 1, *args, &block) + index = assert_index(index, :after) + insert(index + 1, *args, &block) end def swap(target, *args, &block) @@ -79,5 +78,13 @@ module ActionDispatch raise "MiddlewareStack#build requires an app" unless app reverse.inject(app) { |a, e| e.build(a) } end + + protected + + def assert_index(index, where) + i = index.is_a?(Integer) ? index : self.index(index) + raise "No such middleware to insert #{where}: #{index.inspect}" unless i + i + end end end diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 8afc685fdf..683dd72555 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -1,6 +1,5 @@ require 'active_support/core_ext/object/to_param' require 'active_support/core_ext/regexp' -require 'action_controller/polymorphic_routes' module ActionDispatch # = Routing @@ -217,13 +216,14 @@ module ActionDispatch autoload :Route, 'action_dispatch/routing/route' autoload :RouteSet, 'action_dispatch/routing/route_set' autoload :UrlFor, 'action_dispatch/routing/url_for' + autoload :PolymorphicRoutes, 'action_dispatch/routing/polymorphic_routes' SEPARATORS = %w( / . ? ) #:nodoc: HTTP_METHODS = [:get, :head, :post, :put, :delete, :options] #:nodoc: # A helper module to hold URL related helpers. module Helpers #:nodoc: - include ActionController::PolymorphicRoutes + include PolymorphicRoutes end end end diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb new file mode 100644 index 0000000000..31dba835ac --- /dev/null +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -0,0 +1,186 @@ +module ActionDispatch + module Routing + # Polymorphic URL helpers are methods for smart resolution to a named route call when + # given an Active Record model instance. They are to be used in combination with + # ActionController::Resources. + # + # These methods are useful when you want to generate correct URL or path to a RESTful + # resource without having to know the exact type of the record in question. + # + # Nested resources and/or namespaces are also supported, as illustrated in the example: + # + # polymorphic_url([:admin, @article, @comment]) + # + # results in: + # + # admin_article_comment_url(@article, @comment) + # + # == Usage within the framework + # + # Polymorphic URL helpers are used in a number of places throughout the Rails framework: + # + # * <tt>url_for</tt>, so you can use it with a record as the argument, e.g. + # <tt>url_for(@article)</tt>; + # * ActionView::Helpers::FormHelper uses <tt>polymorphic_path</tt>, so you can write + # <tt>form_for(@article)</tt> without having to specify <tt>:url</tt> parameter for the form + # action; + # * <tt>redirect_to</tt> (which, in fact, uses <tt>url_for</tt>) so you can write + # <tt>redirect_to(post)</tt> in your controllers; + # * ActionView::Helpers::AtomFeedHelper, so you don't have to explicitly specify URLs + # for feed entries. + # + # == Prefixed polymorphic helpers + # + # In addition to <tt>polymorphic_url</tt> and <tt>polymorphic_path</tt> methods, a + # number of prefixed helpers are available as a shorthand to <tt>:action => "..."</tt> + # in options. Those are: + # + # * <tt>edit_polymorphic_url</tt>, <tt>edit_polymorphic_path</tt> + # * <tt>new_polymorphic_url</tt>, <tt>new_polymorphic_path</tt> + # + # Example usage: + # + # edit_polymorphic_path(@post) # => "/posts/1/edit" + # polymorphic_path(@post, :format => :pdf) # => "/posts/1.pdf" + module PolymorphicRoutes + # Constructs a call to a named RESTful route for the given record and returns the + # resulting URL string. For example: + # + # # calls post_url(post) + # polymorphic_url(post) # => "http://example.com/posts/1" + # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1" + # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1" + # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1" + # polymorphic_url(Comment) # => "http://example.com/comments" + # + # ==== Options + # + # * <tt>:action</tt> - Specifies the action prefix for the named route: + # <tt>:new</tt> or <tt>:edit</tt>. Default is no prefix. + # * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>. + # Default is <tt>:url</tt>. + # + # ==== Examples + # + # # an Article record + # polymorphic_url(record) # same as article_url(record) + # + # # a Comment record + # polymorphic_url(record) # same as comment_url(record) + # + # # it recognizes new records and maps to the collection + # record = Comment.new + # polymorphic_url(record) # same as comments_url() + # + # # the class of a record will also map to the collection + # polymorphic_url(Comment) # same as comments_url() + # + def polymorphic_url(record_or_hash_or_array, options = {}) + if record_or_hash_or_array.kind_of?(Array) + record_or_hash_or_array = record_or_hash_or_array.compact + record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1 + end + + record = extract_record(record_or_hash_or_array) + record = record.to_model if record.respond_to?(:to_model) + + args = case record_or_hash_or_array + when Hash; [ record_or_hash_or_array ] + when Array; record_or_hash_or_array.dup + else [ record_or_hash_or_array ] + end + + inflection = if options[:action].to_s == "new" + args.pop + :singular + elsif (record.respond_to?(:persisted?) && !record.persisted?) + args.pop + :plural + elsif record.is_a?(Class) + args.pop + :plural + else + :singular + end + + args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)} + named_route = build_named_route_call(record_or_hash_or_array, inflection, options) + + url_options = options.except(:action, :routing_type) + unless url_options.empty? + args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options + end + + send(named_route, *args) + end + + # Returns the path component of a URL for the given record. It uses + # <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>. + def polymorphic_path(record_or_hash_or_array, options = {}) + polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path)) + end + + %w(edit new).each do |action| + module_eval <<-EOT, __FILE__, __LINE__ + 1 + def #{action}_polymorphic_url(record_or_hash, options = {}) # def edit_polymorphic_url(record_or_hash, options = {}) + polymorphic_url( # polymorphic_url( + record_or_hash, # record_or_hash, + options.merge(:action => "#{action}")) # options.merge(:action => "edit")) + end # end + # + def #{action}_polymorphic_path(record_or_hash, options = {}) # def edit_polymorphic_path(record_or_hash, options = {}) + polymorphic_url( # polymorphic_url( + record_or_hash, # record_or_hash, + options.merge(:action => "#{action}", :routing_type => :path)) # options.merge(:action => "edit", :routing_type => :path)) + end # end + EOT + end + + private + def action_prefix(options) + options[:action] ? "#{options[:action]}_" : '' + end + + def routing_type(options) + options[:routing_type] || :url + end + + def build_named_route_call(records, inflection, options = {}) + unless records.is_a?(Array) + record = extract_record(records) + route = '' + else + record = records.pop + route = records.inject("") do |string, parent| + if parent.is_a?(Symbol) || parent.is_a?(String) + string << "#{parent}_" + else + string << ActiveModel::Naming.plural(parent).singularize + string << "_" + end + end + end + + if record.is_a?(Symbol) || record.is_a?(String) + route << "#{record}_" + else + route << ActiveModel::Naming.plural(record) + route = route.singularize if inflection == :singular + route << "_" + route << "index_" if ActiveModel::Naming.uncountable?(record) && inflection == :plural + end + + action_prefix(options) + route + routing_type(options).to_s + end + + def extract_record(record_or_hash_or_array) + case record_or_hash_or_array + when Array; record_or_hash_or_array.last + when Hash; record_or_hash_or_array[:id] + else record_or_hash_or_array + end + end + end + end +end + diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 36c52eb65a..a9b97a17eb 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -414,7 +414,8 @@ module ActionDispatch elsif value.is_a?(Array) value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/') else - Rack::Mount::Utils.escape_uri(value.to_param) + return nil unless param = value.to_param + param.split('/').map { |v| Rack::Mount::Utils.escape_uri(v) }.join("/") end end {:parameterize => parameterize} diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 980abd44df..662eb05c26 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -82,6 +82,7 @@ module ActionDispatch # module UrlFor extend ActiveSupport::Concern + include PolymorphicRoutes included do # TODO: with_routing extends @controller with url_helpers, trickling down to including this module which overrides its default_url_options diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb index 0e4a92048f..822150b768 100644 --- a/actionpack/lib/action_dispatch/testing/assertions.rb +++ b/actionpack/lib/action_dispatch/testing/assertions.rb @@ -1,7 +1,6 @@ module ActionDispatch module Assertions autoload :DomAssertions, 'action_dispatch/testing/assertions/dom' - autoload :ModelAssertions, 'action_dispatch/testing/assertions/model' autoload :ResponseAssertions, 'action_dispatch/testing/assertions/response' autoload :RoutingAssertions, 'action_dispatch/testing/assertions/routing' autoload :SelectorAssertions, 'action_dispatch/testing/assertions/selector' @@ -11,7 +10,6 @@ module ActionDispatch included do include DomAssertions - include ModelAssertions include ResponseAssertions include RoutingAssertions include SelectorAssertions diff --git a/actionpack/lib/action_dispatch/testing/assertions/model.rb b/actionpack/lib/action_dispatch/testing/assertions/model.rb deleted file mode 100644 index 46714418c6..0000000000 --- a/actionpack/lib/action_dispatch/testing/assertions/model.rb +++ /dev/null @@ -1,19 +0,0 @@ -module ActionDispatch - module Assertions - module ModelAssertions - # Ensures that the passed record is valid by Active Record standards and - # returns any error messages if it is not. - # - # ==== Examples - # - # # assert that a newly created record is valid - # model = Model.new - # assert_valid(model) - # - def assert_valid(record) - ::ActiveSupport::Deprecation.warn("assert_valid is deprecated. Use assert record.valid? instead", caller) - assert record.valid?, record.errors.full_messages.join("\n") - end - end - end -end diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 9f56cca869..c0d7423682 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -23,6 +23,7 @@ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) + require 'active_support/ruby/shim' require 'active_support/core_ext/class/attribute_accessors' diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb index ba3bdd0d18..b7ffa345cc 100644 --- a/actionpack/lib/action_view/helpers.rb +++ b/actionpack/lib/action_view/helpers.rb @@ -20,7 +20,6 @@ module ActionView #:nodoc: autoload :NumberHelper autoload :PrototypeHelper autoload :RawOutputHelper - autoload :RecordIdentificationHelper autoload :RecordTagHelper autoload :SanitizeHelper autoload :ScriptaculousHelper @@ -51,7 +50,6 @@ module ActionView #:nodoc: include NumberHelper include PrototypeHelper include RawOutputHelper - include RecordIdentificationHelper include RecordTagHelper include SanitizeHelper include ScriptaculousHelper diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index f097b9a5a3..8050669adb 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -800,7 +800,8 @@ module ActionView start = options.delete(:start) || 0 stop = options.delete(:end) || 59 step = options.delete(:step) || 1 - leading_zeros = options.delete(:leading_zeros).nil? ? true : false + options.reverse_merge!({:leading_zeros => true}) + leading_zeros = options.delete(:leading_zeros) select_options = [] start.step(stop, step) do |i| diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index b8c163e1c2..b0af836522 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -298,12 +298,12 @@ module ActionView object_name = record_or_name_or_array when Array object = record_or_name_or_array.last - object_name = options[:as] || ActionController::RecordIdentifier.singular_class_name(object) + object_name = options[:as] || ActiveModel::Naming.singular(object) apply_form_for_options!(record_or_name_or_array, options) args.unshift object else object = record_or_name_or_array - object_name = options[:as] || ActionController::RecordIdentifier.singular_class_name(object) + object_name = options[:as] || ActiveModel::Naming.singular(object) apply_form_for_options!([object], options) args.unshift object end @@ -529,7 +529,7 @@ module ActionView object = args.first else object = record_or_name_or_array - object_name = ActionController::RecordIdentifier.singular_class_name(object) + object_name = ActiveModel::Naming.singular(object) end builder = options[:builder] || ActionView::Base.default_form_builder @@ -1152,11 +1152,11 @@ module ActionView end when Array object = record_or_name_or_array.last - name = "#{object_name}#{index}[#{ActionController::RecordIdentifier.singular_class_name(object)}]" + name = "#{object_name}#{index}[#{ActiveModel::Naming.singular(object)}]" args.unshift(object) else object = record_or_name_or_array - name = "#{object_name}#{index}[#{ActionController::RecordIdentifier.singular_class_name(object)}]" + name = "#{object_name}#{index}[#{ActiveModel::Naming.singular(object)}]" args.unshift(object) end diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 6f9d14de8b..ee34452769 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -447,7 +447,7 @@ module ActionView # wrap the output in an appropriate <tt><select></tt> tag. def grouped_options_for_select(grouped_options, selected_key = nil, prompt = nil) body = '' - body << content_tag(:option, prompt, :value => "") if prompt + body << content_tag(:option, prompt, { :value => "" }, true) if prompt grouped_options = grouped_options.sort if grouped_options.is_a?(Hash) @@ -593,11 +593,11 @@ module ActionView private def add_options(option_tags, options, value = nil) if options[:include_blank] - option_tags = "<option value=\"\">#{options[:include_blank] if options[:include_blank].kind_of?(String)}</option>\n" + option_tags + option_tags = "<option value=\"\">#{html_escape(options[:include_blank]) if options[:include_blank].kind_of?(String)}</option>\n" + option_tags end if value.blank? && options[:prompt] prompt = options[:prompt].kind_of?(String) ? options[:prompt] : I18n.translate('helpers.select.prompt', :default => 'Please select') - option_tags = "<option value=\"\">#{prompt}</option>\n" + option_tags + option_tags = "<option value=\"\">#{html_escape(prompt)}</option>\n" + option_tags end option_tags.html_safe end diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 5c0ff5d59c..28b8a27eef 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -139,7 +139,7 @@ module ActionView function = "if (#{options[:condition]}) { #{function}; }" if options[:condition] function = "if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }" if options[:confirm] - return function + return function.html_safe end # All the methods were moved to GeneratorMethods so that diff --git a/actionpack/lib/action_view/helpers/record_identification_helper.rb b/actionpack/lib/action_view/helpers/record_identification_helper.rb deleted file mode 100644 index 372f1cb8aa..0000000000 --- a/actionpack/lib/action_view/helpers/record_identification_helper.rb +++ /dev/null @@ -1,23 +0,0 @@ -module ActionView - # = Action View Record Identification Helpers - # - # See ActionController::RecordIdentifier for documentation on these methods. - module Helpers - module RecordIdentificationHelper - # See ActionController::RecordIdentifier.partial_path -- this is just a delegate to that for convenient access in the view. - def partial_path(*args, &block) - ActionController::RecordIdentifier.partial_path(*args, &block) - end - - # See ActionController::RecordIdentifier.dom_class -- this is just a delegate to that for convenient access in the view. - def dom_class(*args, &block) - ActionController::RecordIdentifier.dom_class(*args, &block) - end - - # See ActionController::RecordIdentifier.dom_id -- this is just a delegate to that for convenient access in the view. - def dom_id(*args, &block) - ActionController::RecordIdentifier.dom_id(*args, &block) - end - end - end -end
\ No newline at end of file diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb index 7433f08777..e4a9210cde 100644 --- a/actionpack/lib/action_view/helpers/record_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb @@ -1,7 +1,11 @@ +require 'action_controller/record_identifier' + module ActionView # = Action View Record Tag Helpers module Helpers module RecordTagHelper + include ActionController::RecordIdentifier + # Produces a wrapper DIV element with id and class parameters that # relate to the specified Active Record object. Usage example: # diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 0e3cc54fd1..b493a0cb0e 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -398,7 +398,7 @@ module ActionView def link_to_unless(condition, name, options = {}, html_options = {}, &block) if condition if block_given? - block.arity <= 1 ? yield(name) : yield(name, options, html_options) + block.arity <= 1 ? capture(name, &block) : capture(name, options, html_options, &block) else name end diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 56aebca957..137281e5e9 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -37,7 +37,7 @@ module ActionView include ActionController::TemplateAssertions include ActionView::Context - include ActionController::PolymorphicRoutes + include ActionDispatch::Routing::PolymorphicRoutes include ActionController::RecordIdentifier include AbstractController::Helpers diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 765e111226..53cdd358b4 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -482,21 +482,6 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase assert_redirected_to :controller => 'admin/user' end - def test_assert_valid - get :get_valid_record - assert_deprecated { assert_valid assigns('record') } - end - - def test_assert_valid_failing - get :get_invalid_record - - begin - assert_deprecated { assert_valid assigns('record') } - assert false - rescue ActiveSupport::TestCase::Assertion => e - end - end - def test_assert_response_uses_exception_message @controller = AssertResponseWithUnexpectedErrorController.new get :index diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb index 6a84475758..835a0e970b 100644 --- a/actionpack/test/controller/record_identifier_test.rb +++ b/actionpack/test/controller/record_identifier_test.rb @@ -26,20 +26,6 @@ class Sheep end end -class Comment::Nested < Comment; end - -class Test::Unit::TestCase - protected - def comments_url - 'http://www.example.com/comments' - end - - def comment_url(comment) - "http://www.example.com/comments/#{comment.id}" - end -end - - class RecordIdentifierTest < Test::Unit::TestCase include ActionController::RecordIdentifier @@ -76,30 +62,4 @@ class RecordIdentifierTest < Test::Unit::TestCase def test_dom_class_with_prefix assert_equal "custom_prefix_#{@singular}", dom_class(@record, :custom_prefix) end - - def test_singular_class_name - assert_equal @singular, singular_class_name(@record) - end - - def test_singular_class_name_for_class - assert_equal @singular, singular_class_name(@klass) - end - - def test_plural_class_name - assert_equal @plural, plural_class_name(@record) - end - - def test_plural_class_name_for_class - assert_equal @plural, plural_class_name(@klass) - end - - def test_uncountable - assert_equal true, uncountable?(@uncountable) - assert_equal false, uncountable?(@klass) - end - - private - def method_missing(method, *args) - RecordIdentifier.send(method, *args) - end end diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index 0f64b77647..a24de62b19 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -79,6 +79,14 @@ class RescueController < ActionController::Base render :text => 'no way' end + rescue_from ActionView::TemplateError do + render :text => 'action_view templater error' + end + + rescue_from IOError do + render :text => 'io error' + end + before_filter(:only => :before_filter_raises) { raise 'umm nice' } def before_filter_raises @@ -141,6 +149,14 @@ class RescueController < ActionController::Base def missing_template end + + def io_error_in_view + raise ActionView::TemplateError.new(nil, {}, IOError.new('this is io error')) + end + + def zero_division_error_in_view + raise ActionView::TemplateError.new(nil, {}, ZeroDivisionError.new('this is zero division error')) + end protected def deny_access @@ -228,6 +244,17 @@ class ControllerInheritanceRescueControllerTest < ActionController::TestCase end class RescueControllerTest < ActionController::TestCase + + def test_io_error_in_view + get :io_error_in_view + assert_equal 'io error', @response.body + end + + def test_zero_division_error_in_view + get :zero_division_error_in_view + assert_equal 'action_view templater error', @response.body + end + def test_rescue_handler get :not_authorized assert_response :forbidden diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index f9fc7a0976..950ad9266f 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -461,6 +461,13 @@ XML def test_assert_routing_in_module assert_routing 'admin/user', :controller => 'admin/user', :action => 'index' end + + def test_assert_routing_with_glob + with_routing do |set| + set.draw { |map| match('*path' => "pages#show") } + assert_routing('/company/about', { :controller => 'pages', :action => 'show', :path => 'company/about' }) + end + end def test_params_passing get :test_params, :page => {:name => "Page name", :month => '4', :year => '2004', :day => '6'} diff --git a/actionpack/test/dispatch/middleware_stack_test.rb b/actionpack/test/dispatch/middleware_stack_test.rb index 170c5b8565..6a1a4f556f 100644 --- a/actionpack/test/dispatch/middleware_stack_test.rb +++ b/actionpack/test/dispatch/middleware_stack_test.rb @@ -66,6 +66,16 @@ class MiddlewareStackTest < ActiveSupport::TestCase assert_equal BazMiddleware, @stack[0].klass end + test "raise an error on invalid index" do + assert_raise RuntimeError do + @stack.insert("HiyaMiddleware", BazMiddleware) + end + + assert_raise RuntimeError do + @stack.insert_after("HiyaMiddleware", BazMiddleware) + end + end + test "lazy evaluates middleware class" do assert_difference "@stack.size" do @stack.use "MiddlewareStackTest::BazMiddleware" diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index e5ee412021..c8947aac80 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -392,19 +392,19 @@ class RequestTest < ActiveSupport::TestCase [{'baz'=>[{'foo'=>'baz'}, "1"]}, {'baz'=>[{'foo'=>'[FILTERED]'}, "1"]}, [/foo/]]] test_hashes.each do |before_filter, after_filter, filter_words| - request = stub_request('action_dispatch.parameter_filter' => filter_words) - assert_equal after_filter, request.send(:process_parameter_filter, before_filter) + parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words) + assert_equal after_filter, parameter_filter.filter(before_filter) filter_words << 'blah' filter_words << lambda { |key, value| value.reverse! if key =~ /bargain/ } - request = stub_request('action_dispatch.parameter_filter' => filter_words) + parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words) before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}} after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}} - assert_equal after_filter, request.send(:process_parameter_filter, before_filter) + assert_equal after_filter, parameter_filter.filter(before_filter) end end diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index f0e01bfff0..3864821ef0 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -44,7 +44,12 @@ class CookieStoreTest < ActionController::IntegrationTest session[:foo] = 'bye!' * 1024 head :ok end - + + def change_session_id + request.session_options[:id] = nil + get_session_id + end + def rescue_action(e) raise end end @@ -212,6 +217,19 @@ class CookieStoreTest < ActionController::IntegrationTest end end + def test_setting_session_id_to_nil_is_respected + with_test_route_set do + cookies[SessionKey] = SignedBar + + get "/get_session_id" + sid = response.body + assert_equal sid.size, 36 + + get "/change_session_id" + assert_not_equal sid, response.body + end + end + def test_session_store_with_expire_after with_test_route_set(:expire_after => 5.hours) do # First request accesses the session diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index 65b5f5ccc1..d14e5020c7 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -210,6 +210,12 @@ class FormOptionsHelperTest < ActionView::TestCase assert grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]]).html_safe? end + def test_grouped_options_for_select_with_prompt_returns_html_escaped_string + assert_dom_equal( + "<option value=\"\"><Choose One></option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], nil, '<Choose One>')) + end + def test_optgroups_with_with_options_with_hash assert_dom_equal( "<optgroup label=\"Europe\"><option value=\"Denmark\">Denmark</option>\n<option value=\"Germany\">Germany</option></optgroup><optgroup label=\"North America\"><option value=\"United States\">United States</option>\n<option value=\"Canada\">Canada</option></optgroup>", @@ -367,6 +373,15 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_with_blank_as_string_escaped + @post = Post.new + @post.category = "<mus>" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\"><None></option>\n<option value=\"abe\">abe</option>\n<option value=\"<mus>\" selected=\"selected\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest), :include_blank => '<None>') + ) + end + def test_select_with_default_prompt @post = Post.new @post.category = "" @@ -394,6 +409,14 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_with_given_prompt_escaped + @post = Post.new + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\"><The prompt></option>\n<option value=\"abe\">abe</option>\n<option value=\"<mus>\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest), :prompt => '<The prompt>') + ) + end + def test_select_with_prompt_and_blank @post = Post.new @post.category = "" diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb index 0ff37f44c2..036a44730c 100644 --- a/actionpack/test/template/prototype_helper_test.rb +++ b/actionpack/test/template/prototype_helper_test.rb @@ -104,6 +104,12 @@ class PrototypeHelperTest < PrototypeHelperBaseTest assert_equal javascript_tag(create_generator(&block).to_s, {:defer => 'true'}), update_page_tag({:defer => 'true'}, &block) end + def test_remote_function + res = remote_function(:url => authors_path, :with => "'author[name]='+$F('author_name')+'&author[dob]='+$F('author_dob')") + assert_equal "new Ajax.Request('/authors', {asynchronous:true, evalScripts:true, parameters:'author[name]='+$F('author_name')+'&author[dob]='+$F('author_dob')})", res + assert res.html_safe? + end + protected def author_path(record) "/authors/#{record.id}" |