diff options
Diffstat (limited to 'actionpack')
107 files changed, 786 insertions, 4873 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 32aba2091a..81abb8b5f1 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,4 +1,6 @@ -*Rails 3.0.0 [Release Candidate] (unreleased)* +*Rails 3.0.0 [release candidate] (July 26th, 2010)* + +* 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] @@ -31,6 +33,7 @@ * Removed textilize, textilize_without_paragraph and markdown helpers. [Santiago Pastorino] + *Rails 3.0.0 [beta 4] (June 8th, 2010)* * Remove middleware laziness [José Valim] diff --git a/actionpack/README b/actionpack/README.rdoc index 1a59f728cc..b297ceb0e2 100644 --- a/actionpack/README +++ b/actionpack/README.rdoc @@ -1,34 +1,35 @@ -= Action Pack -- On rails from request to response - -Action Pack splits the response to a web request into a controller part -(performing the logic) and a view part (rendering a template). This two-step -approach is known as an action, which will normally create, read, update, or -delete (CRUD for short) some sort of model part (often backed by a database) -before choosing either to render a template or redirecting to another action. - -Action Pack implements these actions as public methods on Action Controllers -and uses Action Views to implement the template rendering. Action Controllers -are then responsible for handling all the actions relating to a certain part -of an application. This grouping usually consists of actions for lists and for -CRUDs revolving around a single (or a few) model objects. So ContactsController -would be responsible for listing contacts, creating, deleting, and updating -contacts. A WeblogController could be responsible for both posts and comments. - -Action View templates are written using embedded Ruby in tags mingled in with -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: += Action Pack -- From request to response + +Action Pack is a framework for handling and responding to web requests. It +provides mechanisms for *routing* (mapping request URLs to actions), defining +*controllers* that implement actions, and generating responses by rendering +*views*, which are templates of various formats. In short, Action Pack +provides the view and controller layers in the MVC paradigm. + +It consists of several modules: + +* Action Dispatch, which parses information about the web request, handles + routing as defined by the user, and does advanced processing related to HTTP + such as MIME-type negotiation, decoding parameters in POST/PUT bodies, + handling HTTP caching logic, cookies and sessions. + +* Action Controller, which provides a base controller class that can be + subclassed to implement filters and actions to handle requests. The result + of an action is typically content generated from views. + +* Action View, which handles view template lookup and rendering, and provides + view helpers that assist when building HTML forms, Atom feeds and more. + Template formats that Action View handles are ERb (embedded Ruby, typically + used to inline short Ruby snippets inside HTML), XML Builder and RJS + (dynamically generated JavaScript from Ruby code). + +With the Ruby on Rails framework, users only directly interface with the +Action Controller module. Necessary Action Dispatch functionality is activated +by default and Action View rendering is implicitly triggered by Action +Controller. However, these modules are designed to function on their own and +can be used outside of Rails. + +A short rundown of some of the major features: * Actions grouped in controller as methods instead of separate command objects and can therefore share helper methods @@ -40,26 +41,29 @@ A short rundown of the major features: def update @customer = find_customer - @customer.attributes = params[:customer] - @customer.save ? - redirect_to(:action => "show") : - render(:action => "edit") + if @customer.update_attributes(params[:customer]) + redirect_to :action => "show" + else + render :action => "edit" + end end private - def find_customer() Customer.find(params[:id]) end + def find_customer + Customer.find params[:id] + end end {Learn more}[link:classes/ActionController/Base.html] -* Embedded Ruby for templates (no new "easy" template language) +* ERb templates (static content mixed with dynamic output from ruby) <% for post in @posts %> Title: <%= post.title %> <% end %> - All post titles: <%= @posts.collect{ |p| p.title }.join ", " %> + All post titles: <%= @posts.collect{ |p| p.title }.join(", ") %> <% unless @person.is_client? %> Not for clients to see... @@ -68,7 +72,7 @@ A short rundown of the major features: {Learn more}[link:classes/ActionView.html] -* Builder-based templates (great for XML content, like RSS) +* "Builder" templates (great for XML content, like RSS) xml.rss("version" => "2.0") do xml.channel do @@ -93,11 +97,16 @@ A short rundown of the major features: {Learn more}[link:classes/ActionView/Base.html] -* Filters for pre and post processing of the response (as methods, procs, and classes) +* Filters for pre- and post-processing of the response class WeblogController < ActionController::Base + # filters as methods before_filter :authenticate, :cache, :audit + + # filter as a proc after_filter { |c| c.response.body = Gzip::compress(c.response.body) } + + # class filter after_filter LocalizeFilter def index @@ -120,16 +129,14 @@ A short rundown of the major features: * Helpers for forms, dates, action links, and text - <%= text_field "post", "title", "size" => 30 %> - <%= html_date_select(Date.today) %> + <%= text_field_tag "post", "title", "size" => 30 %> <%= link_to "New post", :controller => "post", :action => "new" %> <%= truncate(post.title, :length => 25) %> {Learn more}[link:classes/ActionView/Helpers.html] -* Layout sharing for template reuse (think simple version of Struts - Tiles[http://jakarta.apache.org/struts/userGuide/dev_tiles.html]) +* Layout sharing for template reuse class WeblogController < ActionController::Base layout "weblog_layout" @@ -150,22 +157,22 @@ A short rundown of the major features: {Learn more}[link:classes/ActionController/Layout/ClassMethods.html] -* Routing makes pretty urls incredibly easy +* Routing makes pretty URLs incredibly easy - map.connect 'clients/:client_name/:project_name/:controller/:action' + match 'clients/:client_name/:project_name/:controller/:action' - Accessing /clients/37signals/basecamp/project/dash calls ProjectController#dash with - { "client_name" => "37signals", "project_name" => "basecamp" } in params[:params] + Accessing "/clients/37signals/basecamp/project/index" calls ProjectController#index with + { "client_name" => "37signals", "project_name" => "basecamp" } in `params` - From that URL, you can rewrite the redirect in a number of ways: + From that action, you can write the redirect in a number of ways: redirect_to(:action => "edit") => - /clients/37signals/basecamp/project/dash + /clients/37signals/basecamp/project/edit redirect_to(:client_name => "nextangle", :project_name => "rails") => - /clients/nextangle/rails/project/dash + /clients/nextangle/rails/project/index - {Learn more}[link:classes/ActionController/Base.html] + {Learn more}[link:classes/ActionDispatch/Routing.html] * Easy testing of both controller and rendered template through ActionController::TestCase @@ -242,62 +249,6 @@ A short rundown of the major features: {Learn more}[link:classes/ActionController/Rescue.html] -* Scaffolding for Active Record model objects - - class AccountController < ActionController::Base - scaffold :account - end - - The AccountController now has the full CRUD range of actions and default - templates: list, show, destroy, new, create, edit, update - - {Learn more}[link:classes/ActionController/Scaffolding/ClassMethods.html] - - -* Form building for Active Record model objects - - The post object has a title (varchar), content (text), and - written_on (date) - - <%= form "post" %> - - ...will generate something like (the selects will have more options, of - course): - - <form action="create" method="POST"> - <p> - <b>Title:</b><br/> - <input type="text" name="post[title]" value="<%= @post.title %>" /> - </p> - <p> - <b>Content:</b><br/> - <textarea name="post[content]"><%= @post.title %></textarea> - </p> - <p> - <b>Written on:</b><br/> - <select name='post[written_on(3i)]'><option>18</option></select> - <select name='post[written_on(2i)]'><option value='7'>July</option></select> - <select name='post[written_on(1i)]'><option>2004</option></select> - </p> - - <input type="submit" value="Create"> - </form> - - This form generates a params[:post] array that can be used directly in a save action: - - class WeblogController < ActionController::Base - def create - post = Post.create(params[:post]) - redirect_to :action => "show", :id => post.id - end - end - - {Learn more}[link:classes/ActionView/Helpers/ActiveRecordHelper.html] - - -* Runs on top of WEBrick, Mongrel, CGI, FCGI, and mod_ruby - - == Simple example (from outside of Rails) This example will implement a simple weblog system using inline templates and @@ -364,24 +315,15 @@ new model). After creating the post, it'll redirect to the show page using an URL such as /weblog/5 (where 5 is the id of the post). -== Download +== Download and installation -The latest version of Action Pack can be found at +The latest version of Action Pack can be installed with Rubygems: -* http://rubyforge.org/project/showfiles.php?group_id=249 + % [sudo] gem install actionpack -Documentation can be found at +Source code can be downloaded as part of the Rails project on GitHub -* http://api.rubyonrails.com - - -== Installation - -You can install Action Pack with the following command. - - % [sudo] ruby install.rb - -from its distribution directory. +* http://github.com/rails/rails/tree/master/actionpack/ == License @@ -391,10 +333,10 @@ Action Pack is released under the MIT license. == Support -The Action Pack homepage is http://www.rubyonrails.org. You can find -the Action Pack RubyForge page at http://rubyforge.org/projects/actionpack. -And as Jim from Rake says: +API documentation is at + +* http://api.rubyonrails.com + +Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here: - Feel free to submit commits or feature requests. If you send a patch, - remember to update the corresponding unit tests. If fact, I prefer - new feature to be submitted in the form of new unit tests. +* https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets diff --git a/actionpack/Rakefile b/actionpack/Rakefile index aed5278e38..4af8ea167a 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -1,8 +1,8 @@ -gem 'rdoc', '= 2.2' +gem 'rdoc', '>= 2.5.9' require 'rdoc' require 'rake' require 'rake/testtask' -require 'rake/rdoctask' +require 'rdoc/task' require 'rake/packagetask' require 'rake/gempackagetask' @@ -38,16 +38,16 @@ end # Genereate the RDoc documentation -Rake::RDocTask.new { |rdoc| +RDoc::Task.new { |rdoc| rdoc.rdoc_dir = 'doc' rdoc.title = "Action Pack -- On rails from request to response" - rdoc.options << '--line-numbers' << '--inline-source' rdoc.options << '--charset' << 'utf-8' - rdoc.template = ENV['template'] ? "#{ENV['template']}.rb" : '../doc/template/horo' + rdoc.options << '-f' << 'horo' + rdoc.options << '--main' << 'README.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') @@ -89,4 +89,4 @@ task :lines do end puts "Total: Lines #{total_lines}, LOC #{total_codelines}" -end
\ No newline at end of file +end diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index df0b5ac9a2..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' @@ -25,7 +25,7 @@ Gem::Specification.new do |s| s.add_dependency('i18n', '~> 0.4.1') s.add_dependency('rack', '~> 1.2.1') s.add_dependency('rack-test', '~> 0.5.4') - #s.add_dependency('rack-mount', '~> 0.6.6') - s.add_dependency('tzinfo', '~> 0.3.16') + s.add_dependency('rack-mount', '~> 0.6.9') + s.add_dependency('tzinfo', '~> 0.3.22') s.add_dependency('erubis', '~> 2.6.6') end 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/abstract_controller/asset_paths.rb b/actionpack/lib/abstract_controller/asset_paths.rb index 6d6f6ac607..9ca2fb742f 100644 --- a/actionpack/lib/abstract_controller/asset_paths.rb +++ b/actionpack/lib/abstract_controller/asset_paths.rb @@ -3,7 +3,7 @@ module AbstractController extend ActiveSupport::Concern included do - config_accessor :assets_dir, :javascripts_dir, :stylesheets_dir + config_accessor :asset_host, :asset_path, :assets_dir, :javascripts_dir, :stylesheets_dir end end end
\ No newline at end of file diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 8a8337858b..db0a6736e0 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -72,6 +72,13 @@ module AbstractController end end + # action_methods are cached and there is sometimes need to refresh + # them. clear_action_methods! allows you to do that, so next time + # you run action_methods, they will be recalculated + def clear_action_methods! + @action_methods = nil + end + # Returns the full controller name, underscored, without the ending Controller. # For instance, MyApp::MyPostsController would return "my_app/my_posts" for # controller_name. @@ -81,6 +88,11 @@ module AbstractController def controller_path @controller_path ||= name.sub(/Controller$/, '').underscore unless anonymous? end + + def method_added(name) + super + clear_action_methods! + end end abstract! 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..9dfffced75 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, @@ -64,9 +63,8 @@ module ActionController klass.helper :all end - config_accessor :asset_host, :asset_path ActiveSupport.run_load_hooks(:action_controller, self) 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/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index be7448ce01..b0eb24a4a8 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -63,7 +63,7 @@ module ActionController # def test_access_granted_from_xml # get( # "/notes/1.xml", nil, - # :authorization => ActionController::HttpAuthentication::Basic.encode_credentials(users(:dhh).name, users(:dhh).password) + # 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(users(:dhh).name, users(:dhh).password) # ) # # assert_equal 200, status 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/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 4f384d1ec5..c6d4c6d936 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -12,27 +12,30 @@ module ActionController #:nodoc: end module ClassMethods - # Defines mimes that are rendered by default when invoking respond_with. + # Defines mime types that are rendered by default when invoking + # <tt>respond_with</tt>. # # Examples: # # respond_to :html, :xml, :json # - # All actions on your controller will respond to :html, :xml and :json. + # Specifies that all actions in the controller respond to requests + # for <tt>:html</tt>, <tt>:xml</tt> and <tt>:json</tt>. # - # But if you want to specify it based on your actions, you can use only and - # except: + # To specify on per-action basis, use <tt>:only</tt> and + # <tt>:except</tt> with an array of actions or a single action: # # respond_to :html # respond_to :xml, :json, :except => [ :edit ] # - # The definition above explicits that all actions respond to :html. And all - # actions except :edit respond to :xml and :json. - # - # You can specify also only parameters: + # This specifies that all actions respond to <tt>:html</tt> + # and all actions except <tt>:edit</tt> respond to <tt>:xml</tt> and + # <tt>:json</tt>. # # respond_to :rjs, :only => :create # + # This specifies that the <tt>:create</tt> action and no other responds + # to <tt>:rjs</tt>. def respond_to(*mimes) options = mimes.extract_options! @@ -49,7 +52,7 @@ module ActionController #:nodoc: self.mimes_for_respond_to = new.freeze end - # Clear all mimes in respond_to. + # Clear all mime types in <tt>respond_to</tt>. # def clear_respond_to self.mimes_for_respond_to = ActiveSupport::OrderedHash.new.freeze @@ -145,7 +148,7 @@ module ActionController #:nodoc: # and accept Rails' defaults, life will be much easier. # # If you need to use a MIME type which isn't supported by default, you can register your own handlers in - # environment.rb as follows. + # config/initializers/mime_types.rb as follows. # # Mime::Type.register "image/jpg", :jpg # 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/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 9261422f0b..cd2dfafbe6 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -5,8 +5,6 @@ require "action_view/railtie" require "active_support/deprecation/proxy_wrappers" require "active_support/deprecation" -require "action_controller/railties/url_helpers" - module ActionController class Railtie < Rails::Railtie config.action_controller = ActiveSupport::OrderedOptions.new @@ -33,21 +31,6 @@ module ActionController end end - initializer "action_controller.set_configs" do |app| - paths = app.config.paths - ac = app.config.action_controller - - ac.assets_dir ||= paths.public.to_a.first - ac.javascripts_dir ||= paths.public.javascripts.to_a.first - ac.stylesheets_dir ||= paths.public.stylesheets.to_a.first - ac.page_cache_directory ||= paths.public.to_a.first - ac.helpers_path ||= paths.app.helpers.to_a - - ActiveSupport.on_load(:action_controller) do - self.config.merge!(ac) - end - end - initializer "action_controller.logger" do ActiveSupport.on_load(:action_controller) { self.logger ||= Rails.logger } end @@ -56,11 +39,23 @@ module ActionController ActiveSupport.on_load(:action_controller) { self.cache_store ||= RAILS_CACHE } end - initializer "action_controller.url_helpers" do |app| + initializer "action_controller.set_configs" do |app| + paths = app.config.paths + options = app.config.action_controller + + options.assets_dir ||= paths.public.to_a.first + options.javascripts_dir ||= paths.public.javascripts.to_a.first + options.stylesheets_dir ||= paths.public.stylesheets.to_a.first + options.page_cache_directory ||= paths.public.to_a.first + options.helpers_path ||= paths.app.helpers.to_a + ActiveSupport.on_load(:action_controller) do - extend ::ActionController::Railties::UrlHelpers.with(app.routes) + include app.routes.url_helpers + options.each { |k,v| send("#{k}=", v) } end + end + initializer "action_controller.deprecated_routes" do |app| message = "ActionController::Routing::Routes is deprecated. " \ "Instead, use Rails.application.routes" diff --git a/actionpack/lib/action_controller/railties/url_helpers.rb b/actionpack/lib/action_controller/railties/url_helpers.rb deleted file mode 100644 index 9df5665542..0000000000 --- a/actionpack/lib/action_controller/railties/url_helpers.rb +++ /dev/null @@ -1,14 +0,0 @@ -module ActionController - module Railties - module UrlHelpers - def self.with(routes) - Module.new do - define_method(:inherited) do |klass| - super(klass) - klass.send(:include, routes.url_helpers) - end - end - 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_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 650eb16ac0..e306697f4b 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -365,7 +365,7 @@ module ActionController def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') - returning __send__(request_method, action, parameters, session, flash) do + __send__(request_method, action, parameters, session, flash).tap do @request.env.delete 'HTTP_X_REQUESTED_WITH' @request.env.delete 'HTTP_ACCEPT' end diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index cdf81c6648..aeec934be8 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 @@ -42,6 +47,7 @@ module ActionDispatch end autoload_under 'middleware' do + autoload :BestStandardsSupport autoload :Callbacks autoload :Cookies autoload :Flash @@ -63,6 +69,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/best_standards_support.rb b/actionpack/lib/action_dispatch/middleware/best_standards_support.rb new file mode 100644 index 0000000000..69adcc419f --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/best_standards_support.rb @@ -0,0 +1,22 @@ +module ActionDispatch + class BestStandardsSupport + def initialize(app, type = true) + @app = app + + @header = case type + when true + "IE=Edge,chrome=1" + when :builtin + "IE=Edge" + when false + nil + end + end + + def call(env) + status, headers, body = @app.call(env) + headers["X-UA-Compatible"] = @header + [status, headers, body] + end + end +end diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index d69ba39728..4d33cd3b0c 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -45,10 +45,10 @@ module ActionDispatch # * <tt>:value</tt> - The cookie's value or list of values (as an array). # * <tt>:path</tt> - The path for which this cookie applies. Defaults to the root # of the application. - # * <tt>:domain</tt> - The domain for which this cookie applies so you can - # restrict to the domain level. If you use a schema like www.example.com + # * <tt>:domain</tt> - The domain for which this cookie applies so you can + # restrict to the domain level. If you use a schema like www.example.com # and want to share session with user.example.com set <tt>:domain</tt> - # to <tt>:all</tt>. Make sure to specify the <tt>:domain</tt> option with + # to <tt>:all</tt>. Make sure to specify the <tt>:domain</tt> option with # <tt>:all</tt> again when deleting keys. # # :domain => nil # Does not sets cookie domain. (default) @@ -63,7 +63,7 @@ module ActionDispatch class Cookies HTTP_HEADER = "Set-Cookie".freeze TOKEN_KEY = "action_dispatch.secret_token".freeze - + # Raised when storing more than 4K of session data. class CookieOverflow < StandardError; end @@ -101,7 +101,7 @@ module ActionDispatch def handle_options(options) #:nodoc: options[:path] ||= "/" - + if options[:domain] == :all @host =~ DOMAIN_REGEXP options[:domain] = ".#{$2}.#{$3}" @@ -122,7 +122,7 @@ module ActionDispatch value = super(key.to_s, value) handle_options(options) - + @set_cookies[key] = options @delete_cookies.delete(key) value @@ -151,7 +151,7 @@ module ActionDispatch # This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples: # # cookies.permanent.signed[:remember_me] = current_user.id - # # => Set-Cookie: discount=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT + # # => Set-Cookie: remember_me=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT def permanent @permanent ||= PermanentCookieJar.new(self, @secret) 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..dd82294644 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 diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index dce47c63bc..ca1494425f 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -35,7 +35,7 @@ module ActionDispatch # such as 'MD5', 'RIPEMD160', 'SHA256', etc. # # To generate a secret key for an existing application, run - # "rake secret" and set the key in config/environment.rb. + # "rake secret" and set the key in config/initializers/secret_token.rb. # # Note that changing digest or secret invalidates all existing sessions! class CookieStore < AbstractStore 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/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index ed93211255..a3af37947a 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -7,10 +7,11 @@ module ActionDispatch config.action_dispatch.x_sendfile_header = "" config.action_dispatch.ip_spoofing_check = true config.action_dispatch.show_exceptions = true + config.action_dispatch.best_standards_support = true # Prepare dispatcher callbacks and run 'prepare' callbacks initializer "action_dispatch.prepare_dispatcher" do |app| ActionDispatch::Callbacks.to_prepare { app.routes_reloader.execute_if_updated } end end -end
\ No newline at end of file +end diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index c664fb0bc2..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 @@ -31,7 +30,7 @@ module ActionDispatch # Think of creating routes as drawing a map for your requests. The map tells # them where to go based on some predefined pattern: # - # AppName::Application.routes.draw do |map| + # AppName::Application.routes.draw do # Pattern 1 tells some request to go to one place # Pattern 2 tell them to go to another # ... @@ -106,7 +105,7 @@ module ActionDispatch # You can specify a regular expression to define a format for a parameter. # # controller 'geocode' do - # match 'geocode/:postalcode' => :show', :constraints => { + # match 'geocode/:postalcode' => :show, :constraints => { # :postalcode => /\d{5}(-\d{4})?/ # } # @@ -114,13 +113,13 @@ module ActionDispatch # expression modifiers: # # controller 'geocode' do - # match 'geocode/:postalcode' => :show', :constraints => { + # match 'geocode/:postalcode' => :show, :constraints => { # :postalcode => /hx\d\d\s\d[a-z]{2}/i # } # end # # controller 'geocode' do - # match 'geocode/:postalcode' => :show', :constraints => { + # match 'geocode/:postalcode' => :show, :constraints => { # :postalcode => /# Postcode format # \d{5} #Prefix # (-\d{4})? #Suffix @@ -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/deprecated_mapper.rb b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb index b3146a1c60..e04062ce8b 100644 --- a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb +++ b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/with_options' +require 'active_support/core_ext/object/try' module ActionDispatch module Routing @@ -500,7 +501,7 @@ module ActionDispatch end def add_conditions_for(conditions, method) - returning({:conditions => conditions.dup}) do |options| + {:conditions => conditions.dup}.tap do |options| options[:conditions][:method] = method unless method == :any end end diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 430f6fc5a3..c118c72440 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1,3 +1,4 @@ +require 'erb' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/object/blank' @@ -35,11 +36,12 @@ module ActionDispatch end class Mapping #:nodoc: - IGNORE_OPTIONS = [:to, :as, :controller, :action, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix] + IGNORE_OPTIONS = [:to, :as, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix] def initialize(set, scope, args) @set, @scope = set, scope @path, @options = extract_path_and_options(args) + normalize_options! end def to_route @@ -57,14 +59,6 @@ module ActionDispatch path = args.first end - if @scope[:module] && options[:to] && !options[:to].is_a?(Proc) - if options[:to].to_s.include?("#") - options[:to] = "#{@scope[:module]}/#{options[:to]}" - elsif @scope[:controller].nil? - options[:to] = "#{@scope[:module]}##{options[:to]}" - end - end - if path.match(':controller') raise ArgumentError, ":controller segment is not allowed within a namespace block" if @scope[:module] @@ -75,15 +69,19 @@ module ActionDispatch options.reverse_merge!(:controller => /.+?/) end - path = normalize_path(path) - path_without_format = path.sub(/\(\.:format\)$/, '') + [ normalize_path(path), options ] + end + + def normalize_options! + path_without_format = @path.sub(/\(\.:format\)$/, '') - if using_match_shorthand?(path_without_format, options) - options[:to] ||= path_without_format[1..-1].sub(%r{/([^/]*)$}, '#\1') - options[:as] ||= path_without_format[1..-1].gsub("/", "_") + if using_match_shorthand?(path_without_format, @options) + to_shorthand = @options[:to].blank? + @options[:to] ||= path_without_format[1..-1].sub(%r{/([^/]*)$}, '#\1') + @options[:as] ||= path_without_format[1..-1].gsub("/", "_") end - [ path, options ] + @options.merge!(default_controller_and_action(to_shorthand)) end # match "account" => "account#index" @@ -122,44 +120,43 @@ module ActionDispatch def defaults @defaults ||= (@options[:defaults] || {}).tap do |defaults| - defaults.merge!(default_controller_and_action) defaults.reverse_merge!(@scope[:defaults]) if @scope[:defaults] @options.each { |k, v| defaults[k] = v unless v.is_a?(Regexp) || IGNORE_OPTIONS.include?(k.to_sym) } end end - def default_controller_and_action + def default_controller_and_action(to_shorthand=nil) if to.respond_to?(:call) { } else - defaults = case to - when String + if to.is_a?(String) controller, action = to.split('#') - { :controller => controller, :action => action } - when Symbol - { :action => to.to_s } - else - {} + elsif to.is_a?(Symbol) + action = to.to_s end - defaults[:controller] ||= default_controller - defaults[:action] ||= default_action + controller ||= default_controller + action ||= default_action - defaults.delete(:controller) if defaults[:controller].blank? || defaults[:controller].is_a?(Regexp) - defaults.delete(:action) if defaults[:action].blank? || defaults[:action].is_a?(Regexp) + unless controller.is_a?(Regexp) || to_shorthand + controller = [@scope[:module], controller].compact.join("/").presence + end - defaults[:controller] = defaults[:controller].to_s if defaults.key?(:controller) - defaults[:action] = defaults[:action].to_s if defaults.key?(:action) + controller = controller.to_s unless controller.is_a?(Regexp) + action = action.to_s unless action.is_a?(Regexp) - if defaults[:controller].blank? && segment_keys.exclude?("controller") + if controller.blank? && segment_keys.exclude?("controller") raise ArgumentError, "missing :controller" end - if defaults[:action].blank? && segment_keys.exclude?("action") + if action.blank? && segment_keys.exclude?("action") raise ArgumentError, "missing :action" end - defaults + { :controller => controller, :action => action }.tap do |hash| + hash.delete(:controller) if hash[:controller].blank? + hash.delete(:action) if hash[:action].blank? + end end end @@ -207,6 +204,8 @@ module ActionDispatch def default_action if @options[:action] @options[:action] + elsif @scope[:action] + @scope[:action] end end end @@ -279,7 +278,6 @@ module ActionDispatch path = args.shift || block path_proc = path.is_a?(Proc) ? path : proc { |params| path % params } status = options[:status] || 301 - body = 'Moved Permanently' lambda do |env| req = Request.new(env) @@ -292,11 +290,14 @@ module ActionDispatch uri.host ||= req.host uri.port ||= req.port unless req.port == 80 + body = %(<html><body>You are being <a href="#{ERB::Util.h(uri.to_s)}">redirected</a>.</body></html>) + headers = { 'Location' => uri.to_s, 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s } + [ status, headers, [body] ] end end @@ -424,7 +425,7 @@ module ActionDispatch end def merge_controller_scope(parent, child) - @scope[:module] ? "#{@scope[:module]}/#{child}" : child + child end def merge_path_names_scope(parent, child) 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 1b1a221c60..d23b580d97 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -1,10 +1,8 @@ +require 'rack/mount' require 'forwardable' require 'active_support/core_ext/object/to_query' require 'action_dispatch/routing/deprecated_mapper' -$: << File.expand_path('../../vendor/rack-mount-0.6.6.pre', __FILE__) -require 'rack/mount' - module ActionDispatch module Routing class RouteSet #:nodoc: @@ -394,10 +392,9 @@ module ActionDispatch end def generate - error = ActionController::RoutingError.new("No route matches #{options.inspect}") path, params = @set.set.generate(:path_info, named_route, options, recall, opts) - raise error unless path + raise_routing_error unless path params.reject! {|k,v| !v } @@ -406,7 +403,7 @@ module ActionDispatch path << "?#{params.to_query}" if params.any? "#{script_name}#{path}" rescue Rack::Mount::RoutingError - raise error + raise_routing_error end def opts @@ -416,12 +413,17 @@ 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} end + def raise_routing_error + raise ActionController::RoutingError.new("No route matches #{options.inspect}") + end + def different_controller? return false unless current_controller controller.to_param != current_controller.to_param @@ -455,7 +457,7 @@ module ActionDispatch def url_for(options) finalize! - options = default_url_options.merge(options || {}) + options = (options || {}).reverse_merge!(default_url_options) handle_positional_args(options) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 980abd44df..ba93ff8630 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -20,7 +20,7 @@ module ActionDispatch # <%= link_to('Click here', :controller => 'users', # :action => 'new', :message => 'Welcome!') %> # - # #=> Generates a link to: /users/new?message=Welcome%21 + # # Generates a link to /users/new?message=Welcome%21 # # link_to, and all other functions that require URL generation functionality, # actually use ActionController::UrlFor under the hood. And in particular, @@ -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 @@ -128,7 +129,7 @@ module ActionDispatch when String options when nil, Hash - _routes.url_for(url_options.merge((options || {}).symbolize_keys)) + _routes.url_for((options || {}).reverse_merge!(url_options).symbolize_keys) else polymorphic_url(options) end 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_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 64eb6d8de7..b52795c575 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -1,6 +1,7 @@ require 'stringio' require 'uri' require 'active_support/core_ext/kernel/singleton_class' +require 'active_support/core_ext/object/try' require 'rack/test' require 'test/unit/assertions' @@ -319,7 +320,7 @@ module ActionDispatch reset! unless @integration_session # reset the html_document variable, but only for new get/post calls @html_document = nil unless %w(cookies assigns).include?(method) - returning @integration_session.__send__(method, *args) do + @integration_session.__send__(method, *args).tap do copy_session_variables! end end @@ -362,7 +363,7 @@ module ActionDispatch def method_missing(sym, *args, &block) reset! unless @integration_session if @integration_session.respond_to?(sym) - returning @integration_session.__send__(sym, *args, &block) do + @integration_session.__send__(sym, *args, &block).tap do copy_session_variables! end else diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount.rb deleted file mode 100644 index 9fbf707724..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'rack' - -module Rack #:nodoc: - # A stackable dynamic tree based Rack router. - # - # Rack::Mount supports Rack's Cascade style of trying several routes until - # it finds one that is not a 404. This allows multiple routes to be nested - # or stacked on top of each other. Since the application endpoint can - # trigger the router to continue matching, middleware can be used to add - # arbitrary conditions to any route. This allows you to route based on - # other request attributes, session information, or even data dynamically - # pulled from a database. - module Mount - autoload :CodeGeneration, 'rack/mount/code_generation' - autoload :GeneratableRegexp, 'rack/mount/generatable_regexp' - autoload :Multimap, 'rack/mount/multimap' - autoload :Prefix, 'rack/mount/prefix' - autoload :RegexpWithNamedGroups, 'rack/mount/regexp_with_named_groups' - autoload :Route, 'rack/mount/route' - autoload :RouteSet, 'rack/mount/route_set' - autoload :RoutingError, 'rack/mount/route_set' - autoload :Strexp, 'rack/mount/strexp' - autoload :Utils, 'rack/mount/utils' - autoload :Version, 'rack/mount/version' - - module Analysis #:nodoc: - autoload :Frequency, 'rack/mount/analysis/frequency' - autoload :Histogram, 'rack/mount/analysis/histogram' - autoload :Splitting, 'rack/mount/analysis/splitting' - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/frequency.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/frequency.rb deleted file mode 100644 index 671258f807..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/frequency.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'rack/mount/utils' - -module Rack::Mount - module Analysis - class Frequency #:nodoc: - def initialize(*keys) - clear - keys.each { |key| self << key } - end - - def clear - @raw_keys = [] - @key_frequency = Analysis::Histogram.new - self - end - - def <<(key) - raise ArgumentError unless key.is_a?(Hash) - @raw_keys << key - nil - end - - def possible_keys - @possible_keys ||= begin - @raw_keys.map do |key| - key.inject({}) { |requirements, (method, requirement)| - process_key(requirements, method, requirement) - requirements - } - end - end - end - - def process_key(requirements, method, requirement) - if requirement.is_a?(Regexp) - expression = Utils.parse_regexp(requirement) - - if expression.is_a?(Regin::Expression) && expression.anchored_to_line? - expression = Regin::Expression.new(expression.reject { |e| e.is_a?(Regin::Anchor) }) - return requirements[method] = expression.to_s if expression.literal? - end - end - - requirements[method] = requirement - end - - def report - @report ||= begin - possible_keys.each { |keys| keys.each_pair { |key, _| @key_frequency << key } } - return [] if @key_frequency.count <= 1 - @key_frequency.keys_in_upper_quartile - end - end - - def expire! - @possible_keys = @report = nil - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/histogram.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/histogram.rb deleted file mode 100644 index 20aaa132f9..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/histogram.rb +++ /dev/null @@ -1,74 +0,0 @@ -module Rack::Mount - module Analysis - class Histogram < Hash #:nodoc: - attr_reader :count - - def initialize - @count = 0 - super(0) - expire_caches! - end - - def <<(value) - @count += 1 - self[value] += 1 if value - expire_caches! - self - end - - def sorted_by_frequency - sort_by { |_, value| value }.reverse! - end - - def max - @max ||= values.max || 0 - end - - def min - @min ||= values.min || 0 - end - - def mean - @mean ||= calculate_mean - end - - def standard_deviation - @standard_deviation ||= calculate_standard_deviation - end - - def upper_quartile_limit - @upper_quartile_limit ||= calculate_upper_quartile_limit - end - - def keys_in_upper_quartile - @keys_in_upper_quartile ||= compute_keys_in_upper_quartile - end - - private - def calculate_mean - count / size - end - - def calculate_variance - values.inject(0) { |sum, e| sum + (e - mean) ** 2 } / count.to_f - end - - def calculate_standard_deviation - Math.sqrt(calculate_variance) - end - - def calculate_upper_quartile_limit - mean + standard_deviation - end - - def compute_keys_in_upper_quartile - sorted_by_frequency.select { |_, value| value >= upper_quartile_limit }.map! { |key, _| key } - end - - def expire_caches! - @max = @min = @mean = @standard_deviation = nil - @keys_in_upper_quartile = nil - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/splitting.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/splitting.rb deleted file mode 100644 index 8a8c551302..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/analysis/splitting.rb +++ /dev/null @@ -1,159 +0,0 @@ -require 'rack/mount/utils' - -module Rack::Mount - module Analysis - class Splitting < Frequency - NULL = "\0".freeze - - class Key < Struct.new(:method, :index, :separators) - def self.split(value, separator_pattern) - keys = value.split(separator_pattern) - keys.shift if keys[0] == '' - keys << NULL - keys - end - - def call(cache, obj) - (cache[method] ||= self.class.split(obj.send(method), separators))[index] - end - - def call_source(cache, obj) - "(#{cache}[:#{method}] ||= Analysis::Splitting::Key.split(#{obj}.#{method}, #{separators.inspect}))[#{index}]" - end - - def inspect - "#{method}[#{index}]" - end - end - - def clear - @boundaries = {} - super - end - - def <<(key) - super - key.each_pair do |k, v| - analyze_capture_boundaries(v, @boundaries[k] ||= Histogram.new) - end - end - - def separators(key) - (@boundaries[key].keys_in_upper_quartile + ['/']).uniq - end - - def process_key(requirements, method, requirement) - separators = separators(method) - if requirement.is_a?(Regexp) && separators.any? - generate_split_keys(requirement, separators).each_with_index do |value, index| - requirements[Key.new(method, index, Regexp.union(*separators))] = value - end - else - super - end - end - - private - def analyze_capture_boundaries(regexp, boundaries) #:nodoc: - return boundaries unless regexp.is_a?(Regexp) - - parts = Utils.parse_regexp(regexp) - parts.each_with_index do |part, index| - if part.is_a?(Regin::Group) - if index > 0 - previous = parts[index-1] - if previous.is_a?(Regin::Character) && previous.literal? - boundaries << previous.to_s - end - end - - if inside = part.expression[0] - if inside.is_a?(Regin::Character) && inside.literal? - boundaries << inside.to_s - end - end - - if index < parts.length - following = parts[index+1] - if following.is_a?(Regin::Character) && following.literal? - boundaries << following.to_s - end - end - end - end - - boundaries - end - - def generate_split_keys(regexp, separators) #:nodoc: - segments = [] - buf = nil - parts = Utils.parse_regexp(regexp) - parts.each_with_index do |part, index| - case part - when Regin::Anchor - if part.value == '$' || part.value == '\Z' - segments << join_buffer(buf, regexp) if buf - segments << NULL - buf = nil - break - end - when Regin::CharacterClass - break if separators.any? { |s| part.include?(s) } - buf = nil - segments << part.to_regexp(true) - when Regin::Character - if separators.any? { |s| part.include?(s) } - segments << join_buffer(buf, regexp) if buf - peek = parts[index+1] - if peek.is_a?(Regin::Character) && separators.include?(peek.value) - segments << '' - end - buf = nil - else - buf ||= Regin::Expression.new([]) - buf += [part] - end - when Regin::Group - if part.quantifier == '?' - value = part.expression.first - if separators.any? { |s| value.include?(s) } - segments << join_buffer(buf, regexp) if buf - buf = nil - end - break - elsif part.quantifier == nil - break if separators.any? { |s| part.include?(s) } - buf = nil - segments << part.to_regexp(true) - else - break - end - else - break - end - - if index + 1 == parts.size - segments << join_buffer(buf, regexp) if buf - buf = nil - break - end - end - - while segments.length > 0 && (segments.last.nil? || segments.last == '') - segments.pop - end - - segments - end - - def join_buffer(parts, regexp) - if parts.literal? - parts.to_s - else - parts.to_regexp(true) - end - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/code_generation.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/code_generation.rb deleted file mode 100644 index 903c79fdc6..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/code_generation.rb +++ /dev/null @@ -1,113 +0,0 @@ -module Rack::Mount - module CodeGeneration #:nodoc: - def _expired_recognize(env) #:nodoc: - raise 'route set not finalized' - end - - def rehash - super - optimize_recognize! - end - - private - def expire! - if @optimized_recognize_defined - remove_metaclass_method :recognize - - class << self - alias_method :recognize, :_expired_recognize - end - - @optimized_recognize_defined = false - end - - super - end - - def optimize_container_iterator(container) - body = [] - - container.each_with_index { |route, i| - body << "route = self[#{i}]" - body << 'matches = {}' - body << 'params = route.defaults.dup' - - conditions = [] - route.conditions.each do |method, condition| - b = [] - if condition.is_a?(Regexp) - b << "if m = obj.#{method}.match(#{condition.inspect})" - b << "matches[:#{method}] = m" - if (named_captures = route.named_captures[method]) && named_captures.any? - b << 'captures = m.captures' - b << 'p = nil' - b << named_captures.map { |k, j| "params[#{k.inspect}] = p if p = captures[#{j}]" }.join('; ') - end - else - b << "if m = obj.#{method} == route.conditions[:#{method}]" - end - b << 'true' - b << 'end' - conditions << "(#{b.join('; ')})" - end - - body << <<-RUBY - if #{conditions.join(' && ')} - yield route, matches, params - end - RUBY - } - - container.instance_eval(<<-RUBY, __FILE__, __LINE__) - def optimized_each(obj) - #{body.join("\n")} - nil - end - RUBY - end - - def optimize_recognize! - keys = @recognition_keys.map { |key| - if key.respond_to?(:call_source) - key.call_source(:cache, :obj) - else - "obj.#{key}" - end - }.join(', ') - - @optimized_recognize_defined = true - - remove_metaclass_method :recognize - - instance_eval(<<-RUBY, __FILE__, __LINE__) - def recognize(obj) - cache = {} - container = @recognition_graph[#{keys}] - optimize_container_iterator(container) unless container.respond_to?(:optimized_each) - - if block_given? - container.optimized_each(obj) do |route, matches, params| - yield route, matches, params - end - else - container.optimized_each(obj) do |route, matches, params| - return route, matches, params - end - end - - nil - end - RUBY - end - - # method_defined? can't distinguish between instance - # and meta methods. So we have to rescue if the method - # has not been defined in the metaclass yet. - def remove_metaclass_method(symbol) - metaclass = class << self; self; end - metaclass.send(:remove_method, symbol) - rescue NameError => e - nil - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/generatable_regexp.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/generatable_regexp.rb deleted file mode 100644 index 47bbab3784..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/generatable_regexp.rb +++ /dev/null @@ -1,210 +0,0 @@ -require 'rack/mount/utils' - -module Rack::Mount - class GeneratableRegexp < Regexp #:nodoc: - class DynamicSegment #:nodoc: - attr_reader :name, :requirement - - def initialize(name, requirement) - @name, @requirement = name.to_sym, requirement - freeze - end - - def ==(obj) - @name == obj.name && @requirement == obj.requirement - end - - def =~(str) - @requirement =~ str - end - - def to_hash - { @name => @requirement } - end - - def inspect - "/(?<#{@name}>#{@requirement.source})/" - end - end - - module InstanceMethods - def self.extended(obj) - obj.segments - end - - def defaults=(defaults) - @required_captures = nil - @required_params = nil - @required_defaults = nil - @defaults = defaults - end - - def defaults - @defaults ||= {} - end - - def generatable? - segments.any? - end - - def generate(params = {}, recall = {}, options = {}) - return nil unless generatable? - - merged = recall.merge(params) - return nil unless required_params.all? { |p| merged.include?(p) } - return nil unless required_defaults.all? { |k, v| merged[k] == v } - - generate_from_segments(segments, params, merged, options) - end - - def segments - @segments ||= begin - defaults - segments = [] - catch(:halt) do - expression = Utils.parse_regexp(self) - segments = parse_segments(expression) - end - segments - end - end - - def captures - segments.flatten.find_all { |s| s.is_a?(DynamicSegment) } - end - - def required_captures - @required_captures ||= segments.find_all { |s| - s.is_a?(DynamicSegment) && !@defaults.include?(s.name) - }.freeze - end - - def required_params - @required_params ||= required_captures.map { |s| s.name }.freeze - end - - def required_defaults - @required_defaults ||= begin - required_defaults = @defaults.dup - captures.inject({}) { |h, s| h.merge!(s.to_hash) }.keys.each { |name| - required_defaults.delete(name) - } - required_defaults - end - end - - def freeze - segments - captures - required_captures - required_params - required_defaults - super - end - - private - def parse_segments(segments) - s = [] - segments.each_with_index do |part, index| - case part - when Regin::Anchor - # ignore - when Regin::Character - throw :halt unless part.literal? - - if s.last.is_a?(String) - s.last << part.value.dup - else - s << part.value.dup - end - when Regin::Group - if part.name - s << DynamicSegment.new(part.name, part.expression.to_regexp(true)) - else - s << parse_segments(part.expression) - end - when Regin::Expression - return parse_segments(part) - else - throw :halt - end - end - - s - end - - EMPTY_STRING = ''.freeze - - def generate_from_segments(segments, params, merged, options, optional = false) - if optional - return EMPTY_STRING if segments.all? { |s| s.is_a?(String) } - return EMPTY_STRING unless segments.flatten.any? { |s| - params.has_key?(s.name) if s.is_a?(DynamicSegment) - } - return EMPTY_STRING if segments.any? { |segment| - if segment.is_a?(DynamicSegment) - value = merged[segment.name] || @defaults[segment.name] - value = parameterize(segment.name, value, options) - - merged_value = parameterize(segment.name, merged[segment.name], options) - default_value = parameterize(segment.name, @defaults[segment.name], options) - - if value.nil? || segment !~ value - true - elsif merged_value == default_value - # Nasty control flow - return :clear_remaining_segments - else - false - end - end - } - end - - generated = segments.map do |segment| - case segment - when String - segment - when DynamicSegment - value = params[segment.name] || merged[segment.name] || @defaults[segment.name] - value = parameterize(segment.name, value, options) - if value && segment =~ value.to_s - value - else - return - end - when Array - value = generate_from_segments(segment, params, merged, options, true) - if value == :clear_remaining_segments - segment.each { |s| params.delete(s.name) if s.is_a?(DynamicSegment) } - EMPTY_STRING - elsif value.nil? - EMPTY_STRING - else - value - end - end - end - - # Delete any used items from the params - segments.each { |s| params.delete(s.name) if s.is_a?(DynamicSegment) } - - generated.join - end - - def parameterize(name, value, options) - if block = options[:parameterize] - block.call(name, value) - else - value - end - end - end - include InstanceMethods - - def initialize(regexp) - super - segments - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/multimap.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/multimap.rb deleted file mode 100644 index 0f8eaaec67..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/multimap.rb +++ /dev/null @@ -1,53 +0,0 @@ -begin - require 'nested_multimap' -rescue LoadError - $: << File.expand_path(File.join(File.dirname(__FILE__), 'vendor/multimap')) - require 'nested_multimap' -end - -module Rack::Mount - class Multimap < NestedMultimap #:nodoc: - def store(*args) - keys = args.dup - value = keys.pop - key = keys.shift - - raise ArgumentError, 'wrong number of arguments (1 for 2)' unless value - - unless key.respond_to?(:=~) - raise ArgumentError, "unsupported key: #{args.first.inspect}" - end - - if key.is_a?(Regexp) - if keys.empty? - @hash.each_pair { |k, l| l << value if k =~ key } - self.default << value - else - @hash.each_pair { |k, _| - if k =~ key - args[0] = k - super(*args) - end - } - - self.default = self.class.new(default) unless default.is_a?(self.class) - default[*keys.dup] = value - end - else - super(*args) - end - end - alias_method :[]=, :store - - undef :index, :invert - - def height - containers_with_default.max { |a, b| a.length <=> b.length }.length - end - - def average_height - lengths = containers_with_default.map { |e| e.length } - lengths.inject(0) { |sum, len| sum += len }.to_f / lengths.size - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/prefix.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/prefix.rb deleted file mode 100644 index 58892e4c4f..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/prefix.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'rack/mount/utils' - -module Rack::Mount - class Prefix #:nodoc: - EMPTY_STRING = ''.freeze - PATH_INFO = 'PATH_INFO'.freeze - SCRIPT_NAME = 'SCRIPT_NAME'.freeze - SLASH = '/'.freeze - - KEY = 'rack.mount.prefix'.freeze - - def initialize(app, prefix = nil) - @app, @prefix = app, prefix.freeze - freeze - end - - def call(env) - if prefix = env[KEY] || @prefix - old_path_info = env[PATH_INFO].dup - old_script_name = env[SCRIPT_NAME].dup - - begin - env[PATH_INFO] = Utils.normalize_path(env[PATH_INFO].sub(prefix, EMPTY_STRING)) - env[PATH_INFO] = EMPTY_STRING if env[PATH_INFO] == SLASH - env[SCRIPT_NAME] = Utils.normalize_path(env[SCRIPT_NAME].to_s + prefix) - @app.call(env) - ensure - env[PATH_INFO] = old_path_info - env[SCRIPT_NAME] = old_script_name - end - else - @app.call(env) - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/regexp_with_named_groups.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/regexp_with_named_groups.rb deleted file mode 100644 index c11292b2a2..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/regexp_with_named_groups.rb +++ /dev/null @@ -1,69 +0,0 @@ -module Rack::Mount - if Regin.regexp_supports_named_captures? - RegexpWithNamedGroups = Regexp - else - require 'strscan' - - # A wrapper that adds shim named capture support to older - # versions of Ruby. - # - # Because the named capture syntax causes a parse error, an - # alternate syntax is used to indicate named captures. - # - # Ruby 1.9+ named capture syntax: - # - # /(?<foo>[a-z]+)/ - # - # Ruby 1.8 shim syntax: - # - # /(?:<foo>[a-z]+)/ - class RegexpWithNamedGroups < Regexp - def self.new(regexp) #:nodoc: - if regexp.is_a?(RegexpWithNamedGroups) - regexp - else - super - end - end - - # Wraps Regexp with named capture support. - def initialize(regexp) - regexp = Regexp.compile(regexp) unless regexp.is_a?(Regexp) - source, options = regexp.source, regexp.options - @names, scanner = [], StringScanner.new(source) - - while scanner.skip_until(/\(/) - if scanner.scan(/\?:<([^>]+)>/) - @names << scanner[1] - elsif scanner.scan(/\?(i?m?x?\-?i?m?x?)?:/) - # ignore noncapture - else - @names << nil - end - end - source.gsub!(/\?:<([^>]+)>/, '') - - @names = [] unless @names.any? - @names.freeze - - super(source, options) - end - - def names - @names.dup - end - - def named_captures - named_captures = {} - names.each_with_index { |n, i| - named_captures[n] = [i+1] if n - } - named_captures - end - - def eql?(other) - super && @names.eql?(other.names) - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route.rb deleted file mode 100644 index 680c40f147..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route.rb +++ /dev/null @@ -1,130 +0,0 @@ -require 'rack/mount/generatable_regexp' -require 'rack/mount/regexp_with_named_groups' -require 'rack/mount/utils' - -module Rack::Mount - # Route is an internal class used to wrap a single route attributes. - # - # Plugins should not depend on any method on this class or instantiate - # new Route objects. Instead use the factory method, RouteSet#add_route - # to create new routes and add them to the set. - class Route - # Valid rack application to call if conditions are met - attr_reader :app - - # A hash of conditions to match against. Conditions may be expressed - # as strings or regexps to match against. - attr_reader :conditions - - # A hash of values that always gets merged into the parameters hash - attr_reader :defaults - - # Symbol identifier for the route used with named route generations - attr_reader :name - - attr_reader :named_captures - - def initialize(app, conditions, defaults, name) - unless app.respond_to?(:call) - raise ArgumentError, 'app must be a valid rack application' \ - ' and respond to call' - end - @app = app - - @name = name ? name.to_sym : nil - @defaults = (defaults || {}).freeze - - @conditions = {} - - conditions.each do |method, pattern| - next unless method && pattern - - pattern = Regexp.compile("\\A#{Regexp.escape(pattern)}\\Z") if pattern.is_a?(String) - - if pattern.is_a?(Regexp) - pattern = Utils.normalize_extended_expression(pattern) - pattern = RegexpWithNamedGroups.new(pattern) - pattern.extend(GeneratableRegexp::InstanceMethods) - pattern.defaults = @defaults - end - - @conditions[method] = pattern.freeze - end - - @named_captures = {} - @conditions.map { |method, condition| - next unless condition.respond_to?(:named_captures) - @named_captures[method] = condition.named_captures.inject({}) { |named_captures, (k, v)| - named_captures[k.to_sym] = v.last - 1 - named_captures - }.freeze - } - @named_captures.freeze - - @has_significant_params = @conditions.any? { |method, condition| - (condition.respond_to?(:required_params) && condition.required_params.any?) || - (condition.respond_to?(:required_defaults) && condition.required_defaults.any?) - } - - if @conditions.has_key?(:path_info) && - !Utils.regexp_anchored?(@conditions[:path_info]) - @prefix = true - @app = Prefix.new(@app) - else - @prefix = false - end - - @conditions.freeze - end - - def prefix? - @prefix - end - - - def generation_keys - @conditions.inject({}) { |keys, (method, condition)| - if condition.respond_to?(:required_defaults) - keys.merge!(condition.required_defaults) - else - keys - end - } - end - - def significant_params? - @has_significant_params - end - - def generate(method, params = {}, recall = {}, options = {}) - if method.nil? - result = @conditions.inject({}) { |h, (m, condition)| - if condition.respond_to?(:generate) - h[m] = condition.generate(params, recall, options) - end - h - } - return nil if result.values.compact.empty? - else - if condition = @conditions[method] - if condition.respond_to?(:generate) - result = condition.generate(params, recall, options) - end - end - end - - if result - @defaults.each do |key, value| - params.delete(key) if params[key] == value - end - end - - result - end - - - def inspect #:nodoc: - "#<#{self.class.name} @app=#{@app.inspect} @conditions=#{@conditions.inspect} @defaults=#{@defaults.inspect} @name=#{@name.inspect}>" - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route_set.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route_set.rb deleted file mode 100644 index 0e5a65a640..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/route_set.rb +++ /dev/null @@ -1,409 +0,0 @@ -require 'rack/mount/multimap' -require 'rack/mount/route' -require 'rack/mount/utils' - -module Rack::Mount - class RoutingError < StandardError; end - - class RouteSet - # Initialize a new RouteSet without optimizations - def self.new_without_optimizations(options = {}, &block) - new(options.merge(:_optimize => false), &block) - end - - # Basic RouteSet initializer. - # - # If a block is given, the set is yielded and finalized. - # - # See other aspects for other valid options: - # - <tt>Generation::RouteSet.new</tt> - # - <tt>Recognition::RouteSet.new</tt> - def initialize(options = {}, &block) - @parameters_key = options.delete(:parameters_key) || 'rack.routing_args' - @parameters_key.freeze - - @named_routes = {} - - @recognition_key_analyzer = Analysis::Splitting.new - @generation_key_analyzer = Analysis::Frequency.new - - @request_class = options.delete(:request_class) || Rack::Request - @valid_conditions = @request_class.public_instance_methods.map! { |m| m.to_sym } - - extend CodeGeneration unless options[:_optimize] == false - @optimized_recognize_defined = false - - @routes = [] - expire! - - if block_given? - yield self - rehash - end - end - - # Builder method to add a route to the set - # - # <tt>app</tt>:: A valid Rack app to call if the conditions are met. - # <tt>conditions</tt>:: A hash of conditions to match against. - # Conditions may be expressed as strings or - # regexps to match against. - # <tt>defaults</tt>:: A hash of values that always gets merged in - # <tt>name</tt>:: Symbol identifier for the route used with named - # route generations - def add_route(app, conditions = {}, defaults = {}, name = nil) - unless conditions.is_a?(Hash) - raise ArgumentError, 'conditions must be a Hash' - end - - unless conditions.all? { |method, pattern| - @valid_conditions.include?(method) - } - raise ArgumentError, 'conditions may only include ' + - @valid_conditions.inspect - end - - route = Route.new(app, conditions, defaults, name) - @routes << route - - @recognition_key_analyzer << route.conditions - - @named_routes[route.name] = route if route.name - @generation_key_analyzer << route.generation_keys - - expire! - route - end - - def recognize(obj) - raise 'route set not finalized' unless @recognition_graph - - cache = {} - keys = @recognition_keys.map { |key| - if key.respond_to?(:call) - key.call(cache, obj) - else - obj.send(key) - end - } - - @recognition_graph[*keys].each do |route| - matches = {} - params = route.defaults.dup - - if route.conditions.all? { |method, condition| - value = obj.send(method) - if condition.is_a?(Regexp) && (m = value.match(condition)) - matches[method] = m - captures = m.captures - route.named_captures[method].each do |k, i| - if v = captures[i] - params[k] = v - end - end - true - elsif value == condition - true - else - false - end - } - if block_given? - yield route, matches, params - else - return route, matches, params - end - end - end - - nil - end - - X_CASCADE = 'X-Cascade'.freeze - PASS = 'pass'.freeze - PATH_INFO = 'PATH_INFO'.freeze - - # Rack compatible recognition and dispatching method. Routes are - # tried until one returns a non-catch status code. If no routes - # match, the catch status code is returned. - # - # This method can only be invoked after the RouteSet has been - # finalized. - def call(env) - raise 'route set not finalized' unless @recognition_graph - - env[PATH_INFO] = Utils.normalize_path(env[PATH_INFO]) - - request = nil - req = @request_class.new(env) - recognize(req) do |route, matches, params| - # TODO: We only want to unescape params from uri related methods - params.each { |k, v| params[k] = Utils.unescape_uri(v) if v.is_a?(String) } - - if route.prefix? - env[Prefix::KEY] = matches[:path_info].to_s - end - - env[@parameters_key] = params - result = route.app.call(env) - return result unless result[1][X_CASCADE] == PASS - end - - request || [404, {'Content-Type' => 'text/html', 'X-Cascade' => 'pass'}, ['Not Found']] - end - - # Generates a url from Rack env and identifiers or significant keys. - # - # To generate a url by named route, pass the name in as a +Symbol+. - # url(env, :dashboard) # => "/dashboard" - # - # Additional parameters can be passed in as a hash - # url(env, :people, :id => "1") # => "/people/1" - # - # If no name route is given, it will fall back to a slower - # generation search. - # url(env, :controller => "people", :action => "show", :id => "1") - # # => "/people/1" - def url(env, *args) - named_route, params = nil, {} - - case args.length - when 2 - named_route, params = args[0], args[1].dup - when 1 - if args[0].is_a?(Hash) - params = args[0].dup - else - named_route = args[0] - end - else - raise ArgumentError - end - - only_path = params.delete(:only_path) - recall = env[@parameters_key] || {} - - unless result = generate(:all, named_route, params, recall, - :parameterize => lambda { |name, param| Utils.escape_uri(param) }) - return - end - - parts, params = result - return unless parts - - params.each do |k, v| - if v - params[k] = v - else - params.delete(k) - end - end - - req = stubbed_request_class.new(env) - req._stubbed_values = parts.merge(:query_string => Utils.build_nested_query(params)) - only_path ? req.fullpath : req.url - end - - def generate(method, *args) #:nodoc: - raise 'route set not finalized' unless @generation_graph - - method = nil if method == :all - named_route, params, recall, options = extract_params!(*args) - merged = recall.merge(params) - route = nil - - if named_route - if route = @named_routes[named_route.to_sym] - recall = route.defaults.merge(recall) - url = route.generate(method, params, recall, options) - [url, params] - else - raise RoutingError, "#{named_route} failed to generate from #{params.inspect}" - end - else - keys = @generation_keys.map { |key| - if k = merged[key] - k.to_s - else - nil - end - } - @generation_graph[*keys].each do |r| - next unless r.significant_params? - if url = r.generate(method, params, recall, options) - return [url, params] - end - end - - raise RoutingError, "No route matches #{params.inspect}" - end - end - - # Number of routes in the set - def length - @routes.length - end - - def rehash #:nodoc: - @recognition_keys = build_recognition_keys - @recognition_graph = build_recognition_graph - @generation_keys = build_generation_keys - @generation_graph = build_generation_graph - end - - # Finalizes the set and builds optimized data structures. You *must* - # freeze the set before you can use <tt>call</tt> and <tt>url</tt>. - # So remember to call freeze after you are done adding routes. - def freeze - unless frozen? - rehash - - @recognition_key_analyzer = nil - @generation_key_analyzer = nil - @valid_conditions = nil - - @routes.each { |route| route.freeze } - @routes.freeze - end - - super - end - - def marshal_dump #:nodoc: - hash = {} - - instance_variables_to_serialize.each do |ivar| - hash[ivar] = instance_variable_get(ivar) - end - - if graph = hash[:@recognition_graph] - hash[:@recognition_graph] = graph.dup - end - - hash - end - - def marshal_load(hash) #:nodoc: - hash.each do |ivar, value| - instance_variable_set(ivar, value) - end - end - - protected - def recognition_stats - { :keys => @recognition_keys, - :keys_size => @recognition_keys.size, - :graph_size => @recognition_graph.size, - :graph_height => @recognition_graph.height, - :graph_average_height => @recognition_graph.average_height } - end - - private - def expire! #:nodoc: - @recognition_keys = @recognition_graph = nil - @recognition_key_analyzer.expire! - - @generation_keys = @generation_graph = nil - @generation_key_analyzer.expire! - end - - def instance_variables_to_serialize - instance_variables.map { |ivar| ivar.to_sym } - [:@stubbed_request_class, :@optimized_recognize_defined] - end - - # An internal helper method for constructing a nested set from - # the linear route set. - # - # build_nested_route_set([:request_method, :path_info]) { |route, method| - # route.send(method) - # } - def build_nested_route_set(keys, &block) - graph = Multimap.new - @routes.each_with_index do |route, index| - catch(:skip) do - k = keys.map { |key| block.call(key, index) } - Utils.pop_trailing_nils!(k) - k.map! { |key| key || /.+/ } - graph[*k] = route - end - end - graph - end - - def build_recognition_graph - build_nested_route_set(@recognition_keys) { |k, i| - @recognition_key_analyzer.possible_keys[i][k] - } - end - - def build_recognition_keys - @recognition_key_analyzer.report - end - - def build_generation_graph - build_nested_route_set(@generation_keys) { |k, i| - throw :skip unless @routes[i].significant_params? - - if k = @generation_key_analyzer.possible_keys[i][k] - k.to_s - else - nil - end - } - end - - def build_generation_keys - @generation_key_analyzer.report - end - - def extract_params!(*args) - case args.length - when 4 - named_route, params, recall, options = args - when 3 - if args[0].is_a?(Hash) - params, recall, options = args - else - named_route, params, recall = args - end - when 2 - if args[0].is_a?(Hash) - params, recall = args - else - named_route, params = args - end - when 1 - if args[0].is_a?(Hash) - params = args[0] - else - named_route = args[0] - end - else - raise ArgumentError - end - - named_route ||= nil - params ||= {} - recall ||= {} - options ||= {} - - [named_route, params.dup, recall.dup, options.dup] - end - - def stubbed_request_class - @stubbed_request_class ||= begin - klass = Class.new(@request_class) - klass.public_instance_methods.each do |method| - next if method =~ /^__|object_id/ - klass.class_eval <<-RUBY - def #{method}(*args, &block) - @_stubbed_values[:#{method}] || super - end - RUBY - end - klass.class_eval { attr_accessor :_stubbed_values } - klass - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp.rb deleted file mode 100644 index d0d8797008..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp.rb +++ /dev/null @@ -1,68 +0,0 @@ -require 'rack/mount/strexp/parser' - -module Rack::Mount - class Strexp - class << self - # Parses segmented string expression and converts it into a Regexp - # - # Strexp.compile('foo') - # # => %r{\Afoo\Z} - # - # Strexp.compile('foo/:bar', {}, ['/']) - # # => %r{\Afoo/(?<bar>[^/]+)\Z} - # - # Strexp.compile(':foo.example.com') - # # => %r{\A(?<foo>.+)\.example\.com\Z} - # - # Strexp.compile('foo/:bar', {:bar => /[a-z]+/}, ['/']) - # # => %r{\Afoo/(?<bar>[a-z]+)\Z} - # - # Strexp.compile('foo(.:extension)') - # # => %r{\Afoo(\.(?<extension>.+))?\Z} - # - # Strexp.compile('src/*files') - # # => %r{\Asrc/(?<files>.+)\Z} - def compile(str, requirements = {}, separators = [], anchor = true) - return Regexp.compile(str) if str.is_a?(Regexp) - - requirements = requirements ? requirements.dup : {} - normalize_requirements!(requirements, separators) - - parser = StrexpParser.new - parser.anchor = anchor - parser.requirements = requirements - - begin - re = parser.scan_str(str) - rescue Racc::ParseError => e - raise RegexpError, e.message - end - - Regexp.compile(re) - end - alias_method :new, :compile - - private - def normalize_requirements!(requirements, separators) - requirements.each do |key, value| - if value.is_a?(Regexp) - if regexp_has_modifiers?(value) - requirements[key] = value - else - requirements[key] = value.source - end - else - requirements[key] = Regexp.escape(value) - end - end - requirements.default ||= separators.any? ? - "[^#{separators.join}]+" : '.+' - requirements - end - - def regexp_has_modifiers?(regexp) - regexp.options & (Regexp::IGNORECASE | Regexp::EXTENDED) != 0 - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/parser.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/parser.rb deleted file mode 100644 index cfe05afc61..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/parser.rb +++ /dev/null @@ -1,160 +0,0 @@ -# -# DO NOT MODIFY!!!! -# This file is automatically generated by Racc 1.4.6 -# from Racc grammer file "". -# - -require 'racc/parser.rb' - -require 'rack/mount/utils' -require 'rack/mount/strexp/tokenizer' - -module Rack - module Mount - class StrexpParser < Racc::Parser - - -if Regin.regexp_supports_named_captures? - REGEXP_NAMED_CAPTURE = '(?<%s>%s)'.freeze -else - REGEXP_NAMED_CAPTURE = '(?:<%s>%s)'.freeze -end - -attr_accessor :anchor, :requirements -##### State transition tables begin ### - -racc_action_table = [ - 1, 2, 3, 9, 4, 1, 2, 3, 12, 4, - 1, 2, 3, 11, 4, 1, 2, 3, nil, 4 ] - -racc_action_check = [ - 0, 0, 0, 5, 0, 3, 3, 3, 9, 3, - 8, 8, 8, 8, 8, 6, 6, 6, nil, 6 ] - -racc_action_pointer = [ - -2, nil, nil, 3, nil, 3, 13, nil, 8, 8, - nil, nil, nil ] - -racc_action_default = [ - -8, -4, -5, -8, -7, -8, -1, -3, -8, -8, - -2, -6, 13 ] - -racc_goto_table = [ - 6, 5, 10, 8, 10 ] - -racc_goto_check = [ - 2, 1, 3, 2, 3 ] - -racc_goto_pointer = [ - nil, 1, 0, -4 ] - -racc_goto_default = [ - nil, nil, nil, 7 ] - -racc_reduce_table = [ - 0, 0, :racc_error, - 1, 8, :_reduce_1, - 2, 9, :_reduce_2, - 1, 9, :_reduce_none, - 1, 10, :_reduce_4, - 1, 10, :_reduce_5, - 3, 10, :_reduce_6, - 1, 10, :_reduce_7 ] - -racc_reduce_n = 8 - -racc_shift_n = 13 - -racc_token_table = { - false => 0, - :error => 1, - :PARAM => 2, - :GLOB => 3, - :LPAREN => 4, - :RPAREN => 5, - :CHAR => 6 } - -racc_nt_base = 7 - -racc_use_result_var = true - -Racc_arg = [ - racc_action_table, - racc_action_check, - racc_action_default, - racc_action_pointer, - racc_goto_table, - racc_goto_check, - racc_goto_default, - racc_goto_pointer, - racc_nt_base, - racc_reduce_table, - racc_token_table, - racc_shift_n, - racc_reduce_n, - racc_use_result_var ] - -Racc_token_to_s_table = [ - "$end", - "error", - "PARAM", - "GLOB", - "LPAREN", - "RPAREN", - "CHAR", - "$start", - "target", - "expr", - "token" ] - -Racc_debug_parser = false - -##### State transition tables end ##### - -# reduce 0 omitted - -def _reduce_1(val, _values, result) - result = anchor ? "\\A#{val.join}\\Z" : "\\A#{val.join}" - result -end - -def _reduce_2(val, _values, result) - result = val.join - result -end - -# reduce 3 omitted - -def _reduce_4(val, _values, result) - name = val[0].to_sym - requirement = requirements[name] - result = REGEXP_NAMED_CAPTURE % [name, requirement] - - result -end - -def _reduce_5(val, _values, result) - name = val[0].to_sym - requirement = requirements[name] - result = REGEXP_NAMED_CAPTURE % [name, '.+' || requirement] - - result -end - -def _reduce_6(val, _values, result) - result = "(?:#{val[1]})?" - result -end - -def _reduce_7(val, _values, result) - result = Regexp.escape(val[0]) - result -end - -def _reduce_none(val, _values, result) - val[0] -end - - end # class StrexpParser - end # module Mount -end # module Rack diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/parser.y b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/parser.y deleted file mode 100644 index ffbd9fae11..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/parser.y +++ /dev/null @@ -1,34 +0,0 @@ -class Rack::Mount::StrexpParser -rule - target: expr { result = anchor ? "\\A#{val.join}\\Z" : "\\A#{val.join}" } - - expr: expr token { result = val.join } - | token - - token: PARAM { - name = val[0].to_sym - requirement = requirements[name] - result = REGEXP_NAMED_CAPTURE % [name, requirement] - } - | GLOB { - name = val[0].to_sym - requirement = requirements[name] - result = REGEXP_NAMED_CAPTURE % [name, '.+' || requirement] - } - | LPAREN expr RPAREN { result = "(?:#{val[1]})?" } - | CHAR { result = Regexp.escape(val[0]) } -end - ----- header ---- -require 'rack/mount/utils' -require 'rack/mount/strexp/tokenizer' - ----- inner - -if Regin.regexp_supports_named_captures? - REGEXP_NAMED_CAPTURE = '(?<%s>%s)'.freeze -else - REGEXP_NAMED_CAPTURE = '(?:<%s>%s)'.freeze -end - -attr_accessor :anchor, :requirements diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/tokenizer.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/tokenizer.rb deleted file mode 100644 index 0ff7f67661..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/tokenizer.rb +++ /dev/null @@ -1,83 +0,0 @@ -#-- -# DO NOT MODIFY!!!! -# This file is automatically generated by rex 1.0.5.beta1 -# from lexical definition file "lib/rack/mount/strexp/tokenizer.rex". -#++ - -require 'racc/parser' -class Rack::Mount::StrexpParser < Racc::Parser - require 'strscan' - - class ScanError < StandardError ; end - - attr_reader :lineno - attr_reader :filename - attr_accessor :state - - def scan_setup(str) - @ss = StringScanner.new(str) - @lineno = 1 - @state = nil - end - - def action - yield - end - - def scan_str(str) - scan_setup(str) - do_parse - end - alias :scan :scan_str - - def load_file( filename ) - @filename = filename - open(filename, "r") do |f| - scan_setup(f.read) - end - end - - def scan_file( filename ) - load_file(filename) - do_parse - end - - - def next_token - return if @ss.eos? - - text = @ss.peek(1) - @lineno += 1 if text == "\n" - token = case @state - when nil - case - when (text = @ss.scan(/\\(\(|\)|:|\*)/)) - action { [:CHAR, @ss[1]] } - - when (text = @ss.scan(/\:([a-zA-Z_]\w*)/)) - action { [:PARAM, @ss[1]] } - - when (text = @ss.scan(/\*([a-zA-Z_]\w*)/)) - action { [:GLOB, @ss[1]] } - - when (text = @ss.scan(/\(/)) - action { [:LPAREN, text] } - - when (text = @ss.scan(/\)/)) - action { [:RPAREN, text] } - - when (text = @ss.scan(/./)) - action { [:CHAR, text] } - - else - text = @ss.string[@ss.pos .. -1] - raise ScanError, "can not match: '" + text + "'" - end # if - - else - raise ScanError, "undefined state: '" + state.to_s + "'" - end # case state - token - end # def next_token - -end # class diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/tokenizer.rex b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/tokenizer.rex deleted file mode 100644 index 473bd096e1..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp/tokenizer.rex +++ /dev/null @@ -1,12 +0,0 @@ -class Rack::Mount::StrexpParser -macro - RESERVED \(|\)|:|\* - ALPHA_U [a-zA-Z_] -rule - \\({RESERVED}) { [:CHAR, @ss[1]] } - \:({ALPHA_U}\w*) { [:PARAM, @ss[1]] } - \*({ALPHA_U}\w*) { [:GLOB, @ss[1]] } - \( { [:LPAREN, text] } - \) { [:RPAREN, text] } - . { [:CHAR, text] } -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/utils.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/utils.rb deleted file mode 100644 index aa23b1162f..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/utils.rb +++ /dev/null @@ -1,148 +0,0 @@ -begin - require 'regin' -rescue LoadError - $: << File.expand_path(File.join(File.dirname(__FILE__), 'vendor/regin')) - require 'regin' -end - -require 'uri' - -module Rack::Mount - # Private utility methods used throughout Rack::Mount. - #-- - # This module is a trash can. Try to move these functions into - # more appropriate contexts. - #++ - module Utils - # Normalizes URI path. - # - # Strips off trailing slash and ensures there is a leading slash. - # - # normalize_path("/foo") # => "/foo" - # normalize_path("/foo/") # => "/foo" - # normalize_path("foo") # => "/foo" - # normalize_path("") # => "/" - def normalize_path(path) - path = "/#{path}" - path.squeeze!('/') - path.sub!(%r{/+\Z}, '') - path = '/' if path == '' - path - end - module_function :normalize_path - - # Removes trailing nils from array. - # - # pop_trailing_nils!([1, 2, 3]) # => [1, 2, 3] - # pop_trailing_nils!([1, 2, 3, nil, nil]) # => [1, 2, 3] - # pop_trailing_nils!([nil]) # => [] - def pop_trailing_nils!(ary) - while ary.length > 0 && ary.last.nil? - ary.pop - end - ary - end - module_function :pop_trailing_nils! - - RESERVED_PCHAR = ':@&=+$,;%' - SAFE_PCHAR = "#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}" - if RUBY_VERSION >= '1.9' - UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false).freeze - else - UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false, 'N').freeze - end - - Parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI - - def escape_uri(uri) - Parser.escape(uri.to_s, UNSAFE_PCHAR) - end - module_function :escape_uri - - if ''.respond_to?(:force_encoding) - def unescape_uri(uri) - Parser.unescape(uri).force_encoding('utf-8') - end - else - def unescape_uri(uri) - URI.unescape(uri) - end - end - module_function :unescape_uri - - # Taken from Rack 1.1.x to build nested query strings - def build_nested_query(value, prefix = nil) #:nodoc: - case value - when Array - value.map { |v| - build_nested_query(v, "#{prefix}[]") - }.join("&") - when Hash - value.map { |k, v| - build_nested_query(v, prefix ? "#{prefix}[#{Rack::Utils.escape(k)}]" : Rack::Utils.escape(k)) - }.join("&") - when String - raise ArgumentError, "value must be a Hash" if prefix.nil? - "#{prefix}=#{Rack::Utils.escape(value)}" - else - prefix - end - end - module_function :build_nested_query - - # Determines whether the regexp must match the entire string. - # - # regexp_anchored?(/^foo$/) # => true - # regexp_anchored?(/foo/) # => false - # regexp_anchored?(/^foo/) # => false - # regexp_anchored?(/foo$/) # => false - def regexp_anchored?(regexp) - regexp.source =~ /\A(\\A|\^).*(\\Z|\$)\Z/m ? true : false - end - module_function :regexp_anchored? - - def normalize_extended_expression(regexp) - return regexp unless regexp.options & Regexp::EXTENDED != 0 - source = regexp.source - source.gsub!(/#.+$/, '') - source.gsub!(/\s+/, '') - source.gsub!(/\\\//, '/') - Regexp.compile(source) - end - module_function :normalize_extended_expression - - def parse_regexp(regexp) - cache = @@_parse_regexp_cache ||= {} - - if expression = cache[regexp] - return expression - end - - unless regexp.is_a?(RegexpWithNamedGroups) - regexp = RegexpWithNamedGroups.new(regexp) - end - - expression = Regin.parse(regexp) - - unless Regin.regexp_supports_named_captures? - tag_captures = Proc.new do |group| - case group - when Regin::Group - # TODO: dup instead of mutating - group.instance_variable_set('@name', regexp.names[group.index]) if group.index - tag_captures.call(group.expression) - when Regin::Expression - group.each { |child| tag_captures.call(child) } - end - end - tag_captures.call(expression) - end - - cache[regexp] = expression.freeze - expression - rescue Racc::ParseError, Regin::Parser::ScanError - [] - end - module_function :parse_regexp - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multimap.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multimap.rb deleted file mode 100644 index 0b49b49280..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multimap.rb +++ /dev/null @@ -1,569 +0,0 @@ -require 'forwardable' -require 'multiset' - -# Multimap is a generalization of a map or associative array -# abstract data type in which more than one value may be associated -# with and returned for a given key. -# -# == Example -# -# require 'multimap' -# map = Multimap.new -# map["a"] = 100 -# map["b"] = 200 -# map["a"] = 300 -# map["a"] # -> [100, 300] -# map["b"] # -> [200] -# map.keys # -> #<Multiset: {a, a, b}> -class Multimap - extend Forwardable - - include Enumerable - - # call-seq: - # Multimap[ [key =>|, value]* ] => multimap - # - # Creates a new multimap populated with the given objects. - # - # Multimap["a", 100, "b", 200] #=> {"a"=>[100], "b"=>[200]} - # Multimap["a" => 100, "b" => 200] #=> {"a"=>[100], "b"=>[200]} - def self.[](*args) - default = [] - - if args.size == 2 && args.last.is_a?(Hash) - default = args.shift - elsif !args.first.is_a?(Hash) && args.size % 2 == 1 - default = args.shift - end - - if args.size == 1 && args.first.is_a?(Hash) - args[0] = args.first.inject({}) { |hash, (key, value)| - unless value.is_a?(default.class) - value = (default.dup << value) - end - hash[key] = value - hash - } - else - index = 0 - args.map! { |value| - unless index % 2 == 0 || value.is_a?(default.class) - value = (default.dup << value) - end - index += 1 - value - } - end - - map = new - map.instance_variable_set(:@hash, Hash[*args]) - map.default = default - map - end - - # call-seq: - # Multimap.new => multimap - # Multimap.new(default) => multimap - # - # Returns a new, empty multimap. - # - # map = Multimap.new(Set.new) - # h["a"] = 100 - # h["b"] = 200 - # h["a"] #=> [100].to_set - # h["c"] #=> [].to_set - def initialize(default = []) - @hash = Hash.new(default) - end - - def initialize_copy(original) #:nodoc: - @hash = Hash.new(original.default.dup) - original._internal_hash.each_pair do |key, container| - @hash[key] = container.dup - end - end - - def_delegators :@hash, :clear, :default, :default=, :empty?, - :fetch, :has_key?, :key? - - # Retrieves the <i>value</i> object corresponding to the - # <i>*keys</i> object. - def [](key) - @hash[key] - end - - # call-seq: - # map[key] = value => value - # map.store(key, value) => value - # - # Associates the value given by <i>value</i> with the key - # given by <i>key</i>. Unlike a regular hash, multiple can be - # assoicated with the same value. - # - # map = Multimap["a" => 100, "b" => 200] - # map["a"] = 9 - # map["c"] = 4 - # map #=> {"a" => [100, 9], "b" => [200], "c" => [4]} - def store(key, value) - update_container(key) do |container| - container << value - container - end - end - alias_method :[]=, :store - - # call-seq: - # map.delete(key, value) => value - # map.delete(key) => value - # - # Deletes and returns a key-value pair from <i>map</i>. If only - # <i>key</i> is given, all the values matching that key will be - # deleted. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.delete("b", 300) #=> 300 - # map.delete("a") #=> [100] - def delete(key, value = nil) - if value - @hash[key].delete(value) - else - @hash.delete(key) - end - end - - # call-seq: - # map.each { |key, value| block } => map - # - # Calls <i>block</i> for each key/value pair in <i>map</i>, passing - # the key and value to the block as a two-element array. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.each { |key, value| puts "#{key} is #{value}" } - # - # <em>produces:</em> - # - # a is 100 - # b is 200 - # b is 300 - def each - each_pair do |key, value| - yield [key, value] - end - end - - # call-seq: - # map.each_association { |key, container| block } => map - # - # Calls <i>block</i> once for each key/container in <i>map</i>, passing - # the key and container to the block as parameters. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.each_association { |key, container| puts "#{key} is #{container}" } - # - # <em>produces:</em> - # - # a is [100] - # b is [200, 300] - def each_association(&block) - @hash.each_pair(&block) - end - - # call-seq: - # map.each_container { |container| block } => map - # - # Calls <i>block</i> for each container in <i>map</i>, passing the - # container as a parameter. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.each_container { |container| puts container } - # - # <em>produces:</em> - # - # [100] - # [200, 300] - def each_container - each_association do |_, container| - yield container - end - end - - # call-seq: - # map.each_key { |key| block } => map - # - # Calls <i>block</i> for each key in <i>hsh</i>, passing the key - # as a parameter. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.each_key { |key| puts key } - # - # <em>produces:</em> - # - # a - # b - # b - def each_key - each_pair do |key, _| - yield key - end - end - - # call-seq: - # map.each_pair { |key_value_array| block } => map - # - # Calls <i>block</i> for each key/value pair in <i>map</i>, - # passing the key and value as parameters. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.each_pair { |key, value| puts "#{key} is #{value}" } - # - # <em>produces:</em> - # - # a is 100 - # b is 200 - # b is 300 - def each_pair - each_association do |key, values| - values.each do |value| - yield key, value - end - end - end - - # call-seq: - # map.each_value { |value| block } => map - # - # Calls <i>block</i> for each key in <i>map</i>, passing the - # value as a parameter. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.each_value { |value| puts value } - # - # <em>produces:</em> - # - # 100 - # 200 - # 300 - def each_value - each_pair do |_, value| - yield value - end - end - - def ==(other) #:nodoc: - case other - when Multimap - @hash == other._internal_hash - else - @hash == other - end - end - - def eql?(other) #:nodoc: - case other - when Multimap - @hash.eql?(other._internal_hash) - else - @hash.eql?(other) - end - end - - def freeze #:nodoc: - each_container { |container| container.freeze } - default.freeze - super - end - - # call-seq: - # map.has_value?(value) => true or false - # map.value?(value) => true or false - # - # Returns <tt>true</tt> if the given value is present for any key - # in <i>map</i>. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.has_value?(300) #=> true - # map.has_value?(999) #=> false - def has_value?(value) - values.include?(value) - end - alias_method :value?, :has_value? - - # call-seq: - # map.index(value) => key - # - # Returns the key for a given value. If not found, returns - # <tt>nil</tt>. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.index(100) #=> "a" - # map.index(200) #=> "b" - # map.index(999) #=> nil - def index(value) - invert[value] - end - - # call-seq: - # map.delete_if {| key, value | block } -> map - # - # Deletes every key-value pair from <i>map</i> for which <i>block</i> - # evaluates to <code>true</code>. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.delete_if {|key, value| value >= 300 } - # #=> Multimap["a" => 100, "b" => 200] - # - def delete_if - each_association do |key, container| - container.delete_if do |value| - yield [key, value] - end - end - self - end - - # call-seq: - # map.reject {| key, value | block } -> map - # - # Same as <code>Multimap#delete_if</code>, but works on (and returns) a - # copy of the <i>map</i>. Equivalent to - # <code><i>map</i>.dup.delete_if</code>. - # - def reject(&block) - dup.delete_if(&block) - end - - # call-seq: - # map.reject! {| key, value | block } -> map or nil - # - # Equivalent to <code>Multimap#delete_if</code>, but returns - # <code>nil</code> if no changes were made. - # - def reject!(&block) - old_size = size - delete_if(&block) - old_size == size ? nil : self - end - - # call-seq: - # map.replace(other_map) => map - # - # Replaces the contents of <i>map</i> with the contents of - # <i>other_map</i>. - # - # map = Multimap["a" => 100, "b" => 200] - # map.replace({ "c" => 300, "d" => 400 }) - # #=> Multimap["c" => 300, "d" => 400] - def replace(other) - case other - when Array - @hash.replace(self.class[self.default, *other]) - when Hash - @hash.replace(self.class[self.default, other]) - when self.class - @hash.replace(other) - else - raise ArgumentError - end - end - - # call-seq: - # map.invert => multimap - # - # Returns a new multimap created by using <i>map</i>'s values as keys, - # and the keys as values. - # - # map = Multimap["n" => 100, "m" => 100, "d" => [200, 300]] - # map.invert #=> Multimap[100 => ["n", "m"], 200 => "d", 300 => "d"] - def invert - h = self.class.new(default.dup) - each_pair { |key, value| h[value] = key } - h - end - - # call-seq: - # map.keys => multiset - # - # Returns a new +Multiset+ populated with the keys from this hash. See also - # <tt>Multimap#values</tt> and <tt>Multimap#containers</tt>. - # - # map = Multimap["a" => 100, "b" => [200, 300], "c" => 400] - # map.keys #=> Multiset.new(["a", "b", "b", "c"]) - def keys - keys = Multiset.new - each_key { |key| keys << key } - keys - end - - # Returns true if the given key is present in Multimap. - def include?(key) - keys.include?(key) - end - alias_method :member?, :include? - - # call-seq: - # map.length => fixnum - # map.size => fixnum - # - # Returns the number of key-value pairs in the map. - # - # map = Multimap["a" => 100, "b" => [200, 300], "c" => 400] - # map.length #=> 4 - # map.delete("a") #=> 100 - # map.length #=> 3 - def size - values.size - end - alias_method :length, :size - - # call-seq: - # map.merge(other_map) => multimap - # - # Returns a new multimap containing the contents of <i>other_map</i> and - # the contents of <i>map</i>. - # - # map1 = Multimap["a" => 100, "b" => 200] - # map2 = Multimap["a" => 254, "c" => 300] - # map2.merge(map2) #=> Multimap["a" => 100, "b" => [200, 254], "c" => 300] - # map1 #=> Multimap["a" => 100, "b" => 200] - def merge(other) - dup.update(other) - end - - # call-seq: - # map.merge!(other_map) => multimap - # map.update(other_map) => multimap - # - # Adds each pair from <i>other_map</i> to <i>map</i>. - # - # map1 = Multimap["a" => 100, "b" => 200] - # map2 = Multimap["b" => 254, "c" => 300] - # - # map1.merge!(map2) - # #=> Multimap["a" => 100, "b" => [200, 254], "c" => 300] - def update(other) - case other - when self.class - other.each_pair { |key, value| store(key, value) } - when Hash - update(self.class[self.default, other]) - else - raise ArgumentError - end - self - end - alias_method :merge!, :update - - # call-seq: - # map.select { |key, value| block } => multimap - # - # Returns a new Multimap consisting of the pairs for which the - # block returns true. - # - # map = Multimap["a" => 100, "b" => 200, "c" => 300] - # map.select { |k,v| k > "a" } #=> Multimap["b" => 200, "c" => 300] - # map.select { |k,v| v < 200 } #=> Multimap["a" => 100] - def select - inject(self.class.new) { |map, (key, value)| - map[key] = value if yield([key, value]) - map - } - end - - # call-seq: - # map.to_a => array - # - # Converts <i>map</i> to a nested array of [<i>key, - # value</i>] arrays. - # - # map = Multimap["a" => 100, "b" => [200, 300], "c" => 400] - # map.to_a #=> [["a", 100], ["b", 200], ["b", 300], ["c", 400]] - def to_a - ary = [] - each_pair do |key, value| - ary << [key, value] - end - ary - end - - # call-seq: - # map.to_hash => hash - # - # Converts <i>map</i> to a basic hash. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.to_hash #=> { "a" => [100], "b" => [200, 300] } - def to_hash - @hash.dup - end - - # call-seq: - # map.containers => array - # - # Returns a new array populated with the containers from <i>map</i>. See - # also <tt>Multimap#keys</tt> and <tt>Multimap#values</tt>. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.containers #=> [[100], [200, 300]] - def containers - containers = [] - each_container { |container| containers << container } - containers - end - - # call-seq: - # map.values => array - # - # Returns a new array populated with the values from <i>map</i>. See - # also <tt>Multimap#keys</tt> and <tt>Multimap#containers</tt>. - # - # map = Multimap["a" => 100, "b" => [200, 300]] - # map.values #=> [100, 200, 300] - def values - values = [] - each_value { |value| values << value } - values - end - - # Return an array containing the values associated with the given keys. - def values_at(*keys) - @hash.values_at(*keys) - end - - def marshal_dump #:nodoc: - @hash - end - - def marshal_load(hash) #:nodoc: - @hash = hash - end - - def to_yaml(opts = {}) #:nodoc: - YAML::quick_emit(self, opts) do |out| - out.map(taguri, to_yaml_style) do |map| - @hash.each do |k, v| - map.add(k, v) - end - map.add('__default__', @hash.default) - end - end - end - - def yaml_initialize(tag, val) #:nodoc: - default = val.delete('__default__') - @hash = val - @hash.default = default - self - end - - protected - def _internal_hash #:nodoc: - @hash - end - - def update_container(key) #:nodoc: - container = @hash[key] - container = container.dup if container.equal?(default) - container = yield(container) - @hash[key] = container - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb deleted file mode 100644 index 119bf12646..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/multiset.rb +++ /dev/null @@ -1,185 +0,0 @@ -require 'set' - -# Multiset implements a collection of unordered values and -# allows duplicates. -# -# == Example -# -# require 'multiset' -# s1 = Multiset.new [1, 2] # -> #<Multiset: {1, 2}> -# s1.add(2) # -> #<Multiset: {1, 2, 2}> -# s1.merge([2, 6]) # -> #<Multiset: {1, 2, 2, 2, 3}> -# s1.multiplicity(2) # -> 3 -# s1.multiplicity(3) # -> 1 -class Multiset < Set - def initialize(*args, &block) #:nodoc: - @hash = Hash.new(0) - super - end - - # Returns the number of times an element belongs to the multiset. - def multiplicity(e) - @hash[e] - end - - # Returns the total number of elements in a multiset, including - # repeated memberships - def cardinality - @hash.inject(0) { |s, (e, m)| s += m } - end - alias_method :size, :cardinality - alias_method :length, :cardinality - - # Converts the set to an array. The order of elements is uncertain. - def to_a - inject([]) { |ary, (key, _)| ary << key } - end - - # Returns true if the set is a superset of the given set. - def superset?(set) - set.is_a?(self.class) or raise ArgumentError, "value must be a set" - return false if cardinality < set.cardinality - set.all? { |o| set.multiplicity(o) <= multiplicity(o) } - end - - # Returns true if the set is a proper superset of the given set. - def proper_superset?(set) - set.is_a?(self.class) or raise ArgumentError, "value must be a set" - return false if cardinality <= set.cardinality - set.all? { |o| set.multiplicity(o) <= multiplicity(o) } - end - - # Returns true if the set is a subset of the given set. - def subset?(set) - set.is_a?(self.class) or raise ArgumentError, "value must be a set" - return false if set.cardinality < cardinality - all? { |o| multiplicity(o) <= set.multiplicity(o) } - end - - # Returns true if the set is a proper subset of the given set. - def proper_subset?(set) - set.is_a?(self.class) or raise ArgumentError, "value must be a set" - return false if set.cardinality <= cardinality - all? { |o| multiplicity(o) <= set.multiplicity(o) } - end - - # Calls the given block once for each element in the set, passing - # the element as parameter. Returns an enumerator if no block is - # given. - def each - @hash.each_pair do |key, multiplicity| - multiplicity.times do - yield(key) - end - end - self - end - - # Adds the given object to the set and returns self. Use +merge+ to - # add many elements at once. - def add(o) - @hash[o] ||= 0 - @hash[o] += 1 - self - end - alias << add - - undef :add? - - # Deletes all the identical object from the set and returns self. - # If +n+ is given, it will remove that amount of identical objects - # from the set. Use +subtract+ to delete many different items at - # once. - def delete(o, n = nil) - if n - @hash[o] ||= 0 - @hash[o] -= n if @hash[o] > 0 - @hash.delete(o) if @hash[o] == 0 - else - @hash.delete(o) - end - self - end - - undef :delete? - - # Deletes every element of the set for which block evaluates to - # true, and returns self. - def delete_if - each { |o| delete(o) if yield(o) } - self - end - - # Merges the elements of the given enumerable object to the set and - # returns self. - def merge(enum) - enum.each { |o| add(o) } - self - end - - # Deletes every element that appears in the given enumerable object - # and returns self. - def subtract(enum) - enum.each { |o| delete(o, 1) } - self - end - - # Returns a new set containing elements common to the set and the - # given enumerable object. - def &(enum) - s = dup - n = self.class.new - enum.each { |o| - if s.include?(o) - s.delete(o, 1) - n.add(o) - end - } - n - end - alias intersection & - - # Returns a new set containing elements exclusive between the set - # and the given enumerable object. (set ^ enum) is equivalent to - # ((set | enum) - (set & enum)). - def ^(enum) - n = self.class.new(enum) - each { |o| n.include?(o) ? n.delete(o, 1) : n.add(o) } - n - end - - # Returns true if two sets are equal. Two multisets are equal if - # they have the same cardinalities and each element has the same - # multiplicity in both sets. The equality of each element inside - # the multiset is defined according to Object#eql?. - def eql?(set) - return true if equal?(set) - set = self.class.new(set) unless set.is_a?(self.class) - return false unless cardinality == set.cardinality - superset?(set) && subset?(set) - end - alias_method :==, :eql? - - def marshal_dump #:nodoc: - @hash - end - - def marshal_load(hash) #:nodoc: - @hash = hash - end - - def to_yaml(opts = {}) #:nodoc: - YAML::quick_emit(self, opts) do |out| - out.map(taguri, to_yaml_style) do |map| - @hash.each do |k, v| - map.add(k, v) - end - end - end - end - - def yaml_initialize(tag, val) #:nodoc: - @hash = val - self - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/nested_multimap.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/nested_multimap.rb deleted file mode 100644 index 4eb088b91a..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/multimap/nested_multimap.rb +++ /dev/null @@ -1,158 +0,0 @@ -require 'multimap' - -# NestedMultimap allows values to be assoicated with a nested -# set of keys. -class NestedMultimap < Multimap - # call-seq: - # multimap[*keys] = value => value - # multimap.store(*keys, value) => value - # - # Associates the value given by <i>value</i> with multiple key - # given by <i>keys</i>. - # - # map = NestedMultimap.new - # map["a"] = 100 - # map["a", "b"] = 101 - # map["a"] = 102 - # map #=> {"a"=>{"b"=>[100, 101, 102], default => [100, 102]}} - def store(*args) - keys = args - value = args.pop - - raise ArgumentError, 'wrong number of arguments (1 for 2)' unless value - - if keys.length > 1 - update_container(keys.shift) do |container| - container = self.class.new(container) unless container.is_a?(self.class) - container[*keys] = value - container - end - elsif keys.length == 1 - super(keys.first, value) - else - self << value - end - end - alias_method :[]=, :store - - # call-seq: - # multimap << obj => multimap - # - # Pushes the given object on to the end of all the containers. - # - # map = NestedMultimap["a" => [100], "b" => [200, 300]] - # map << 300 - # map["a"] #=> [100, 300] - # map["c"] #=> [300] - def <<(value) - @hash.each_value { |container| container << value } - self.default << value - self - end - - # call-seq: - # multimap[*keys] => value - # multimap[key1, key2, key3] => value - # - # Retrieves the <i>value</i> object corresponding to the - # <i>*keys</i> object. - def [](*keys) - i, l, r, k = 0, keys.length, self, self.class - while r.is_a?(k) - r = i < l ? r._internal_hash[keys[i]] : r.default - i += 1 - end - r - end - - # call-seq: - # multimap.each_association { |key, container| block } => multimap - # - # Calls <i>block</i> once for each key/container in <i>map</i>, passing - # the key and container to the block as parameters. - # - # map = NestedMultimap.new - # map["a"] = 100 - # map["a", "b"] = 101 - # map["a"] = 102 - # map["c"] = 200 - # map.each_association { |key, container| puts "#{key} is #{container}" } - # - # <em>produces:</em> - # - # ["a", "b"] is [100, 101, 102] - # "c" is [200] - def each_association - super() do |key, container| - if container.respond_to?(:each_association) - container.each_association do |nested_key, value| - yield [key, nested_key].flatten, value - end - else - yield key, container - end - end - end - - # call-seq: - # multimap.each_container_with_default { |container| block } => map - # - # Calls <i>block</i> for every container in <i>map</i> including - # the default, passing the container as a parameter. - # - # map = NestedMultimap.new - # map["a"] = 100 - # map["a", "b"] = 101 - # map["a"] = 102 - # map.each_container_with_default { |container| puts container } - # - # <em>produces:</em> - # - # [100, 101, 102] - # [100, 102] - # [] - def each_container_with_default(&block) - @hash.each_value do |container| - iterate_over_container(container, &block) - end - iterate_over_container(default, &block) - self - end - - # call-seq: - # multimap.containers_with_default => array - # - # Returns a new array populated with all the containers from - # <i>map</i> including the default. - # - # map = NestedMultimap.new - # map["a"] = 100 - # map["a", "b"] = 101 - # map["a"] = 102 - # map.containers_with_default #=> [[100, 101, 102], [100, 102], []] - def containers_with_default - containers = [] - each_container_with_default { |container| containers << container } - containers - end - - def inspect #:nodoc: - super.gsub(/\}$/, ", default => #{default.inspect}}") - end - - private - def iterate_over_container(container) - if container.respond_to?(:each_container_with_default) - container.each_container_with_default do |value| - yield value - end - else - yield container - end - end -end - -begin - require 'nested_multimap_ext' -rescue LoadError -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin.rb deleted file mode 100644 index d38922bcc6..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin.rb +++ /dev/null @@ -1,45 +0,0 @@ -module Regin - autoload :Alternation, 'regin/alternation' - autoload :Anchor, 'regin/anchor' - autoload :Atom, 'regin/atom' - autoload :Character, 'regin/character' - autoload :CharacterClass, 'regin/character_class' - autoload :Collection, 'regin/collection' - autoload :Expression, 'regin/expression' - autoload :Group, 'regin/group' - autoload :Options, 'regin/options' - autoload :Parser, 'regin/parser' - - class << self - begin - eval('foo = /(?<foo>.*)/').named_captures - - # Returns true if the interpreter is using the Oniguruma Regexp lib - # and supports named captures. - # - # /(?<foo>bar)/ - def regexp_supports_named_captures? - true - end - rescue SyntaxError, NoMethodError - def regexp_supports_named_captures? #:nodoc: - false - end - end - - # Parses Regexp and returns a Expression data structure. - def parse(regexp) - Parser.parse_regexp(regexp) - end - - # Recompiles Regexp by parsing it and turning it back into a Regexp. - # - # (In the future Regin will perform some Regexp optimizations - # such as removing unnecessary captures and options) - def compile(source) - regexp = Regexp.compile(source) - expression = parse(regexp) - Regexp.compile(expression.to_s(true), expression.flags) - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/alternation.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/alternation.rb deleted file mode 100644 index ce4f52bfdb..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/alternation.rb +++ /dev/null @@ -1,40 +0,0 @@ -module Regin - class Alternation < Collection - def initialize(*args) - args, options = extract_options(args) - - if args.length == 1 && args.first.instance_of?(Array) - super(args.first) - else - super(args) - end - - if options.key?(:ignorecase) - @array.map! { |e| e.dup(:ignorecase => options[:ignorecase]) } - end - end - - # Returns true if expression could be treated as a literal string. - # - # Alternation groups are never literal. - def literal? - false - end - - def flags - 0 - end - - def dup(options = {}) - self.class.new(to_a, options) - end - - def to_s(parent = false) - map { |e| e.to_s(parent) }.join('|') - end - - def inspect #:nodoc: - to_s.inspect - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/anchor.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/anchor.rb deleted file mode 100644 index 05520dd5e0..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/anchor.rb +++ /dev/null @@ -1,4 +0,0 @@ -module Regin - class Anchor < Atom - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/atom.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/atom.rb deleted file mode 100644 index eb1923a5a1..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/atom.rb +++ /dev/null @@ -1,59 +0,0 @@ -module Regin - class Atom - attr_reader :value, :ignorecase - - def initialize(value, options = {}) - @value = value - @ignorecase = options[:ignorecase] - end - - def option_names - %w( ignorecase ) - end - - # Returns true if expression could be treated as a literal string. - def literal? - false - end - - def casefold? - ignorecase ? true : false - end - - def dup(options = {}) - original_options = option_names.inject({}) do |h, m| - h[m.to_sym] = send(m) - h - end - self.class.new(value, original_options.merge(options)) - end - - def to_s(parent = false) - "#{value}" - end - - def inspect #:nodoc: - "#<#{self.class.to_s.sub('Regin::', '')} #{to_s.inspect}>" - end - - def ==(other) #:nodoc: - case other - when String - other == to_s - else - eql?(other) - end - end - - def eql?(other) #:nodoc: - other.instance_of?(self.class) && - self.value.eql?(other.value) && - (!!self.ignorecase).eql?(!!other.ignorecase) - end - - def freeze #:nodoc: - value.freeze - super - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/character.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/character.rb deleted file mode 100644 index 12a9199d2a..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/character.rb +++ /dev/null @@ -1,56 +0,0 @@ -module Regin - class Character < Atom - attr_reader :quantifier - - def initialize(value, options = {}) - @quantifier = options[:quantifier] - super - end - - def option_names - %w( quantifier ) + super - end - - # Returns true if expression could be treated as a literal string. - # - # A Character is literal is there is no quantifier attached to it. - def literal? - quantifier.nil? && !ignorecase - end - - def to_s(parent = false) - if !parent && ignorecase - "(?i-mx:#{value})#{quantifier}" - else - "#{value}#{quantifier}" - end - end - - def to_regexp(anchored = false) - re = to_s(true) - re = "\\A#{re}\\Z" if anchored - Regexp.compile(re, ignorecase) - end - - def match(char) - to_regexp(true).match(char) - end - - def include?(char) - if ignorecase - value.downcase == char.downcase - else - value == char - end - end - - def eql?(other) #:nodoc: - super && quantifier.eql?(other.quantifier) - end - - def freeze #:nodoc: - quantifier.freeze if quantifier - super - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/character_class.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/character_class.rb deleted file mode 100644 index caed5ef9d0..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/character_class.rb +++ /dev/null @@ -1,55 +0,0 @@ -module Regin - class CharacterClass < Character - def initialize(value, options = {}) - @negate = options[:negate] - super - end - - def option_names - %w( negate ) + super - end - - attr_reader :negate - - def negated? - negate ? true : false - end - - # Returns true if expression could be treated as a literal string. - # - # A CharacterClass is never literal. - def literal? - false - end - - def bracketed? - value != '.' && value !~ /^\\[dDsSwW]$/ - end - - def to_s(parent = false) - if bracketed? - if !parent && ignorecase - "(?i-mx:[#{negate && '^'}#{value}])#{quantifier}" - else - "[#{negate && '^'}#{value}]#{quantifier}" - end - else - super - end - end - - def include?(char) - re = quantifier ? to_s.sub(/#{Regexp.escape(quantifier)}$/, '') : to_s - Regexp.compile("\\A#{re}\\Z").match(char) - end - - def eql?(other) #:nodoc: - super && negate == other.negate - end - - def freeze #:nodoc: - negate.freeze if negate - super - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/collection.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/collection.rb deleted file mode 100644 index b60353268a..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/collection.rb +++ /dev/null @@ -1,83 +0,0 @@ -module Regin - class Collection - include Enumerable - - def initialize(*args) - @array = Array.new(*args) - end - - def each - @array.each{ |item| yield item } - end - - def [](i) - @array[i] - end - - def length - @array.length - end - alias_method :size, :length - - def first - @array.first - end - - def last - @array.last - end - - def +(other) - ary = other.is_a?(self.class) ? other.internal_array : other - self.class.new(@array + ary) - end - - def to_regexp(anchored = false) - re = to_s(true) - re = "\\A#{re}\\Z" if anchored - Regexp.compile(re, flags) - end - - def match(char) - to_regexp.match(char) - end - - def include?(char) - any? { |e| e.include?(char) } - end - - def ==(other) #:nodoc: - case other - when String - other == to_s - when Array - other == @array - else - eql?(other) - end - end - - def eql?(other) #:nodoc: - other.instance_of?(self.class) && @array.eql?(other.internal_array) - end - - def freeze #:nodoc: - each { |e| e.freeze } - @array.freeze - super - end - - protected - def internal_array #:nodoc: - @array - end - - def extract_options(args) - if args.last.is_a?(Hash) - return args[0..-2], args.last - else - return args, {} - end - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/expression.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/expression.rb deleted file mode 100644 index 18e4965097..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/expression.rb +++ /dev/null @@ -1,126 +0,0 @@ -module Regin - class Expression < Collection - attr_reader :ignorecase, :multiline, :extended - - def initialize(*args) - args, options = extract_options(args) - - @multiline = @ignorecase = @extended = nil - - if args.length == 1 && args.first.instance_of?(Array) - super(args.first) - else - args = args.map { |e| e.instance_of?(String) ? Character.new(e) : e } - super(args) - end - - self.multiline = options[:multiline] if options.key?(:multiline) - self.ignorecase = options[:ignorecase] if options.key?(:ignorecase) - self.extended = options[:extended] if options.key?(:extended) - end - - # Returns true if expression could be treated as a literal string. - # - # A Expression is literal if all its elements are literal. - def literal? - !ignorecase && all? { |e| e.literal? } - end - - def anchored? - anchored_to_start? && anchored_to_end? - end - - def anchored_to_start? - first.is_a?(Anchor) && first == '\A' - end - - def anchored_to_end? - last.is_a?(Anchor) && last == '\Z' - end - - def anchored_to_line? - anchored_to_start_of_line? && anchored_to_end_of_line? - end - - def anchored_to_start_of_line? - anchored_to_start? || (first.is_a?(Anchor) && first == '^') - end - - def anchored_to_end_of_line? - anchored_to_end? || (last.is_a?(Anchor) && last == '$') - end - - def options? - options.any?(true) - end - - def flags - options.to_i - end - - def +(other) - ary = other.is_a?(self.class) ? other.internal_array : other - ary = @array + ary + [options.to_h(true)] - self.class.new(*ary) - end - - def dup(options = {}) - expression = super() - expression.multiline = options[:multiline] if options.key?(:multiline) - expression.ignorecase = options[:ignorecase] if options.key?(:ignorecase) - expression.extended = options[:extended] if options.key?(:extended) - expression - end - - def to_s(parent = false) - if parent || !options? - map { |e| e.to_s(parent) }.join - else - with, without = [], [] - multiline ? (with << 'm') : (without << 'm') - ignorecase ? (with << 'i') : (without << 'i') - extended ? (with << 'x') : (without << 'x') - - with = with.join - without = without.any? ? "-#{without.join}" : '' - - "(?#{with}#{without}:#{map { |e| e.to_s(true) }.join})" - end - end - - def inspect #:nodoc: - "#<Expression #{to_s.inspect}>" - end - - def casefold? - ignorecase - end - - def eql?(other) #:nodoc: - super && - !!self.multiline == !!other.multiline && - !!self.ignorecase == !!other.ignorecase && - !!self.extended == !!other.extended - end - - protected - def options - Options.new(multiline, ignorecase, extended) - end - - def multiline=(multiline) - @multiline = multiline - end - - def ignorecase=(ignorecase) - if @ignorecase.nil? - @array.map! { |e| e.dup(:ignorecase => ignorecase) } - @ignorecase = ignorecase - end - end - - def extended=(extended) - @extended = extended - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/group.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/group.rb deleted file mode 100644 index d682148bd9..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/group.rb +++ /dev/null @@ -1,90 +0,0 @@ -module Regin - class Group - attr_reader :expression, :quantifier, :capture, :index, :name - - def initialize(expression, options = {}) - @quantifier = @index = @name = nil - @capture = true - @expression = expression.dup(options) - - @quantifier = options[:quantifier] if options.key?(:quantifier) - @capture = options[:capture] if options.key?(:capture) - @index = options[:index] if options.key?(:index) - @name = options[:name] if options.key?(:name) - end - - def option_names - %w( quantifier capture index name ) - end - - # Returns true if expression could be treated as a literal string. - # - # A Group is literal if its expression is literal and it has no quantifier. - def literal? - quantifier.nil? && expression.literal? - end - - def to_s(parent = false) - if !expression.options? - "(#{capture ? '' : '?:'}#{expression.to_s(parent)})#{quantifier}" - elsif capture == false - "#{expression.to_s}#{quantifier}" - else - "(#{expression.to_s})#{quantifier}" - end - end - - def to_regexp(anchored = false) - re = to_s - re = "\\A#{re}\\Z" if anchored - Regexp.compile(re) - end - - def dup(options = {}) - original_options = option_names.inject({}) do |h, m| - h[m.to_sym] = send(m) - h - end - self.class.new(expression, original_options.merge(options)) - end - - def inspect #:nodoc: - to_s.inspect - end - - def match(char) - to_regexp.match(char) - end - - def include?(char) - expression.include?(char) - end - - def capture? - capture - end - - def ==(other) #:nodoc: - case other - when String - other == to_s - else - eql?(other) - end - end - - def eql?(other) #:nodoc: - other.is_a?(self.class) && - self.expression == other.expression && - self.quantifier == other.quantifier && - self.capture == other.capture && - self.index == other.index && - self.name == other.name - end - - def freeze #:nodoc: - expression.freeze if expression - super - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/options.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/options.rb deleted file mode 100644 index 03ba29d9a5..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/options.rb +++ /dev/null @@ -1,55 +0,0 @@ -module Regin - class Options - def self.from_int(flags) - multiline = flags & Regexp::MULTILINE != 0 - ignorecase = flags & Regexp::IGNORECASE != 0 - extended = flags & Regexp::EXTENDED != 0 - - new(multiline, ignorecase, extended) - end - - attr_reader :multiline, :ignorecase, :extended - - def initialize(*args) - if args.first.is_a?(Hash) - @multiline = args[0][:multiline] - @ignorecase = args[0][:ignorecase] - @extended = args[0][:extended] - else - @multiline = args[0] - @ignorecase = args[1] - @extended = args[2] - end - end - - def any?(explicit = false) - if explicit - !multiline.nil? || !ignorecase.nil? || !extended.nil? - else - multiline || ignorecase || extended - end - end - - def to_h(explicit = false) - if explicit - options = {} - options[:multiline] = multiline unless multiline.nil? - options[:ignorecase] = ignorecase unless ignorecase.nil? - options[:extended] = extended unless extended.nil? - options - else - { :multiline => multiline, - :ignorecase => ignorecase, - :extended => extended } - end - end - - def to_i - flag = 0 - flag |= Regexp::MULTILINE if multiline - flag |= Regexp::IGNORECASE if ignorecase - flag |= Regexp::EXTENDED if extended - flag - end - end -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/parser.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/parser.rb deleted file mode 100644 index 0bb9b87e9c..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/parser.rb +++ /dev/null @@ -1,415 +0,0 @@ -# -# DO NOT MODIFY!!!! -# This file is automatically generated by Racc 1.4.6 -# from Racc grammer file "". -# - -require 'racc/parser.rb' -module Regin - class Parser < Racc::Parser #:nodoc: all - -def self.parse_regexp(regexp) - options = Options.from_int(regexp.options) - - parser = new - parser.options_stack << options.to_h - - expression = parser.scan_str(regexp.source) - expression = expression.dup(options.to_h) if options.any? - expression -end - -attr_accessor :options_stack - -def initialize - @capture_index = 0 - @capture_index_stack = [] - @options_stack = [] -end - -##### State transition tables begin ### - -racc_action_table = [ - 2, 18, 19, 19, 8, 10, 11, 13, 48, 19, - 2, 45, 3, 5, 8, 10, 11, 13, 64, 47, - 2, 55, 3, 5, 8, 10, 11, 13, 29, 19, - 2, 16, 3, 5, 8, 10, 11, 13, 61, 19, - 2, 63, 3, 5, 8, 10, 11, 13, 60, 36, - 2, 34, 3, 5, 8, 10, 11, 13, 28, 49, - 2, nil, 3, 5, 8, 10, 11, 13, nil, nil, - 2, nil, 3, 5, 8, 10, 11, 13, nil, 26, - 42, 43, 3, 5, 37, 38, 40, 21, 44, 37, - 38, 40, 22, 23, 24, 14, nil, 15, 31, 32, - 16, nil, 33, 46, 32, nil, nil, 33, 51, 37, - 38, 40, 58, 37, 38, 40, 37, 38, 40, 37, - 38, 40, 37, 38, 40, 37, 38, 40, 37, 38, - 40 ] - -racc_action_check = [ - 0, 4, 27, 4, 0, 0, 0, 0, 36, 56, - 49, 27, 0, 0, 49, 49, 49, 49, 56, 36, - 43, 48, 49, 49, 43, 43, 43, 43, 15, 53, - 6, 15, 43, 43, 6, 6, 6, 6, 53, 52, - 42, 55, 6, 6, 42, 42, 42, 42, 52, 24, - 35, 18, 42, 42, 35, 35, 35, 35, 14, 39, - 19, nil, 35, 35, 19, 19, 19, 19, nil, nil, - 13, nil, 19, 19, 13, 13, 13, 13, nil, 13, - 26, 26, 13, 13, 54, 54, 54, 9, 26, 26, - 26, 26, 9, 9, 9, 2, nil, 2, 17, 17, - 2, nil, 17, 30, 30, nil, nil, 30, 41, 41, - 41, 41, 50, 50, 50, 50, 44, 44, 44, 59, - 59, 59, 58, 58, 58, 51, 51, 51, 62, 62, - 62 ] - -racc_action_pointer = [ - -3, nil, 91, nil, 1, nil, 27, nil, nil, 75, - nil, nil, nil, 67, 53, 22, nil, 93, 51, 57, - nil, nil, nil, nil, 40, nil, 67, 0, nil, nil, - 98, nil, nil, nil, nil, 47, -1, nil, nil, 46, - nil, 87, 37, 17, 94, nil, nil, nil, 12, 7, - 91, 103, 37, 27, 62, 21, 7, nil, 100, 97, - nil, nil, 106, nil, nil, nil, nil, nil ] - -racc_action_default = [ - -37, -13, -37, -19, -37, -20, -2, -4, -11, -6, - -12, -14, -7, -37, -37, -29, -28, -37, -37, -37, - -3, -23, -21, -22, -37, -5, -37, -37, -8, -29, - -37, -9, -27, -26, 68, -1, -37, -34, -35, -37, - -36, -37, -37, -37, -37, -15, -10, -25, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -33, -37, -37, - -17, -18, -37, -24, -16, -32, -31, -30 ] - -racc_goto_table = [ - 4, 41, 20, 35, 17, 39, 25, nil, nil, nil, - nil, nil, nil, 27, nil, nil, 50, 30, nil, 54, - nil, nil, nil, nil, nil, 57, 59, nil, nil, 62, - nil, 20, nil, 65, 66, nil, nil, 67, nil, nil, - nil, nil, 52, 53, nil, nil, nil, nil, nil, 56 ] - -racc_goto_check = [ - 1, 10, 3, 2, 7, 9, 5, nil, nil, nil, - nil, nil, nil, 1, nil, nil, 10, 7, nil, 10, - nil, nil, nil, nil, nil, 10, 10, nil, nil, 10, - nil, 3, nil, 10, 10, nil, nil, 10, nil, nil, - nil, nil, 1, 1, nil, nil, nil, nil, nil, 1 ] - -racc_goto_pointer = [ - nil, 0, -16, -4, nil, -3, nil, 2, nil, -21, - -25 ] - -racc_goto_default = [ - nil, nil, 6, 7, 9, nil, 12, nil, 1, nil, - nil ] - -racc_reduce_table = [ - 0, 0, :racc_error, - 3, 26, :_reduce_1, - 1, 26, :_reduce_2, - 2, 27, :_reduce_3, - 1, 27, :_reduce_4, - 2, 28, :_reduce_5, - 1, 28, :_reduce_none, - 1, 29, :_reduce_none, - 3, 29, :_reduce_8, - 3, 29, :_reduce_9, - 4, 29, :_reduce_10, - 1, 29, :_reduce_11, - 1, 29, :_reduce_12, - 1, 29, :_reduce_13, - 1, 29, :_reduce_14, - 3, 31, :_reduce_15, - 6, 31, :_reduce_16, - 5, 31, :_reduce_17, - 5, 31, :_reduce_18, - 1, 33, :_reduce_none, - 1, 33, :_reduce_none, - 1, 30, :_reduce_none, - 1, 30, :_reduce_none, - 1, 30, :_reduce_none, - 5, 30, :_reduce_24, - 3, 30, :_reduce_25, - 2, 32, :_reduce_26, - 2, 32, :_reduce_27, - 1, 32, :_reduce_none, - 1, 32, :_reduce_none, - 4, 34, :_reduce_30, - 4, 34, :_reduce_31, - 4, 34, :_reduce_32, - 3, 34, :_reduce_33, - 1, 35, :_reduce_34, - 1, 35, :_reduce_35, - 1, 35, :_reduce_36 ] - -racc_reduce_n = 37 - -racc_shift_n = 68 - -racc_token_table = { - false => 0, - :error => 1, - :BAR => 2, - :LBRACK => 3, - :CTYPE => 4, - :RBRACK => 5, - :NEGATE => 6, - :CCLASS => 7, - :DOT => 8, - :CHAR => 9, - :LPAREN => 10, - :RPAREN => 11, - :QMARK => 12, - :COLON => 13, - :NAME => 14, - :L_ANCHOR => 15, - :R_ANCHOR => 16, - :STAR => 17, - :PLUS => 18, - :LCURLY => 19, - :RCURLY => 20, - :MINUS => 21, - :MULTILINE => 22, - :IGNORECASE => 23, - :EXTENDED => 24 } - -racc_nt_base = 25 - -racc_use_result_var = true - -Racc_arg = [ - racc_action_table, - racc_action_check, - racc_action_default, - racc_action_pointer, - racc_goto_table, - racc_goto_check, - racc_goto_default, - racc_goto_pointer, - racc_nt_base, - racc_reduce_table, - racc_token_table, - racc_shift_n, - racc_reduce_n, - racc_use_result_var ] - -Racc_token_to_s_table = [ - "$end", - "error", - "BAR", - "LBRACK", - "CTYPE", - "RBRACK", - "NEGATE", - "CCLASS", - "DOT", - "CHAR", - "LPAREN", - "RPAREN", - "QMARK", - "COLON", - "NAME", - "L_ANCHOR", - "R_ANCHOR", - "STAR", - "PLUS", - "LCURLY", - "RCURLY", - "MINUS", - "MULTILINE", - "IGNORECASE", - "EXTENDED", - "$start", - "expression", - "subexpression", - "quantified_atom", - "atom", - "quantifier", - "group", - "bracket_expression", - "anchor", - "options", - "modifier" ] - -Racc_debug_parser = false - -##### State transition tables end ##### - -# reduce 0 omitted - -def _reduce_1(val, _values, result) - # TODO remove this conditional by breaking - # it into another production - if val[0][0].is_a?(Regin::Alternation) - alt = val[0][0] + [Expression.new(val[2])] - else - alt = Alternation.new(val[0], Expression.new(val[2])) - end - result = Expression.new(alt) - - result -end - -def _reduce_2(val, _values, result) - result = Expression.new(val[0]) - result -end - -def _reduce_3(val, _values, result) - result = val[0] + [val[1]] - result -end - -def _reduce_4(val, _values, result) - result = [val[0]] - result -end - -def _reduce_5(val, _values, result) - result = val[0].dup(:quantifier => val[1]) - result -end - -# reduce 6 omitted - -# reduce 7 omitted - -def _reduce_8(val, _values, result) - result = CharacterClass.new(val[1]) - result -end - -def _reduce_9(val, _values, result) - result = CharacterClass.new(val[1]) - result -end - -def _reduce_10(val, _values, result) - result = CharacterClass.new(val[2], :negate => true) - result -end - -def _reduce_11(val, _values, result) - result = CharacterClass.new(val[0]) - result -end - -def _reduce_12(val, _values, result) - result = CharacterClass.new('.') - result -end - -def _reduce_13(val, _values, result) - result = Anchor.new(val[0]) - result -end - -def _reduce_14(val, _values, result) - result = Character.new(val[0]) - result -end - -def _reduce_15(val, _values, result) - result = Group.new(val[1], :index => @capture_index_stack.pop) - - result -end - -def _reduce_16(val, _values, result) - result = Group.new(val[4], val[2].merge(:capture => false)) - @options_stack.pop - - result -end - -def _reduce_17(val, _values, result) - result = Group.new(val[3], :capture => false); - - result -end - -def _reduce_18(val, _values, result) - result = Group.new(val[3], :name => val[2], :index => @capture_index_stack.pop); - - result -end - -# reduce 19 omitted - -# reduce 20 omitted - -# reduce 21 omitted - -# reduce 22 omitted - -# reduce 23 omitted - -def _reduce_24(val, _values, result) - result = val.join - result -end - -def _reduce_25(val, _values, result) - result = val.join - result -end - -def _reduce_26(val, _values, result) - result = val.join - result -end - -def _reduce_27(val, _values, result) - result = val.join - result -end - -# reduce 28 omitted - -# reduce 29 omitted - -def _reduce_30(val, _values, result) - @options_stack << result = { val[1] => false, val[2] => false, val[3] => false } - - result -end - -def _reduce_31(val, _values, result) - @options_stack << result = { val[0] => true, val[2] => false, val[3] => false } - - result -end - -def _reduce_32(val, _values, result) - @options_stack << result = { val[0] => true, val[1] => true, val[3] => false } - - result -end - -def _reduce_33(val, _values, result) - @options_stack << result = { val[0] => true, val[1] => true, val[2] => true } - - result -end - -def _reduce_34(val, _values, result) - result = :multiline - result -end - -def _reduce_35(val, _values, result) - result = :ignorecase - result -end - -def _reduce_36(val, _values, result) - result = :extended - result -end - -def _reduce_none(val, _values, result) - val[0] -end - - end # class Parser -end # module Regin - -require 'regin/tokenizer' diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/tokenizer.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/tokenizer.rb deleted file mode 100644 index 59e4ffb611..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/tokenizer.rb +++ /dev/null @@ -1,213 +0,0 @@ -#-- -# DO NOT MODIFY!!!! -# This file is automatically generated by rex 1.0.5.beta1 -# from lexical definition file "lib/regin/tokenizer.rex". -#++ - -require 'racc/parser' -class Regin::Parser < Racc::Parser - require 'strscan' - - class ScanError < StandardError ; end - - attr_reader :lineno - attr_reader :filename - attr_accessor :state - - def scan_setup(str) - @ss = StringScanner.new(str) - @lineno = 1 - @state = nil - end - - def action - yield - end - - def scan_str(str) - scan_setup(str) - do_parse - end - alias :scan :scan_str - - def load_file( filename ) - @filename = filename - open(filename, "r") do |f| - scan_setup(f.read) - end - end - - def scan_file( filename ) - load_file(filename) - do_parse - end - - - def next_token - return if @ss.eos? - - text = @ss.peek(1) - @lineno += 1 if text == "\n" - token = case @state - when nil - case - when (text = @ss.scan(/\\[dDsSwW]/)) - action { [:CCLASS, text] } - - when (text = @ss.scan(/\^|\\A/)) - action { [:L_ANCHOR, text] } - - when (text = @ss.scan(/\$|\\Z/)) - action { [:R_ANCHOR, text] } - - when (text = @ss.scan(/<(\w+)>/)) - action { [:NAME, @ss[1]] } - - when (text = @ss.scan(/\(/)) - action { - @capture_index_stack << @capture_index - @capture_index += 1 - @state = :OPTIONS if @ss.peek(1) == '?'; - [:LPAREN, text] - } - - - when (text = @ss.scan(/\)/)) - action { [:RPAREN, text] } - - when (text = @ss.scan(/\[/)) - action { @state = :CCLASS; [:LBRACK, text] } - - when (text = @ss.scan(/\{/)) - action { [:LCURLY, text] } - - when (text = @ss.scan(/\}/)) - action { [:RCURLY, text] } - - when (text = @ss.scan(/\|/)) - action { [:BAR, text] } - - when (text = @ss.scan(/\./)) - action { [:DOT, text] } - - when (text = @ss.scan(/\?/)) - action { [:QMARK, text] } - - when (text = @ss.scan(/\+(?:\?)/)) - action { [:PLUS, text] } - - when (text = @ss.scan(/\*(?:\?)/)) - action { [:STAR, text] } - - when (text = @ss.scan(/\#/)) - action { - if @options_stack[-1][:extended] - @state = :COMMENT; - next_token - else - [:CHAR, text] - end - } - - - when (text = @ss.scan(/\s|\n/)) - action { - if @options_stack[-1][:extended] - next_token - else - [:CHAR, text] - end - } - - - when (text = @ss.scan(/\\(.)/)) - action { [:CHAR, @ss[1]] } - - when (text = @ss.scan(/./)) - action { [:CHAR, text] } - - else - text = @ss.string[@ss.pos .. -1] - raise ScanError, "can not match: '" + text + "'" - end # if - - when :CCLASS - case - when (text = @ss.scan(/\]/)) - action { @state = nil; [:RBRACK, text] } - - when (text = @ss.scan(/\^/)) - action { [:NEGATE, text] } - - when (text = @ss.scan(/:(alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit):/)) - action { [:CTYPE, text] } - - when (text = @ss.scan(/\\-/)) - action { [:CHAR, text] } - - when (text = @ss.scan(/\\(.)/)) - action { [:CHAR, @ss[1]] } - - when (text = @ss.scan(/./)) - action { [:CHAR, text] } - - else - text = @ss.string[@ss.pos .. -1] - raise ScanError, "can not match: '" + text + "'" - end # if - - when :OPTIONS - case - when (text = @ss.scan(/\?/)) - action { - @state = nil unless @ss.peek(1) =~ /-|m|i|x|:/ - [:QMARK, text] - } - - - when (text = @ss.scan(/\-/)) - action { [:MINUS, text] } - - when (text = @ss.scan(/m/)) - action { [:MULTILINE, text] } - - when (text = @ss.scan(/i/)) - action { [:IGNORECASE, text] } - - when (text = @ss.scan(/x/)) - action { [:EXTENDED, text] } - - when (text = @ss.scan(/\:/)) - action { - @capture_index_stack.pop - @capture_index -= 1 - @state = nil; - [:COLON, text] - } - - - else - text = @ss.string[@ss.pos .. -1] - raise ScanError, "can not match: '" + text + "'" - end # if - - when :COMMENT - case - when (text = @ss.scan(/\n/)) - action { @state = nil; next_token } - - when (text = @ss.scan(/./)) - action { next_token } - - else - text = @ss.string[@ss.pos .. -1] - raise ScanError, "can not match: '" + text + "'" - end # if - - else - raise ScanError, "undefined state: '" + state.to_s + "'" - end # case state - token - end # def next_token - -end # class diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/version.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/version.rb deleted file mode 100644 index 7ad2a5a25e..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/vendor/regin/regin/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Regin - Version = '0.3.3' -end diff --git a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/version.rb b/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/version.rb deleted file mode 100644 index a3688b102e..0000000000 --- a/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -module Rack - module Mount - Version = '0.6.6.pre' - end -end diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb index 532d060c06..7eaf7d0534 100644 --- a/actionpack/lib/action_pack/version.rb +++ b/actionpack/lib/action_pack/version.rb @@ -3,7 +3,7 @@ module ActionPack MAJOR = 3 MINOR = 0 TINY = 0 - BUILD = "beta4" + BUILD = "rc" STRING = [MAJOR, MINOR, TINY, BUILD].join('.') 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/atom_feed_helper.rb b/actionpack/lib/action_view/helpers/atom_feed_helper.rb index cb5a1404ff..8e7cf2e701 100644 --- a/actionpack/lib/action_view/helpers/atom_feed_helper.rb +++ b/actionpack/lib/action_view/helpers/atom_feed_helper.rb @@ -10,7 +10,7 @@ module ActionView # Full usage example: # # config/routes.rb: - # Basecamp::Application.routes.draw do |map| + # Basecamp::Application.routes.draw do # resources :posts # root :to => "posts#index" # end diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index f9105ca364..89e95e8694 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -165,7 +165,7 @@ module ActionView def with_output_buffer(buf = nil) #:nodoc: unless buf buf = ActionView::OutputBuffer.new - buf.force_encoding(output_buffer.encoding) if output_buffer && buf.respond_to?(:force_encoding) + buf.force_encoding(output_buffer.encoding) if output_buffer.respond_to?(:encoding) && buf.respond_to?(:force_encoding) end self.output_buffer, old_buffer = buf, output_buffer yield 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 6302491c2a..ebe055bebd 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -150,10 +150,6 @@ module ActionView # here a named route directly as well. Defaults to the current action. # * <tt>:html</tt> - Optional HTML attributes for the form tag. # - # Worth noting is that the +form_for+ tag is called in a ERb evaluation - # block, not an ERb output block. So that's <tt><% %></tt>, not - # <tt><%= %></tt>. - # # Also note that +form_for+ doesn't create an exclusive scope. It's still # possible to use both the stand-alone FormHelper methods and methods # from FormTagHelper. For example: @@ -219,7 +215,7 @@ module ActionView # ... # <% end %> # - # If your resource has associations defined, for example, you want to add comments + # If your resource has associations defined, for example, you want to add comments # to the post given that the routes are set correctly: # # <%= form_for([@document, @comment]) do |f| %> @@ -302,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 @@ -533,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 @@ -587,8 +583,9 @@ module ActionView # 'Accept <a href="/terms">Terms</a>.' # end def label(object_name, method, content_or_options = nil, options = nil, &block) - if block_given? - options = content_or_options if content_or_options.is_a?(Hash) + content_is_options = content_or_options.is_a?(Hash) + if content_is_options || block_given? + options = content_or_options if content_is_options text = nil else text = content_or_options @@ -676,7 +673,7 @@ module ActionView # # => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" /> # def file_field(object_name, method, options = {}) - InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("file", options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("file", options.update({:size => nil})) end # Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by +method+) @@ -1009,9 +1006,9 @@ module ActionView def value_before_type_cast(object, method_name) unless object.nil? - object.respond_to?(method_name + "_before_type_cast") ? - object.send(method_name + "_before_type_cast") : - object.send(method_name) + object.respond_to?(method_name) ? + object.send(method_name) : + object.send(method_name + "_before_type_cast") end end @@ -1156,11 +1153,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/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 4c1b751160..1ea870426a 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -1,6 +1,5 @@ require 'cgi' require 'action_view/helpers/tag_helper' -require 'active_support/core_ext/object/returning' require 'active_support/core_ext/object/blank' module ActionView @@ -527,7 +526,7 @@ module ActionView private def html_options_for_form(url_for_options, options, *parameters_for_url) - returning options.stringify_keys do |html_options| + options.stringify_keys.tap do |html_options| html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart") # The following URL is unescaped, this is just a hash of options, and it is the # responsability of the caller to escape all the values. @@ -539,7 +538,7 @@ module ActionView def extra_tags_for_form(html_options) snowman_tag = tag(:input, :type => "hidden", - :name => "_snowman", :value => "☃".html_safe) + :name => "_e", :value => "☃".html_safe) method = html_options.delete("method").to_s diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 37e5d91d8b..f11027bc93 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -186,14 +186,7 @@ module ActionView # number_with_delimiter(12345678.05, :locale => :fr) # => 12 345 678,05 # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",") # # => 98 765 432,98 - # - # You can still use <tt>number_with_delimiter</tt> with the old API that accepts the - # +delimiter+ as its optional second and the +separator+ as its - # optional third parameter: - # number_with_delimiter(12345678, " ") # => 12 345 678 - # number_with_delimiter(12345678.05, ".", ",") # => 12.345.678,05 - def number_with_delimiter(number, *args) - options = args.extract_options! + def number_with_delimiter(number, options = {}) options.symbolize_keys! begin @@ -207,14 +200,6 @@ module ActionView end defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {}) - - unless args.empty? - ActiveSupport::Deprecation.warn('number_with_delimiter takes an option hash ' + - 'instead of separate delimiter and precision arguments.', caller) - options[:delimiter] ||= args[0] if args[0] - options[:separator] ||= args[1] if args[1] - end - options = options.reverse_merge(defaults) parts = number.to_s.split('.') @@ -249,13 +234,7 @@ module ActionView # number_with_precision(389.32314, :precision => 4, :significant => true) # => 389.3 # number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.') # # => 1.111,23 - # - # You can still use <tt>number_with_precision</tt> with the old API that accepts the - # +precision+ as its optional second parameter: - # number_with_precision(111.2345, 2) # => 111.23 - def number_with_precision(number, *args) - - options = args.extract_options! + def number_with_precision(number, options = {}) options.symbolize_keys! number = begin @@ -272,13 +251,6 @@ module ActionView precision_defaults = I18n.translate(:'number.precision.format', :locale => options[:locale], :default => {}) defaults = defaults.merge(precision_defaults) - #Backwards compatibility - unless args.empty? - ActiveSupport::Deprecation.warn('number_with_precision takes an option hash ' + - 'instead of a separate precision argument.', caller) - options[:precision] ||= args[0] if args[0] - end - options = options.reverse_merge(defaults) # Allow the user to unset default values: Eg.: :significant => false precision = options.delete :precision significant = options.delete :significant @@ -337,13 +309,7 @@ module ActionView # <tt>:strip_insignificant_zeros</tt> to +false+ to change that): # number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB" # number_to_human_size(524288000, :precision=>5) # => "500 MB" - # - # You can still use <tt>number_to_human_size</tt> with the old API that accepts the - # +precision+ as its optional second parameter: - # number_to_human_size(1234567, 1) # => 1 MB - # number_to_human_size(483989, 2) # => 470 KB - def number_to_human_size(number, *args) - options = args.extract_options! + def number_to_human_size(number, options = {}) options.symbolize_keys! number = begin @@ -359,13 +325,7 @@ module ActionView defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {}) human = I18n.translate(:'number.human.format', :locale => options[:locale], :default => {}) defaults = defaults.merge(human) - - unless args.empty? - ActiveSupport::Deprecation.warn('number_to_human_size takes an option hash ' + - 'instead of a separate precision argument.', caller) - options[:precision] ||= args[0] if args[0] - end - + options = options.reverse_merge(defaults) #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros) diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 5c0ff5d59c..99f9363a9a 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -102,7 +102,7 @@ module ActionView :form, :with, :update, :script, :type ]).merge(CALLBACKS) # Returns the JavaScript needed for a remote function. - # Takes the same arguments as link_to_remote. + # See the link_to_remote documentation at http://github.com/rails/prototype_legacy_helper as it takes the same arguments. # # Example: # # Generates: <select id="options" onchange="new Ajax.Updater('options', @@ -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/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb index b47818a22a..d82005fa24 100644 --- a/actionpack/lib/action_view/helpers/sanitize_helper.rb +++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/object/try' require 'action_controller/vendor/html-scanner' require 'action_view/helpers/tag_helper' @@ -7,6 +8,7 @@ module ActionView # The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements. # These helper methods extend Action View making them callable within your template files. module SanitizeHelper + extend ActiveSupport::Concern # This +sanitize+ helper will html encode all tags and strip all attributes that # aren't specifically allowed. # @@ -32,13 +34,13 @@ module ActionView # # Add table tags to the default allowed tags # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td' # end # # Remove tags to the default allowed tags # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.after_initialize do # ActionView::Base.sanitized_allowed_tags.delete 'div' # end @@ -46,7 +48,7 @@ module ActionView # # Change allowed default attributes # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_allowed_attributes = 'id', 'class', 'style' # end # @@ -143,7 +145,7 @@ module ActionView # Gets the HTML::FullSanitizer instance used by +strip_tags+. Replace with # any object that responds to +sanitize+. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.full_sanitizer = MySpecialSanitizer.new # end # @@ -154,7 +156,7 @@ module ActionView # Gets the HTML::LinkSanitizer instance used by +strip_links+. Replace with # any object that responds to +sanitize+. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.link_sanitizer = MySpecialSanitizer.new # end # @@ -165,7 +167,7 @@ module ActionView # Gets the HTML::WhiteListSanitizer instance used by sanitize and +sanitize_css+. # Replace with any object that responds to +sanitize+. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.white_list_sanitizer = MySpecialSanitizer.new # end # @@ -175,7 +177,7 @@ module ActionView # Adds valid HTML attributes that the +sanitize+ helper checks for URIs. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_uri_attributes = 'lowsrc', 'target' # end # @@ -185,7 +187,7 @@ module ActionView # Adds to the Set of 'bad' tags for the +sanitize+ helper. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_bad_tags = 'embed', 'object' # end # @@ -195,7 +197,7 @@ module ActionView # Adds to the Set of allowed tags for the +sanitize+ helper. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td' # end # @@ -205,7 +207,7 @@ module ActionView # Adds to the Set of allowed HTML attributes for the +sanitize+ helper. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_allowed_attributes = 'onclick', 'longdesc' # end # @@ -215,7 +217,7 @@ module ActionView # Adds to the Set of allowed CSS properties for the #sanitize and +sanitize_css+ helpers. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_allowed_css_properties = 'expression' # end # @@ -225,7 +227,7 @@ module ActionView # Adds to the Set of allowed CSS keywords for the +sanitize+ and +sanitize_css+ helpers. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_allowed_css_keywords = 'expression' # end # @@ -235,7 +237,7 @@ module ActionView # Adds to the Set of allowed shorthand CSS properties for the +sanitize+ and +sanitize_css+ helpers. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_shorthand_css_properties = 'expression' # end # @@ -245,7 +247,7 @@ module ActionView # Adds to the Set of allowed protocols for the +sanitize+ helper. # - # Rails::Initializer.run do |config| + # class Application < Rails::Application # config.action_view.sanitized_allowed_protocols = 'ssh', 'feed' # end # diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 0be8a2c36e..c1de5c8cb3 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -10,6 +10,9 @@ module ActionView # your views. These helper methods extend Action View making them callable # within your template files. module TextHelper + extend ActiveSupport::Concern + + include SanitizeHelper # The preferred method of outputting text in your views is to use the # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods # do not operate as expected in an eRuby code block. If you absolutely must @@ -61,27 +64,8 @@ module ActionView # # truncate("<p>Once upon a time in a world far far away</p>") # # => "<p>Once upon a time in a wo..." - # - # You can still use <tt>truncate</tt> with the old API that accepts the - # +length+ as its optional second and the +ellipsis+ as its - # optional third parameter: - # truncate("Once upon a time in a world far far away", 14) - # # => "Once upon a..." - # - # truncate("And they found that many people were sleeping better.", 25, "... (continued)") - # # => "And they f... (continued)" - def truncate(text, *args) - options = args.extract_options! - unless args.empty? - ActiveSupport::Deprecation.warn('truncate takes an option hash instead of separate ' + - 'length and omission arguments', caller) - - options[:length] = args[0] || 30 - options[:omission] = args[1] || "..." - end - + def truncate(text, options = {}) options.reverse_merge!(:length => 30) - text.truncate(options.delete(:length), options) if text end diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 0e3cc54fd1..a5c6718c58 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -95,7 +95,7 @@ module ActionView when String options when Hash - options = { :only_path => options[:host].nil? }.update(options.symbolize_keys) + options = options.symbolize_keys.reverse_merge!(:only_path => options[:host].nil?) super when :back controller.request.env["HTTP_REFERER"] || 'javascript:history.back()' @@ -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/abstract/abstract_controller_test.rb b/actionpack/test/abstract/abstract_controller_test.rb index 3b5013a47a..19855490b4 100644 --- a/actionpack/test/abstract/abstract_controller_test.rb +++ b/actionpack/test/abstract/abstract_controller_test.rb @@ -250,5 +250,19 @@ module AbstractController end end + class Me6 < AbstractController::Base + self.action_methods + + def index + end + end + + class TestActionMethodsReloading < ActiveSupport::TestCase + + test "action_methods should be reloaded after defining a new method" do + assert_equal ["index"], Me6.action_methods + end + end + end end 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/resources_test.rb b/actionpack/test/controller/resources_test.rb index a9d1c55c05..6c8f470fba 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/object/try' require 'abstract_unit' class ResourcesController < ActionController::Base diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index f9fc7a0976..13c9d9ee38 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'controller/fake_controllers' +require 'active_support/ordered_hash' class TestTest < ActionController::TestCase class TestController < ActionController::Base @@ -137,14 +138,14 @@ XML end def test_raw_post_handling - params = {:page => {:name => 'page name'}, 'some key' => 123} + params = ActiveSupport::OrderedHash[:page, {:name => 'page name'}, 'some key', 123] post :render_raw_post, params.dup assert_equal params.to_query, @response.body end def test_body_stream - params = { :page => { :name => 'page name' }, 'some key' => 123 } + params = ActiveSupport::OrderedHash[:page, { :name => 'page name' }, 'some key', 123] post :render_body, params.dup @@ -461,6 +462,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/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 2a014bf976..3f090b7254 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -1,3 +1,4 @@ +require 'erb' require 'abstract_unit' require 'controller/fake_controllers' @@ -56,7 +57,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest match 'account/proc/:name', :to => redirect {|params| "/#{params[:name].pluralize}" } match 'account/proc_req' => redirect {|params, req| "/#{req.method}" } - match 'account/google' => redirect('http://www.google.com/') + match 'account/google' => redirect('http://www.google.com/', :status => 302) match 'openid/login', :via => [:get, :post], :to => "openid#login" @@ -245,7 +246,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest namespace :account do match 'shorthand' - match 'description', :to => "description", :as => "description" + match 'description', :to => :description, :as => "description" + match ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback resource :subscription, :credit, :credit_card root :to => "account#index" @@ -500,9 +502,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_login_redirect with_test_routes do get '/account/login' - assert_equal 301, @response.status - assert_equal 'http://www.example.com/login', @response.headers['Location'] - assert_equal 'Moved Permanently', @response.body + verify_redirect 'http://www.example.com/login' end end @@ -510,18 +510,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest with_test_routes do assert_equal '/account/logout', logout_redirect_path get '/account/logout' - assert_equal 301, @response.status - assert_equal 'http://www.example.com/logout', @response.headers['Location'] - assert_equal 'Moved Permanently', @response.body + verify_redirect 'http://www.example.com/logout' end end def test_namespace_redirect with_test_routes do get '/private' - assert_equal 301, @response.status - assert_equal 'http://www.example.com/private/index', @response.headers['Location'] - assert_equal 'Moved Permanently', @response.body + verify_redirect 'http://www.example.com/private/index' end end @@ -585,27 +581,21 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_redirect_modulo with_test_routes do get '/account/modulo/name' - assert_equal 301, @response.status - assert_equal 'http://www.example.com/names', @response.headers['Location'] - assert_equal 'Moved Permanently', @response.body + verify_redirect 'http://www.example.com/names' end end def test_redirect_proc with_test_routes do get '/account/proc/person' - assert_equal 301, @response.status - assert_equal 'http://www.example.com/people', @response.headers['Location'] - assert_equal 'Moved Permanently', @response.body + verify_redirect 'http://www.example.com/people' end end def test_redirect_proc_with_request with_test_routes do get '/account/proc_req' - assert_equal 301, @response.status - assert_equal 'http://www.example.com/GET', @response.headers['Location'] - assert_equal 'Moved Permanently', @response.body + verify_redirect 'http://www.example.com/GET' end end @@ -1159,7 +1149,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - def test_convention_match_with_no_scope + def test_match_shorthand_with_no_scope with_test_routes do assert_equal '/account/overview', account_overview_path get '/account/overview' @@ -1167,7 +1157,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - def test_convention_match_inside_namespace + def test_match_shorthand_inside_namespace with_test_routes do assert_equal '/account/shorthand', account_shorthand_path get '/account/shorthand' @@ -1175,6 +1165,17 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_scoped_controller_with_namespace_and_action + with_test_routes do + assert_equal '/account/twitter/callback', account_callback_path("twitter") + get '/account/twitter/callback' + assert_equal 'account/callbacks#twitter', @response.body + + get '/account/whatever/callback' + assert_equal 'Not Found', @response.body + end + end + def test_convention_match_nested_and_with_leading_slash with_test_routes do assert_equal '/account/nested/overview', account_nested_overview_path @@ -1191,12 +1192,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - def test_redirect_with_complete_url + def test_redirect_with_complete_url_and_status with_test_routes do get '/account/google' - assert_equal 301, @response.status - assert_equal 'http://www.google.com/', @response.headers['Location'] - assert_equal 'Moved Permanently', @response.body + verify_redirect 'http://www.google.com/', 302 end end @@ -1204,9 +1203,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest previous_host, self.host = self.host, 'www.example.com:3000' with_test_routes do get '/account/login' - assert_equal 301, @response.status - assert_equal 'http://www.example.com:3000/login', @response.headers['Location'] - assert_equal 'Moved Permanently', @response.body + verify_redirect 'http://www.example.com:3000/login' end ensure self.host = previous_host @@ -1887,8 +1884,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - private - def with_test_routes - yield - end +private + def with_test_routes + yield + end + + def verify_redirect(url, status=301) + assert_equal status, @response.status + assert_equal url, @response.headers['Location'] + assert_equal expected_redirect_body(url), @response.body + end + + def expected_redirect_body(url) + %(<html><body>You are being <a href="#{ERB::Util.h(url)}">redirected</a>.</body></html>) + 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/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb index 9f3d68a639..f7c42c7f22 100644 --- a/actionpack/test/template/capture_helper_test.rb +++ b/actionpack/test/template/capture_helper_test.rb @@ -114,7 +114,7 @@ class CaptureHelperTest < ActionView::TestCase end def view_with_controller - returning(TestController.new.view_context) do |view| + TestController.new.view_context.tap do |view| view.output_buffer = ActionView::OutputBuffer.new end end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 4b9e41803f..be66710ae5 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -4,6 +4,16 @@ require 'controller/fake_models' class FormHelperTest < ActionView::TestCase tests ActionView::Helpers::FormHelper + class Developer + def name_before_type_cast + "David" + end + + def name + "Santiago" + end + end + def form_for(*) @output_buffer = super end @@ -110,6 +120,13 @@ class FormHelperTest < ActionView::TestCase I18n.locale = old_locale end + def test_label_with_locales_and_options + old_locale, I18n.locale = I18n.locale, :label + assert_dom_equal('<label for="post_body" class="post_body">Write entire text here</label>', label(:post, :body, :class => 'post_body')) + ensure + I18n.locale = old_locale + end + def test_label_with_for_attribute_as_symbol assert_dom_equal('<label for="my_for">Title</label>', label(:post, :title, nil, :for => "my_for")) end @@ -200,6 +217,11 @@ class FormHelperTest < ActionView::TestCase assert_equal object_name, "post[]" end + def test_file_field_has_no_size + expected = '<input id="user_avatar" name="user[avatar]" type="file" />' + assert_dom_equal expected, file_field("user", "avatar") + end + def test_hidden_field assert_dom_equal '<input id="post_title" name="post[title]" type="hidden" value="Hello World" />', hidden_field("post", "title") @@ -228,6 +250,13 @@ class FormHelperTest < ActionView::TestCase text_field("user", "email", :type => "email") end + def test_text_field_from_a_user_defined_method + @developer = Developer.new + assert_dom_equal( + '<input id="developer_name" name="developer[name]" size="30" type="text" value="Santiago" />', text_field("developer", "name") + ) + end + def test_check_box assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', @@ -598,7 +627,7 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_symbol_object_name form_for(@post, :as => "other_name", :html => { :id => 'create-post' }) do |f| - concat f.label(:title) + concat f.label(:title, :class => 'post_title') concat f.text_field(:title) concat f.text_area(:body) concat f.check_box(:secret) @@ -606,7 +635,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts/123", "create-post", "other_name_edit", :method => "put") do - "<label for='other_name_title'>Title</label>" + + "<label for='other_name_title' class='post_title'>Title</label>" + "<input name='other_name[title]' size='30' id='other_name_title' value='Hello World' type='text' />" + "<textarea name='other_name[body]' id='other_name_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + "<input name='other_name[secret]' value='0' type='hidden' />" + @@ -1484,7 +1513,7 @@ class FormHelperTest < ActionView::TestCase def snowman(method = nil) txt = %{<div style="margin:0;padding:0;display:inline">} - txt << %{<input name="_snowman" type="hidden" value="☃" />} + txt << %{<input name="_e" type="hidden" value="☃" />} txt << %{<input name="_method" type="hidden" value="#{method}" />} if method txt << %{</div>} end 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/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 8a0f352bc0..6c85952d40 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -12,7 +12,7 @@ class FormTagHelperTest < ActionView::TestCase method = options[:method] txt = %{<div style="margin:0;padding:0;display:inline">} - txt << %{<input name="_snowman" type="hidden" value="☃" />} + txt << %{<input name="_e" type="hidden" value="☃" />} txt << %{<input name="_method" type="hidden" value="#{method}" />} if method txt << %{</div>} end diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index c5c2a6b952..a8ca19931b 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -89,6 +89,15 @@ class JavaScriptHelperTest < ActionView::TestCase link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/') end + def test_link_to_function_with_inner_block_does_not_raise_exception + html = link_to_function( "Greet me!" ) do |page| + page.replace_html 'header', (content_tag :h1 do + 'Greetings' + end) + end + assert_dom_equal %(<a href="#" onclick="Element.update("header", "\\u003Ch1\\u003EGreetings\\u003C/h1\\u003E");; return false;">Greet me!</a>), html + end + def test_javascript_tag self.output_buffer = 'foo' diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 14e81fc9dc..7f787b7b00 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -82,16 +82,6 @@ class NumberHelperTest < ActionView::TestCase assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :delimiter => '.', :separator => ',') end - def test_number_with_delimiter_old_api - silence_deprecation_warnings - assert_equal '12 345 678', number_with_delimiter(12345678, " ") - assert_equal '12-345-678.05', number_with_delimiter(12345678.05, '-') - assert_equal '12.345.678,05', number_with_delimiter(12345678.05, '.', ',') - assert_equal '12,345,678.05', number_with_delimiter(12345678.05, ',', '.') - assert_equal '12 345 678-05', number_with_delimiter(12345678.05, ',', '.', :delimiter => ' ', :separator => '-') - restore_deprecation_warnings - end - def test_number_with_precision assert_equal("111.235", number_with_precision(111.2346)) assert_equal("31.83", number_with_precision(31.825, :precision => 2)) @@ -146,15 +136,6 @@ class NumberHelperTest < ActionView::TestCase assert_equal "12", number_with_precision("12.3", :precision => 0, :significant => true ) end - def test_number_with_precision_old_api - silence_deprecation_warnings - assert_equal("31.8250", number_with_precision(31.825, 4)) - assert_equal("111.235", number_with_precision(111.2346, 3)) - assert_equal("111.00", number_with_precision(111, 2)) - assert_equal("111.000", number_with_precision(111, 2, :precision =>3)) - restore_deprecation_warnings - end - def test_number_to_human_size assert_equal '0 Bytes', number_to_human_size(0) assert_equal '1 Byte', number_to_human_size(1) @@ -202,14 +183,6 @@ class NumberHelperTest < ActionView::TestCase assert_equal '1.000,1 TB', number_to_human_size(terabytes(1000.1), :precision => 5, :delimiter => '.', :separator => ',') end - def test_number_to_human_size_old_api - silence_deprecation_warnings - assert_equal '1.3143 KB', number_to_human_size(kilobytes(1.3143), 4, :significant => false) - assert_equal '10.45 KB', number_to_human_size(kilobytes(10.453), 4) - assert_equal '10 KB', number_to_human_size(kilobytes(10.453), 4, :precision => 2) - restore_deprecation_warnings - end - def test_number_to_human assert_equal '123', number_to_human(123) assert_equal '1.23 Thousand', number_to_human(1234) 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}" diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 048f96c9a9..d59bbec4a9 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -1,6 +1,6 @@ # encoding: utf-8 require 'abstract_unit' -require 'active_support/ordered_options' +require 'active_support/ordered_hash' require 'controller/fake_controllers' class UrlHelperTest < ActiveSupport::TestCase @@ -31,17 +31,13 @@ class UrlHelperTest < ActiveSupport::TestCase {} end - def abcd(hash = {}) - hash_for(:a => :b, :c => :d).merge(hash) - end - - def hash_for(opts = {}) - {:controller => "foo", :action => "bar"}.merge(opts) + def hash_for(opts = []) + ActiveSupport::OrderedHash[*([:controller, "foo", :action, "bar"].concat(opts))] end alias url_hash hash_for def test_url_for_does_not_escape_urls - assert_equal "/?a=b&c=d", url_for(abcd) + assert_equal "/?a=b&c=d", url_for(hash_for([:a, :b, :c, :d])) end def test_url_for_with_back @@ -128,7 +124,7 @@ class UrlHelperTest < ActiveSupport::TestCase end def test_link_tag_with_host_option - hash = hash_for(:host => "www.example.com") + hash = hash_for([:host, "www.example.com"]) expected = %q{<a href="http://www.example.com/">Test Link</a>} assert_dom_equal(expected, link_to('Test Link', hash)) end @@ -294,7 +290,7 @@ class UrlHelperTest < ActiveSupport::TestCase def test_current_page_with_params_that_match @request = request_for_url("/?order=desc&page=1") - assert current_page?(hash_for(:order => "desc", :page => "1")) + assert current_page?(hash_for([:order, "desc", :page, "1"])) assert current_page?("http://www.example.com/?order=desc&page=1") end @@ -316,20 +312,20 @@ class UrlHelperTest < ActiveSupport::TestCase @request = request_for_url("/?order=desc&page=1") assert_equal "Showing", - link_to_unless_current("Showing", hash_for(:order=>'desc', :page=>'1')) + link_to_unless_current("Showing", hash_for([:order, 'desc', :page, '1'])) assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/?order=desc&page=1") @request = request_for_url("/?order=desc") assert_equal %{<a href="/?order=asc">Showing</a>}, - link_to_unless_current("Showing", hash_for(:order => :asc)) + link_to_unless_current("Showing", hash_for([:order, :asc])) assert_equal %{<a href="http://www.example.com/?order=asc">Showing</a>}, link_to_unless_current("Showing", "http://www.example.com/?order=asc") @request = request_for_url("/?order=desc") assert_equal %{<a href="/?order=desc&page=2\">Showing</a>}, - link_to_unless_current("Showing", hash_for(:order => "desc", :page => 2)) + link_to_unless_current("Showing", hash_for([:order, "desc", :page, 2])) assert_equal %{<a href="http://www.example.com/?order=desc&page=2">Showing</a>}, link_to_unless_current("Showing", "http://www.example.com/?order=desc&page=2") |