aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md1160
-rw-r--r--actionpack/lib/abstract_controller/layouts.rb1
-rw-r--r--actionpack/lib/action_controller/metal.rb5
-rw-r--r--actionpack/lib/action_controller/metal/force_ssl.rb69
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb2
-rw-r--r--actionpack/lib/action_controller/test_case.rb23
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb3
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb70
-rw-r--r--actionpack/lib/action_dispatch/journey/parser.y1
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb4
-rw-r--r--actionpack/lib/action_dispatch/journey/router.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb8
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb7
-rw-r--r--actionpack/lib/action_pack/version.rb2
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb2
-rw-r--r--actionpack/lib/action_view/path_set.rb6
-rw-r--r--actionpack/lib/action_view/renderer/abstract_renderer.rb15
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb14
-rw-r--r--actionpack/lib/action_view/renderer/renderer.rb6
-rw-r--r--actionpack/test/abstract/layouts_test.rb6
-rw-r--r--actionpack/test/controller/force_ssl_test.rb175
-rw-r--r--actionpack/test/controller/url_for_test.rb7
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb6
-rw-r--r--actionpack/test/dispatch/routing_test.rb51
-rw-r--r--actionpack/test/dispatch/show_exceptions_test.rb12
-rw-r--r--actionpack/test/dispatch/url_generation_test.rb41
-rw-r--r--actionpack/test/fixtures/public/400.html1
-rw-r--r--actionpack/test/template/form_options_helper_test.rb7
-rw-r--r--actionpack/test/template/render_test.rb8
31 files changed, 481 insertions, 1239 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 88cdd53336..ffafa7412d 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,1159 +1,3 @@
-## Rails 4.0.0 (unreleased) ##
+* No changes.
-* Fix explicit names on multiple file fields. If a file field tag has
- the multiple option, it is turned into an array field (appending `[]`),
- but if an explicit name is passed to `file_field` the `[]` is not
- appended.
- Fixes #9830.
-
- *Ryan McGeary*
-
-* Add block support for the `mail_to` helper, similar to the `link_to` helper.
-
- *Sam Pohlenz*
-
-* Automatically configure cookie-based sessions to be encrypted if
- `secret_key_base` is set, falling back to signed if only `secret_token`
- is set. Automatically upgrade existing signed cookie-based sessions from
- Rails 3.x to be encrypted if both `secret_key_base` and `secret_token`
- are set, or signed with the new key generator if only `secret_token` is
- set. This leaves only the `config.session_store :cookie_store` option and
- removes the two new options introduced in 4.0.0.beta1:
- `encrypted_cookie_store` and `upgrade_signature_to_encryption_cookie_store`.
-
- *Trevor Turk*
-
-* Ensure consistent fallback to the default layout lookup for layouts set
- using symbols or procs that return `nil`.
-
- All of the following layouts will result in the default layout lookup:
-
- layout nil
-
- layout proc { nil }
-
- layout :returns_nil
- def returns_nil
- nil
- end
-
- Previously symbols and procs which returned `nil` resulted in no layout which
- differed from the `layout nil` behavior. To get the "no layout" behavior just
- return `false` instead of `nil` for `layout`.
-
- *Chris Nicola*
-
-* Create `UpgradeLegacySignedCookieJar` to transparently upgrade existing signed
- cookies generated by Rails 3.x to avoid invalidating them when upgrading to Rails 4.x.
-
- *Trevor Turk + Neeraj Singh*
-
-* Raise an `ArgumentError` when a clashing named route is defined.
-
- *Trevor Turk*
-
-* Allow default url options to accept host with protocol such as `http://`
-
- config.action_mailer.default_url_options = { host: "http://mydomain.com" }
-
- *Richard Schneeman*
-
-* Ensure that digest authentication responds with a 401 status when a basic
- header is received.
-
- *Brad Dunbar*
-
-* Include I18n locale fallbacks in view lookup.
- Fixes #3512.
-
- *Juan Barreneche*
-
-* Integration and functional tests allow headers and rack env
- variables to be passed when performing requests.
- Fixes #6513.
-
- Example:
-
- # integration test
- get "/success", {}, "HTTP_REFERER" => "http://test.com/",
- "Accepts" => "text/plain, text/html"
-
- # functional test
- @request.headers["Accepts"] = "text/plain, text/html"
-
- *Yves Senn*
-
-* Http::Headers respects headers that are not prefixed with HTTP_
-
- *Yves Senn*
-
-* Fix incorrectly appended square brackets to a multiple select box
- if an explicit name has been given and it already ends with "[]"
-
- Before:
-
- select(:category, [], {}, multiple: true, name: "post[category][]")
- # => <select name="post[category][][]" ...>
-
- After:
-
- select(:category, [], {}, multiple: true, name: "post[category][]")
- # => <select name="post[category][]" ...>
-
- *Olek Janiszewski*
-
-* Fixed regression when using `assert_template` to verify files sent using
- `render file: 'README.md'`.
- Fixes #9464.
-
- *Justin Coyne*
-
-* Fixed `ActionView::Helpers::CaptureHelper#content_for` regression when trying to use it in
- a boolean statement.
- Fixes #9360.
-
- *Nikolay Shebanov*
-
-* `format: true` does not override existing format constraints.
- Fixes #9466.
-
- Example:
-
- # This will force the .json extension.
- get '/json_only', to: ok, format: true, constraints: { format: /json/ }
-
- *Yves Senn*
-
-* Skip valid encoding checks for non-String parameters that come
- from the matched route's defaults.
- Fixes #9435.
-
- Example:
-
- root to: 'main#posts', page: 1
-
- *Yves Senn*
-
-* Don't verify Regexp requirements for non-Regexp `:constraints`.
- Fixes #9432.
-
- Example:
-
- get '/photos.:format' => 'feeds#photos', constraints: {format: 'xml'}
-
- *Yves Senn*
-
-* Make `ActionDispatch::Journey::Path::Pattern#new` raise more meaningful exception message.
-
- *Thierry Zires*
-
-
-## Rails 4.0.0.beta1 (February 25, 2013) ##
-
-* Fix `respond_to` not using formats that have no block if all is present. *Michael Grosser*
-
-* New applications use an encrypted session store by default.
-
- *Santiago Pastorino*
-
-* Determine the controller#action from only the matched path when using the
- shorthand syntax. Previously the complete path was used, which led
- to problems with nesting (scopes and namespaces).
- Fixes #7554.
-
- Example:
-
- # This will route to questions#new.
- scope ':locale' do
- get 'questions/new'
- end
-
- *Yves Senn*
-
-* Remove support for parsing XML parameters from request. If you still want to parse XML
- parameters, please install `actionpack-xml_parser' gem.
-
- *Prem Sichanugrist*
-
-* Remove support for parsing YAML parameters from request.
-
- *Aaron Patterson*
-
-* Add a message when you have no routes defined to both `rake routes` and
- GET "/rails/info/routes" that lets you know you have none defined and links
- to the Rails guide on the topic.
-
- *Steve Klabnik*
-
-* Change `image_alt` method to replace underscores/hyphens to spaces in filenames.
-
- Previously, underscored filenames became `alt="A_long_file_name_with_underscores"`
- in HTML, which is poor for accessibility. For instance, Apple's VoiceOver Utility
- pronounces each underscore. `A_long_file_name` thus would be read as `A underscore
- long underscore file underscore name.` Now underscored or hyphenated filenames
- (both of which are very popular naming conventions) read more naturally in
- screen readers by converting both hyphens and underscores to spaces.
-
- Before:
-
- image_tag('underscored_file_name.png')
- # => <img alt="Underscored_file_name" src="/assets/underscored_file_name.png" />
-
- After:
-
- image_tag('underscored_file_name.png')
- # => <img alt="Underscored file name" src="/assets/underscored_file_name.png" />
-
- *Nick Cox*
-
-* We don't support Ruby constant notation in the `:controller` option for route
- definitions. So, this raises an `ArgumentError` now:
-
- resources :posts, controller: "Admin::Posts" # WRONG
-
- Use path notation instead:
-
- resources :posts, controller: "admin/posts" # RIGHT
-
- *Yves Senn*
-
-* `assert_template` can be used to verify the locals of partials,
- which live inside a directory.
-
- # Prefixed partials inside directories worked and still work.
- assert_template partial: 'directory/_partial', locals: {name: 'John'}
-
- # This did not work but does now.
- assert_template partial: 'directory/partial', locals: {name: 'John'}
-
- Fixes #8516.
-
- *Yves Senn*
-
-* Fix `content_tag_for` with array HTML option.
- It would embed array as string instead of joining it like `content_tag` does:
-
- content_tag(:td, class: ["foo", "bar"]){}
- # => <td class="foo bar"></td>
-
- Before:
-
- content_tag_for(:td, item, class: ["foo", "bar"])
- # => <td class="item [&quot;foo&quot;, &quot;bar&quot;]" id="item_1"></td>
-
- After:
-
- content_tag_for(:td, item, class: ["foo", "bar"])
- # => <td class="item foo bar" id="item_1"></td>
-
- *Semyon Perepelitsa*
-
-* Remove `BestStandardsSupport` middleware, !DOCTYPE html already triggers
- standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx
- and ChromeFrame header has been moved to `config.action_dispatch.default_headers`
-
- *Guillermo Iguaran*
-
-* Fix CSRF protection and `current_url?` helper to work with HEAD requests
- now that `ActionDispatch::Head` has been removed in favor of `Rack::Head`.
-
- *Michiel Sikkes*
-
-* Change `asset_path` to not include `SCRIPT_NAME` when it's used
- from a mounted engine. Fixes #8119.
-
- *Piotr Sarnacki*
-
-* Add JavaScript based routing path matcher to `/rails/info/routes`.
- Routes can now be filtered by whether or not they match a path.
-
- *Richard Schneeman*
-
-* Change the behavior of route defaults so that explicit defaults are no longer
- required where the key is not part of the path. For example:
-
- resources :posts, bucket_type: 'posts'
-
- will be required whenever constructing the url from a hash such as a functional
- test or using `url_for` directly. However using the explicit form alters the
- behavior so it's not required:
-
- resources :projects, defaults: { bucket_type: 'projects' }
-
- This changes existing behavior slightly in that any routes which only differ
- in their defaults will match the first route rather than the closest match.
-
- *Andrew White*
-
-* Add support for routing constraints other than Regexp and String.
- For example this now allows the use of arrays like this:
-
- get '/foo/:action', to: 'foo', constraints: { subdomain: %w[www admin] }
-
- or constraints where the request method returns an Fixnum like this:
-
- get '/foo', to: 'foo#index', constraints: { port: 8080 }
-
- Note that this only applies to constraints on the request - path constraints
- still need to be specified as Regexps as the various constraints are compiled
- into a single Regexp.
-
- *Andrew White*
-
-* Fix a bug in integration tests where setting the port via a url passed to
- the process method was ignored when constructing the request environment.
-
- *Andrew White*
-
-* Allow `:selected` to be set on `date_select` tag helper.
-
- *Colin Burn-Murdoch*
-
-* Fixed JSON params parsing regression for non-object JSON content.
-
- *Dylan Smith*
-
-* Extract `ActionDispatch::PerformanceTest` into https://github.com/rails/rails-perftest
- You can add the gem to your Gemfile to keep using performance tests.
-
- gem 'rails-perftest'
-
- *Yves Senn*
-
-* Added view_cache_dependency API for declaring dependencies that affect
- cache digest computation.
-
- *Jamis Buck*
-
-* `image_submit_tag` will set `alt` attribute from image source if not
- specified.
-
- *Nihad Abbasov*
-
-* Do not generate local variables for partials without object or collection.
- Previously rendering a partial without giving `:object` or `:collection`
- would generate a local variable with the partial name by default.
-
- *Carlos Antonio da Silva*
-
-* Return the last valid, non-private IP address from the X-Forwarded-For,
- Client-IP and Remote-Addr headers, in that order. Document the rationale
- for that decision, and describe the options that can be passed to the
- RemoteIp middleware to change it.
- Fixes #7979.
-
- *André Arko*, *Steve Klabnik*, *Alexey Gaziev*
-
-* Do not append second slash to `root_url` when using `trailing_slash: true`
- Fixes #8700.
-
- Before:
-
- root_url(trailing_slash: true) # => http://test.host//
-
- After:
-
- root_url(trailing_slash: true) # => http://test.host/
-
- *Yves Senn*
-
-* Allow to toggle dumps on error pages.
-
- *Gosha Arinich*
-
-* Fix a bug in `content_tag_for` that prevents it from working without a block.
-
- *Jasl*
-
-* Change the stylesheet of exception pages for development mode.
- Additionally display also the line of code and fragment that raised
- the exception in all exceptions pages.
-
- *Guillermo Iguaran + Jorge Cuadrado*
-
-* Do not append `charset=` parameter when `head` is called with a
- `:content_type` option.
- Fixes #8661.
-
- *Yves Senn*
-
-* Added `Mime::NullType` class. This allows to use `html?`, `xml?`, `json?`, etc.
- when the format of the request is unknown, without raising an exception.
-
- *Angelo Capilleri*
-
-* Integrate the Journey gem into Action Dispatch so that the global namespace
- is not polluted with names that may be used as models.
-
- *Andrew White*
-
-* Extract support for email address obfuscation via `:encode`, `:replace_at`, and `replace_dot`
- options from the `mail_to` helper into the `actionview-encoded_mail_to` gem.
-
- *Nick Reed + DHH*
-
-* Handle `:protocol` option in `stylesheet_link_tag` and `javascript_include_tag`
-
- *Vasiliy Ermolovich*
-
-* Clear url helper methods when routes are reloaded. *Andrew White*
-
-* Fix a bug in `ActionDispatch::Request#raw_post` that caused `env['rack.input']`
- to be read but not rewound.
-
- *Matt Venables*
-
-* Prevent raising `EOFError` on multipart GET request (IE issue). *Adam Stankiewicz*
-
-* Rename all action callbacks from *_filter to *_action to avoid the misconception that these
- callbacks are only suited for transforming or halting the response. With the new style,
- it's more inviting to use them as they were intended, like setting shared ivars for views.
-
- Example:
-
- class PeopleController < ActionController::Base
- before_action :set_person, except: [:index, :new, :create]
- before_action :ensure_permission, only: [:edit, :update]
-
- ...
-
- private
- def set_person
- @person = current_account.people.find(params[:id])
- end
-
- def ensure_permission
- current_person.can_change?(@person)
- end
- end
-
- The old *_filter methods still work with no deprecation notice.
-
- *DHH*
-
-* Add `cache_if` and `cache_unless` for conditional fragment caching:
-
- Example:
-
- <%= cache_if condition, project do %>
- <b>All the topics on this project</b>
- <%= render project.topics %>
- <% end %>
-
- # and
-
- <%= cache_unless condition, project do %>
- <b>All the topics on this project</b>
- <%= render project.topics %>
- <% end %>
-
- *Stephen Ausman + Fabrizio Regini + Angelo Capilleri*
-
-* Add logging filter capability for redirect URLs:
-
- config.filter_redirect << 'http://please.hide.it/'
-
- *Fabrizio Regini*
-
-* Fixed a bug that ignores constraints on a glob route. This was caused because the constraint
- regular expression is overwritten when the `routes.rb` file is processed. Fixes #7924
-
- *Maura Fitzgerald*
-
-* More descriptive error messages when calling `render :partial` with
- an invalid `:layout` argument.
-
- Fixes #8376.
-
- render partial: 'partial', layout: true
-
- # results in ActionView::MissingTemplate: Missing partial /true
-
- *Yves Senn*
-
-* Sweepers was extracted from Action Controller as `rails-observers` gem.
-
- *Rafael Mendonça França*
-
-* Add option flag to `CacheHelper#cache` to manually bypass automatic template digests:
-
- <% cache project, skip_digest: true do %>
- ...
- <% end %>
-
- *Drew Ulmer*
-
-* Do not sort Hash options in `grouped_options_for_select`. *Sergey Kojin*
-
-* Accept symbols as `send_data :disposition` value *Elia Schito*
-
-* Add i18n scope to `distance_of_time_in_words`. *Steve Klabnik*
-
-* `assert_template`:
- - is no more passing with empty string.
- - is now validating option keys. It accepts: `:layout`, `:partial`, `:locals` and `:count`.
-
- *Roberto Soares*
-
-* Allow setting a symbol as path in scope on routes. This is now allowed:
-
- scope :api do
- resources :users
- end
-
- It is also possible to pass multiple symbols to scope to shorten multiple nested scopes:
-
- scope :api do
- scope :v1 do
- resources :users
- end
- end
-
- can be rewritten as:
-
- scope :api, :v1 do
- resources :users
- end
-
- *Guillermo Iguaran + Amparo Luna*
-
-* Fix error when using a non-hash query argument named "params" in `url_for`.
-
- Before:
-
- url_for(params: "") # => undefined method `reject!' for "":String
-
- After:
-
- url_for(params: "") # => http://www.example.com?params=
-
- *tumayun + Carlos Antonio da Silva*
-
-* Render every partial with a new `ActionView::PartialRenderer`. This resolves
- issues when rendering nested partials.
- Fixes #8197.
-
- *Yves Senn*
-
-* Introduce `ActionView::Template::Handlers::ERB.escape_whitelist`. This is a list
- of mime types where template text is not html escaped by default. It prevents `Jack & Joe`
- from rendering as `Jack &amp; Joe` for the whitelisted mime types. The default whitelist
- contains `text/plain`.
- Fixes #7976.
-
- *Joost Baaij*
-
-* Fix input name when `multiple: true` and `:index` are set.
-
- Before:
-
- check_box("post", "comment_ids", { multiple: true, index: "foo" }, 1)
- # => <input name=\"post[foo][comment_ids]\" type=\"hidden\" value=\"0\" /><input id=\"post_foo_comment_ids_1\" name=\"post[foo][comment_ids]\" type=\"checkbox\" value=\"1\" />
-
- After:
-
- check_box("post", "comment_ids", { multiple: true, index: "foo" }, 1)
- # => <input name=\"post[foo][comment_ids][]\" type=\"hidden\" value=\"0\" /><input id=\"post_foo_comment_ids_1\" name=\"post[foo][comment_ids][]\" type=\"checkbox\" value=\"1\" />
-
- Fixes #8108.
-
- *Daniel Fox, Grant Hutchins & Trace Wax*
-
-* `date_select` helper accepts `with_css_classes: true` to add css classes similar with type
- of generated select tags.
-
- *Pavel Nikitin*
-
-* Only non-js/css under `app/assets` path will be included in default `config.assets.precompile`.
-
- *Josh Peek*
-
-* Remove support for the `RAILS_ASSET_ID` environment configuration
- (no longer needed now that we have the asset pipeline).
-
- *Josh Peek*
-
-* Remove old `asset_path` configuration (no longer needed now that we have the asset pipeline).
-
- *Josh Peek*
-
-* `assert_template` can be used to assert on the same template with different locals
- Fixes #3675.
-
- *Yves Senn*
-
-* Remove old asset tag concatenation (no longer needed now that we have the asset pipeline).
-
- *Josh Peek*
-
-* Accept `:remote` as symbolic option for `link_to` helper. *Riley Lynch*
-
-* Warn when the `:locals` option is passed to `assert_template` outside of a view test case
- Fixes #3415.
-
- *Yves Senn*
-
-* The `Rack::Cache` middleware is now disabled by default. To enable it,
- set `config.action_dispatch.rack_cache = true` and add `gem rack-cache` to your Gemfile.
-
- *Guillermo Iguaran*
-
-* `ActionController::Base.page_cache_extension` option is deprecated
- in favour of `ActionController::Base.default_static_extension`.
-
- *Francesco Rodriguez*
-
-* Action and Page caching has been extracted from Action Dispatch
- as `actionpack-action_caching` and `actionpack-page_caching` gems.
- Please read the `README.md` file on both gems for the usage.
-
- *Francesco Rodriguez*
-
-* Failsafe exception returns `text/plain`. *Steve Klabnik*
-
-* Rename internal variables on `ActionController::TemplateAssertions` to prevent
- naming collisions. `@partials`, `@templates` and `@layouts` are now prefixed with an underscore.
- Fixes #7459.
-
- *Yves Senn*
-
-* `resource` and `resources` don't modify the passed options hash.
- Fixes #7777.
-
- *Yves Senn*
-
-* Precompiled assets include aliases from `foo.js` to `foo/index.js` and vice versa.
-
- # Precompiles phone-<digest>.css and aliases phone/index.css to phone.css.
- config.assets.precompile = [ 'phone.css' ]
-
- # Precompiles phone/index-<digest>.css and aliases phone.css to phone/index.css.
- config.assets.precompile = [ 'phone/index.css' ]
-
- # Both of these work with either precompile thanks to their aliases.
- <%= stylesheet_link_tag 'phone', media: 'all' %>
- <%= stylesheet_link_tag 'phone/index', media: 'all' %>
-
- *Jeremy Kemper*
-
-* `assert_template` is no more passing with what ever string that matches
- with the template name.
-
- Before when we have a template `/layout/hello.html.erb`, `assert_template`
- was passing with any string that matches. This behavior allowed false
- positive like:
-
- assert_template "layout"
- assert_template "out/hello"
-
- Now it only passes with:
-
- assert_template "layout/hello"
- assert_template "hello"
-
- Fixes #3849.
-
- *Hugolnx*
-
-* `image_tag` will set the same width and height for image if numerical value
- passed to `size` option.
-
- *Nihad Abbasov*
-
-* Deprecate `Mime::Type#verify_request?` and `Mime::Type.browser_generated_types`,
- since they are no longer used inside of Rails, they will be removed in Rails 4.1.
-
- *Michael Grosser*
-
-* `ActionDispatch::Http::UploadedFile` now delegates `close` to its tempfile. *Sergio Gil*
-
-* Add `ActionController::StrongParameters`, this module converts `params` hash into
- an instance of ActionController::Parameters that allows whitelisting of permitted
- parameters. Non-permitted parameters are forbidden to be used in Active Model by default
- For more details check the documentation of the module or the
- [strong_parameters gem](https://github.com/rails/strong_parameters)
-
- *DHH + Guillermo Iguaran*
-
-* Remove Integration between `attr_accessible`/`attr_protected` and
- `ActionController::ParamsWrapper`. ParamWrapper now wraps all the parameters returned
- by the class method `attribute_names`.
-
- *Guillermo Iguaran*
-
-* Log now displays the correct status code when an exception is raised.
- Fixes #7646.
-
- *Yves Senn*
-
-* Allow pass couple extensions to `ActionView::Template.register_template_handler` call.
-
- *Tima Maslyuchenko*
-
-* Sprockets integration has been extracted from Action Pack to the `sprockets-rails`
- gem. `rails` gem is depending on `sprockets-rails` by default.
-
- *Guillermo Iguaran*
-
-* `ActionDispatch::Session::MemCacheStore` now uses `dalli` instead of the deprecated
- `memcache-client` gem.
-
- *Arun Agrawal + Guillermo Iguaran*
-
-* Support multiple etags in If-None-Match header. *Travis Warlick*
-
-* Allow to configure how unverified request will be handled using `:with`
- option in `protect_from_forgery` method.
-
- Valid unverified request handling methods are:
-
- - `:exception` - Raises ActionController::InvalidAuthenticityToken exception.
- - `:reset_session` - Resets the session.
- - `:null_session` - Provides an empty session during request but doesn't
- reset it completely. Used as default if `:with` option is not specified.
-
- New applications are generated with:
-
- protect_from_forgery with: :exception
-
- *Sergey Nartimov*
-
-* Add `.ruby` template handler, this handler simply allows arbitrary Ruby code as a template. *Guillermo Iguaran*
-
-* Add `separator` option for `ActionView::Helpers::TextHelper#excerpt`:
-
- excerpt('This is a very beautiful morning', 'very', separator: ' ', radius: 1)
- # => ...a very beautiful...
-
- *Guirec Corbel*
-
-* Added controller-level etag additions that will be part of the action etag computation *Jeremy Kemper/DHH*
-
- class InvoicesController < ApplicationController
- etag { current_user.try :id }
-
- def show
- # Etag will differ even for the same invoice when it's viewed by a different current_user
- @invoice = Invoice.find(params[:id])
- fresh_when(@invoice)
- end
- end
-
-* Add automatic template digests to all `CacheHelper#cache` calls (originally spiked in the `cache_digests` plugin) *DHH*
-
-* When building a URL fails, add missing keys provided by Journey. Failed URL
- generation now returns a 500 status instead of a 404.
-
- *Richard Schneeman*
-
-* Deprecate availability of `ActionView::RecordIdentifier` in controllers by default.
- It's view specific and can be easily included in controllers manually if someone
- really needs it. Also deprecate calling `ActionController::RecordIdentifier.dom_id` and
- `dom_class` directly, in favor of `ActionView::RecordIdentifier.dom_id` and `dom_class`.
- `RecordIdentifier` will be removed from `ActionController::Base` in Rails 4.1.
-
- *Piotr Sarnacki*
-
-* Fix `ActionView::RecordIdentifier` to work as a singleton. *Piotr Sarnacki*
-
-* Deprecate `Template#mime_type`, it will be removed in Rails 4.1 in favor of `#type`.
- *Piotr Sarnacki*
-
-* Move vendored html-scanner from `action_controller` to `action_view` directory. If you
- require it directly, please use 'action_view/vendor/html-scanner', reference to
- 'action_controller/vendor/html-scanner' will be removed in Rails 4.1. *Piot Sarnacki*
-
-* Fix handling of date selects when using both disabled and discard options.
- Fixes #7431.
-
- *Vasiliy Ermolovich*
-
-* `ActiveRecord::SessionStore` is extracted out of Rails into a gem `activerecord-session_store`.
- Setting `config.session_store` to `:active_record_store` will no longer work and will break
- if the `activerecord-session_store` gem isn't available. *Prem Sichanugrist*
-
-* Fix `select_tag` when `option_tags` is nil.
- Fixes #7404.
-
- *Sandeep Ravichandran*
-
-* Add `Request#formats=(extensions)` that lets you set multiple formats directly in a prioritized order.
-
- Example of using this for custom iphone views with an HTML fallback:
-
- class ApplicationController < ActionController::Base
- before_filter :adjust_format_for_iphone_with_html_fallback
-
- private
- def adjust_format_for_iphone_with_html_fallback
- request.formats = [ :iphone, :html ] if request.env["HTTP_USER_AGENT"][/iPhone/]
- end
- end
-
- *DHH*
-
-* Add Routing Concerns to declare common routes that can be reused inside
- others resources and routes.
-
- Code before:
-
- resources :messages do
- resources :comments
- end
-
- resources :posts do
- resources :comments
- resources :images, only: :index
- end
-
- Code after:
-
- concern :commentable do
- resources :comments
- end
-
- concern :image_attachable do
- resources :images, only: :index
- end
-
- resources :messages, concerns: :commentable
-
- resources :posts, concerns: [:commentable, :image_attachable]
-
- *DHH + Rafael Mendonça França*
-
-* Add `start_hour` and `end_hour` options to the `select_hour` helper. *Evan Tann*
-
-* Raises an `ArgumentError` when the first argument in `form_for` contain `nil`
- or is empty.
-
- *Richard Schneeman*
-
-* Add 'X-Frame-Options' => 'SAMEORIGIN'
- 'X-XSS-Protection' => '1; mode=block' and
- 'X-Content-Type-Options' => 'nosniff'
- as default headers.
-
- *Egor Homakov*
-
-* Allow data attributes to be set as a first-level option for `form_for`, so you can write `form_for @record, data: { behavior: 'autosave' }` instead of `form_for @record, html: { data: { behavior: 'autosave' } }` *DHH*
-
-* Deprecate `button_to_function` and `link_to_function` helpers.
-
- We recommend the use of Unobtrusive JavaScript instead. For example:
-
- link_to "Greeting", "#", class: "nav_link"
-
- $(function() {
- $('.nav_link').click(function() {
- // Some complex code
-
- return false;
- });
- });
-
- or
-
- link_to "Greeting", '#', onclick: "alert('Hello world!'); return false", class: "nav_link"
-
- for simple cases.
-
- *Rafael Mendonça França*
-
-* `javascript_include_tag :all` will now not include `application.js` if the file does not exists. *Prem Sichanugrist*
-
-* Send an empty response body when call `head` with status between 100 and 199, 204, 205 or 304.
-
- *Armand du Plessis*
-
-* Fixed issue with where digest authentication would not work behind a proxy. *Arthur Smith*
-
-* Added `ActionController::Live`. Mix it in to your controller and you can
- stream data to the client live. For example:
-
- class FooController < ActionController::Base
- include ActionController::Live
-
- def index
- 100.times {
- # Client will see this as it's written
- response.stream.write "hello world\n"
- sleep 1
- }
- response.stream.close
- end
- end
-
- *Aaron Patterson*
-
-* Remove `ActionDispatch::Head` middleware in favor of `Rack::Head`. *Santiago Pastorino*
-
-* Deprecate `:confirm` in favor of `data: { confirm: "Text" }` option for `button_to`, `button_tag`, `image_submit_tag`, `link_to` and `submit_tag` helpers.
-
- *Carlos Galdino + Rafael Mendonça França*
-
-* Show routes in exception page while debugging a `RoutingError` in development.
-
- *Richard Schneeman + Mattt Thompson + Yves Senn*
-
-* Add `ActionController::Flash.add_flash_types` method to allow people to register their own flash types. e.g.:
-
- class ApplicationController
- add_flash_types :error, :warning
- end
-
- If you add the above code, you can use `<%= error %>` in an erb, and `redirect_to /foo, error: 'message'` in a controller.
-
- *kennyj*
-
-* Remove Active Model dependency from Action Pack. *Guillermo Iguaran*
-
-* Support unicode characters in routes. Route will be automatically escaped, so instead of manually escaping:
-
- get Rack::Utils.escape('こんにちは') => 'home#index'
-
- You just have to write the unicode route:
-
- get 'こんにちは' => 'home#index'
-
- *kennyj*
-
-* Return proper format on exceptions. *Santiago Pastorino*
-
-* Allow to use `mounted_helpers` (helpers for accessing mounted engines) in `ActionView::TestCase`. *Piotr Sarnacki*
-
-* Include `mounted_helpers` (helpers for accessing mounted engines) in `ActionDispatch::IntegrationTest` by default. *Piotr Sarnacki*
-
-* Extracted redirect logic from `ActionController::ForceSSL::ClassMethods.force_ssl` into `ActionController::ForceSSL#force_ssl_redirect`
-
- *Jeremy Friesen*
-
-* Make possible to use a block in `button_to` if the button text is hard
- to fit into the name parameter, e.g.:
-
- <%= button_to [:make_happy, @user] do %>
- Make happy <strong><%= @user.name %></strong>
- <% end %>
- # => "<form method="post" action="/users/1/make_happy" class="button_to">
- # <div>
- # <button type="submit">
- # Make happy <strong>Name</strong>
- # </button>
- # </div>
- # </form>"
-
- *Sergey Nartimov*
-
-* Change a way of ordering helpers from several directories. Previously,
- when loading helpers from multiple paths, all of the helpers files were
- gathered into one array an then they were sorted. Helpers from different
- directories should not be mixed before loading them to make loading more
- predictable. The most common use case for such behavior is loading helpers
- from engines. When you load helpers from application and engine Foo, in
- that order, first rails will load all of the helpers from application,
- sorted alphabetically and then it will do the same for Foo engine.
-
- *Piotr Sarnacki*
-
-* `truncate` now always returns an escaped HTML-safe string. The option `:escape` can be used as
- false to not escape the result.
-
- *Li Ellis Gallardo + Rafael Mendonça França*
-
-* `truncate` now accepts a block to show extra content when the text is truncated. *Li Ellis Gallardo*
-
-* Add `week_field`, `week_field_tag`, `month_field`, `month_field_tag`, `datetime_local_field`,
- `datetime_local_field_tag`, `datetime_field` and `datetime_field_tag` helpers. *Carlos Galdino*
-
-* Add `color_field` and `color_field_tag` helpers. *Carlos Galdino*
-
-* `assert_generates`, `assert_recognizes`, and `assert_routing` all raise
- `Assertion` instead of `RoutingError` *David Chelimsky*
-
-* URL path parameters with invalid encoding now raise `ActionController::BadRequest`. *Andrew White*
-
-* Malformed query and request parameter hashes now raise `ActionController::BadRequest`. *Andrew White*
-
-* Add `divider` option to `grouped_options_for_select` to generate a separator
- `optgroup` automatically, and deprecate `prompt` as third argument, in favor
- of using an options hash. *Nicholas Greenfield*
-
-* Add `time_field` and `time_field_tag` helpers which render an `input[type="time"]` tag. *Alex Soulim*
-
-* Removed old text helper apis from `highlight`, `excerpt` and `word_wrap`. *Jeremy Walker*
-
-* Templates without a handler extension now raises a deprecation warning but still
- defaults to ERB. In future releases, it will simply return the template contents. *Steve Klabnik*
-
-* Deprecate `:disable_with` in favor of `data: { disable_with: "Text" }` option from `submit_tag`, `button_tag` and `button_to` helpers.
-
- *Carlos Galdino + Rafael Mendonça França*
-
-* Remove `:mouseover` option from `image_tag` helper. *Rafael Mendonça França*
-
-* The `select` method (select tag) forces `:include_blank` if `required` is true and
- `display size` is one and `multiple` is not true. *Angelo Capilleri*
-
-* Copy literal route constraints to defaults so that url generation know about them.
- The copied constraints are `:protocol`, `:subdomain`, `:domain`, `:host` and `:port`.
-
- *Andrew White*
-
-* `respond_to` and `respond_with` now raise `ActionController::UnknownFormat` instead
- of directly returning head 406. The exception is rescued and converted to 406
- in the exception handling middleware. *Steven Soroka*
-
-* Allows `assert_redirected_to` to match against a regular expression. *Andy Lindeman*
-
-* Add backtrace to development routing error page. *Richard Schneeman*
-
-* Replace `include_seconds` boolean argument with `include_seconds: true` option
- in `distance_of_time_in_words` and `time_ago_in_words` signature. *Dmitriy Kiriyenko*
-
-* Make current object and counter (when it applies) variables accessible when
- rendering templates with :object / :collection. *Carlos Antonio da Silva*
-
-* JSONP now uses mimetype `text/javascript` instead of `application/json`. *omjokine*
-
-* Allow to lazy load `default_form_builder` by passing a `String` instead of a constant. *Piotr Sarnacki*
-
-* Session arguments passed to `process` calls in functional tests are now merged into
- the existing session, whereas previously they would replace the existing session.
- This change may break some existing tests if they are asserting the exact contents of
- the session but should not break existing tests that only assert individual keys.
-
- *Andrew White*
-
-* Add `index` method to FormBuilder class. *Jorge Bejar*
-
-* Remove the leading \n added by textarea on `assert_select`. *Santiago Pastorino*
-
-* Changed default value for `config.action_view.embed_authenticity_token_in_remote_forms`
- to `false`. This change breaks remote forms that need to work also without JavaScript,
- so if you need such behavior, you can either set it to `true` or explicitly pass
- `authenticity_token: true` in form options.
-
-* Added `ActionDispatch::SSL` middleware that when included force all the requests to be under HTTPS protocol. *Rafael Mendonça França*
-
-* Add `include_hidden` option to select tag. With `include_hidden: false` select with `multiple` attribute doesn't generate hidden input with blank value. *Vasiliy Ermolovich*
-
-* Removed default `size` option from the `text_field`, `search_field`, `telephone_field`, `url_field`, `email_field` helpers. *Philip Arndt*
-
-* Removed default `cols` and `rows` options from the `text_area` helper. *Philip Arndt*
-
-* Adds support for layouts when rendering a partial with a given collection. *serabe*
-
-* Allows the route helper `root` to take a string argument. For example, `root 'pages#main'`. *bcardarella*
-
-* Forms of persisted records use always PATCH (via the `_method` hack). *fxn*
-
-* For resources, both PATCH and PUT are routed to the `update` action. *fxn*
-
-* Don't ignore `force_ssl` in development. This is a change of behavior - use a `:if` condition to recreate the old behavior.
-
- class AccountsController < ApplicationController
- force_ssl if: :ssl_configured?
-
- def ssl_configured?
- !Rails.env.development?
- end
- end
-
- *Pat Allan*
-
-* Adds support for the PATCH verb:
- * Request objects respond to `patch?`.
- * Routes have a new `patch` method, and understand `:patch` in the
- existing places where a verb is configured, like `:via`.
- * New method `patch` available in functional tests.
- * If `:patch` is the default verb for updates, edits are
- tunneled as PATCH rather than as PUT, and routing acts accordingly.
- * New method `patch_via_redirect` available in integration tests.
-
- *dlee*
-
-* Integration tests support the `OPTIONS` method. *Jeremy Kemper*
-
-* `expires_in` accepts a `must_revalidate` flag. If true, "must-revalidate"
- is added to the Cache-Control header. *fxn*
-
-* Add `date_field` and `date_field_tag` helpers which render an `input[type="date"]` tag *Olek Janiszewski*
-
-* Adds `image_url`, `javascript_url`, `stylesheet_url`, `audio_url`, `video_url`, and `font_url`
- to assets tag helper. These URL helpers will return the full path to your assets. This is useful
- when you are going to reference this asset from external host. *Prem Sichanugrist*
-
-* Default responder will now always use your overridden block in `respond_with` to render your response. *Prem Sichanugrist*
-
-* Allow `value_method` and `text_method` arguments from `collection_select` and
- `options_from_collection_for_select` to receive an object that responds to `:call`,
- such as a `proc`, to evaluate the option in the current element context. This works
- the same way with `collection_radio_buttons` and `collection_check_boxes`.
-
- *Carlos Antonio da Silva + Rafael Mendonça França*
-
-* Add `collection_check_boxes` form helper, similar to `collection_select`:
- Example:
-
- collection_check_boxes :post, :author_ids, Author.all, :id, :name
- # Outputs something like:
- <input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" />
- <label for="post_author_ids_1">D. Heinemeier Hansson</label>
- <input id="post_author_ids_2" name="post[author_ids][]" type="checkbox" value="2" />
- <label for="post_author_ids_2">D. Thomas</label>
- <input name="post[author_ids][]" type="hidden" value="" />
-
- The label/check_box pairs can be customized with a block.
-
- *Carlos Antonio da Silva + Rafael Mendonça França*
-
-* Add `collection_radio_buttons` form helper, similar to `collection_select`:
- Example:
-
- collection_radio_buttons :post, :author_id, Author.all, :id, :name
- # Outputs something like:
- <input id="post_author_id_1" name="post[author_id]" type="radio" value="1" />
- <label for="post_author_id_1">D. Heinemeier Hansson</label>
- <input id="post_author_id_2" name="post[author_id]" type="radio" value="2" />
- <label for="post_author_id_2">D. Thomas</label>
-
- The label/radio_button pairs can be customized with a block.
-
- *Carlos Antonio da Silva + Rafael Mendonça França*
-
-* `check_box` with `:form` html5 attribute will now replicate the `:form`
- attribute to the hidden field as well. *Carlos Antonio da Silva*
-
-* `label` form helper accepts `for: nil` to not generate the attribute. *Carlos Antonio da Silva*
-
-* Add `:format` option to `number_to_percentage`. *Rodrigo Flores*
-
-* Add `config.action_view.logger` to configure logger for Action View. *Rafael Mendonça França*
-
-* Deprecated `ActionController::Integration` in favour of `ActionDispatch::Integration`.
-
-* Deprecated `ActionController::IntegrationTest` in favour of `ActionDispatch::IntegrationTest`.
-
-* Deprecated `ActionController::PerformanceTest` in favour of `ActionDispatch::PerformanceTest`.
-
-* Deprecated `ActionController::AbstractRequest` in favour of `ActionDispatch::Request`.
-
-* Deprecated `ActionController::Request` in favour of `ActionDispatch::Request`.
-
-* Deprecated `ActionController::AbstractResponse` in favour of `ActionDispatch::Response`.
-
-* Deprecated `ActionController::Response` in favour of `ActionDispatch::Response`.
-
-* Deprecated `ActionController::Routing` in favour of `ActionDispatch::Routing`.
-
-* `check_box helper` with `disabled: true` will generate a disabled
- hidden field to conform with the HTML convention where disabled fields are
- not submitted with the form. This is a behavior change, previously the hidden
- tag had a value of the disabled checkbox. *Tadas Tamosauskas*
-
-* `favicon_link_tag` helper will now use the favicon in app/assets by default. *Lucas Caton*
-
-* `ActionView::Helpers::TextHelper#highlight` now defaults to the
- HTML5 `mark` element. *Brian Cardarella*
-
-Please check [3-2-stable](https://github.com/rails/rails/blob/3-2-stable/actionpack/CHANGELOG.md) for previous changes.
+Please check [4-0-stable](https://github.com/rails/rails/blob/4-0-stable/actionpack/CHANGELOG.md) for previous changes.
diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb
index bac994496e..8e7bdf620e 100644
--- a/actionpack/lib/abstract_controller/layouts.rb
+++ b/actionpack/lib/abstract_controller/layouts.rb
@@ -309,6 +309,7 @@ module AbstractController
RUBY
when Proc
define_method :_layout_from_proc, &_layout
+ protected :_layout_from_proc
<<-RUBY
result = _layout_from_proc(#{_layout.arity == 0 ? '' : 'self'})
return #{default_behavior} if result.nil?
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 143b3e0cbd..b84c9e78c3 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -36,8 +36,7 @@ module ActionController
raise "MiddlewareStack#build requires an app" unless app
middlewares.reverse.inject(app) do |a, middleware|
- middleware.valid?(action) ?
- middleware.build(a) : a
+ middleware.valid?(action) ? middleware.build(a) : a
end
end
end
@@ -57,7 +56,7 @@ module ActionController
# And then to route requests to your metal controller, you would add
# something like this to <tt>config/routes.rb</tt>:
#
- # match 'hello', to: HelloController.action(:index)
+ # get 'hello', to: HelloController.action(:index)
#
# The +action+ method returns a valid Rack application for the \Rails
# router to dispatch to.
diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb
index f1e8714a86..b8afce42c9 100644
--- a/actionpack/lib/action_controller/metal/force_ssl.rb
+++ b/actionpack/lib/action_controller/metal/force_ssl.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/hash/except'
+require 'active_support/core_ext/hash/slice'
+
module ActionController
# This module provides a method which will redirect browser to use HTTPS
# protocol. This will ensure that user's sensitive information will be
@@ -14,6 +17,10 @@ module ActionController
extend ActiveSupport::Concern
include AbstractController::Callbacks
+ ACTION_OPTIONS = [:only, :except, :if, :unless]
+ URL_OPTIONS = [:protocol, :host, :domain, :subdomain, :port, :path]
+ REDIRECT_OPTIONS = [:status, :flash, :alert, :notice]
+
module ClassMethods
# Force the request to this particular controller or specified actions to be
# under HTTPS protocol.
@@ -29,18 +36,34 @@ module ActionController
# end
# end
#
- # ==== Options
- # * <tt>host</tt> - Redirect to a different host name
- # * <tt>only</tt> - The callback should be run only for this action
- # * <tt>except</tt> - The callback should be run for all actions except this action
- # * <tt>if</tt> - A symbol naming an instance method or a proc; the callback
- # will be called only when it returns a true value.
- # * <tt>unless</tt> - A symbol naming an instance method or a proc; the callback
- # will be called only when it returns a false value.
+ # ==== URL Options
+ # You can pass any of the following options to affect the redirect url
+ # * <tt>host</tt> - Redirect to a different host name
+ # * <tt>subdomain</tt> - Redirect to a different subdomain
+ # * <tt>domain</tt> - Redirect to a different domain
+ # * <tt>port</tt> - Redirect to a non-standard port
+ # * <tt>path</tt> - Redirect to a different path
+ #
+ # ==== Redirect Options
+ # You can pass any of the following options to affect the redirect status and response
+ # * <tt>status</tt> - Redirect with a custom status (default is 301 Moved Permanently)
+ # * <tt>flash</tt> - Set a flash message when redirecting
+ # * <tt>alert</tt> - Set a alert message when redirecting
+ # * <tt>notice</tt> - Set a notice message when redirecting
+ #
+ # ==== Action Options
+ # You can pass any of the following options to affect the before_action callback
+ # * <tt>only</tt> - The callback should be run only for this action
+ # * <tt>except</tt> - The callback should be run for all actions except this action
+ # * <tt>if</tt> - A symbol naming an instance method or a proc; the callback
+ # will be called only when it returns a true value.
+ # * <tt>unless</tt> - A symbol naming an instance method or a proc; the callback
+ # will be called only when it returns a false value.
def force_ssl(options = {})
- host = options.delete(:host)
- before_action(options) do
- force_ssl_redirect(host)
+ action_options = options.slice(*ACTION_OPTIONS)
+ redirect_options = options.except(*ACTION_OPTIONS)
+ before_action(action_options) do
+ force_ssl_redirect(redirect_options)
end
end
end
@@ -48,14 +71,26 @@ module ActionController
# Redirect the existing request to use the HTTPS protocol.
#
# ==== Parameters
- # * <tt>host</tt> - Redirect to a different host name
- def force_ssl_redirect(host = nil)
+ # * <tt>host_or_options</tt> - Either a host name or any of the url & redirect options
+ # available to the <tt>force_ssl</tt> method.
+ def force_ssl_redirect(host_or_options = nil)
unless request.ssl?
- redirect_options = {:protocol => 'https://', :status => :moved_permanently}
- redirect_options.merge!(:host => host) if host
- redirect_options.merge!(:params => request.query_parameters)
+ options = {
+ :protocol => 'https://',
+ :host => request.host,
+ :path => request.fullpath,
+ :status => :moved_permanently
+ }
+
+ if host_or_options.is_a?(Hash)
+ options.merge!(host_or_options)
+ elsif host_or_options
+ options.merge!(:host => host_or_options)
+ end
+
+ secure_url = ActionDispatch::Http::URL.url_for(options.slice(*URL_OPTIONS))
flash.keep if respond_to?(:flash)
- redirect_to redirect_options
+ redirect_to secure_url, options.slice(*REDIRECT_OPTIONS)
end
end
end
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 23d70c9ea2..44703221f3 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -230,7 +230,7 @@ module ActionController
# params = ActionController::Parameters.new({
# person: {
# contact: {
- # email: 'none@test.com'
+ # email: 'none@test.com',
# phone: '555-1234'
# }
# }
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index a35a613158..41a286f0ed 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -455,13 +455,14 @@ module ActionController
#
# - +action+: The controller action to call.
# - +parameters+: The HTTP parameters that you want to pass. This may
- # be +nil+, a Hash, or a String that is appropriately encoded
+ # be +nil+, a hash, or a string that is appropriately encoded
# (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
- # - +session+: A Hash of parameters to store in the session. This may be +nil+.
- # - +flash+: A Hash of parameters to store in the flash. This may be +nil+.
+ # - +session+: A hash of parameters to store in the session. This may be +nil+.
+ # - +flash+: A hash of parameters to store in the flash. This may be +nil+.
+ #
+ # You can also simulate POST, PATCH, PUT, DELETE, HEAD, and OPTIONS requests with
+ # +post+, +patch+, +put+, +delete+, +head+, and +options+.
#
- # You can also simulate POST, PATCH, PUT, DELETE, and HEAD requests with
- # +#post+, +#patch+, +#put+, +#delete+, and +#head+.
# Note that the request method is not verified. The different methods are
# available to make the tests more expressive.
def get(action, *args)
@@ -469,37 +470,37 @@ module ActionController
end
# Simulate a POST request with the given parameters and set/volley the response.
- # See +#get+ for more details.
+ # See +get+ for more details.
def post(action, *args)
process(action, "POST", *args)
end
# Simulate a PATCH request with the given parameters and set/volley the response.
- # See +#get+ for more details.
+ # See +get+ for more details.
def patch(action, *args)
process(action, "PATCH", *args)
end
# Simulate a PUT request with the given parameters and set/volley the response.
- # See +#get+ for more details.
+ # See +get+ for more details.
def put(action, *args)
process(action, "PUT", *args)
end
# Simulate a DELETE request with the given parameters and set/volley the response.
- # See +#get+ for more details.
+ # See +get+ for more details.
def delete(action, *args)
process(action, "DELETE", *args)
end
# Simulate a HEAD request with the given parameters and set/volley the response.
- # See +#get+ for more details.
+ # See +get+ for more details.
def head(action, *args)
process(action, "HEAD", *args)
end
# Simulate a OPTIONS request with the given parameters and set/volley the response.
- # See +#get+ for more details.
+ # See +get+ for more details.
def options(action, *args)
process(action, "OPTIONS", *args)
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 06e936cdb0..60a2cccdc5 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -55,6 +55,7 @@ module ActionDispatch # :nodoc:
CONTENT_TYPE = "Content-Type".freeze
SET_COOKIE = "Set-Cookie".freeze
LOCATION = "Location".freeze
+ NO_CONTENT_CODES = [204, 304]
cattr_accessor(:default_charset) { "utf-8" }
cattr_accessor(:default_headers)
@@ -289,7 +290,7 @@ module ActionDispatch # :nodoc:
header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join)
- if [204, 304].include?(@status)
+ if NO_CONTENT_CODES.include?(@status)
header.delete CONTENT_TYPE
[status, header, []]
else
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index ab5399c8ea..6f5a52c568 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -4,7 +4,9 @@ require 'active_support/core_ext/hash/slice'
module ActionDispatch
module Http
module URL
- IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
+ IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
+ HOST_REGEXP = /(^.*:\/\/)?([^:]+)(?::(\d+$))?/
+ PROTOCOL_REGEXP = /^([^:]+)(:)?(\/\/)?$/
mattr_accessor :tld_length
self.tld_length = 1
@@ -28,6 +30,7 @@ module ActionDispatch
end
def url_for(options = {})
+ options = options.dup
path = options.delete(:script_name).to_s.chomp("/")
path << options.delete(:path).to_s
@@ -59,15 +62,20 @@ module ActionDispatch
result = ""
unless options[:only_path]
- protocol = extract_protocol(options)
- unless options[:protocol] == false
- result << protocol
- result << ":" unless result.match(%r{:|//})
+ if match = options[:host].match(HOST_REGEXP)
+ options[:protocol] ||= match[1] unless options[:protocol] == false
+ options[:host] = match[2]
+ options[:port] = match[3] unless options.key?(:port)
end
- result << "//" unless result.match("//")
+
+ options[:protocol] = normalize_protocol(options)
+ options[:host] = normalize_host(options)
+ options[:port] = normalize_port(options)
+
+ result << options[:protocol]
result << rewrite_authentication(options)
- result << host_or_subdomain_and_domain(options)
- result << ":#{options.delete(:port)}" if options[:port]
+ result << options[:host]
+ result << ":#{options[:port]}" if options[:port]
end
result
end
@@ -76,6 +84,10 @@ module ActionDispatch
host && IP_HOST_REGEXP !~ host
end
+ def same_host?(options)
+ (options[:subdomain] == true || !options.key?(:subdomain)) && options[:domain].nil?
+ end
+
def rewrite_authentication(options)
if options[:user] && options[:password]
"#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
@@ -84,29 +96,47 @@ module ActionDispatch
end
end
- # Extracts protocol http:// or https:// from options[:host]
- # needs to be called whether the :protocol is being used or not
- def extract_protocol(options)
- if options[:host] && match = options[:host].match(/(^.*:\/\/)(.*)/)
- options[:protocol] ||= match[1]
- options[:host] = match[2]
+ def normalize_protocol(options)
+ case options[:protocol]
+ when nil
+ "http://"
+ when false, "//"
+ "//"
+ when PROTOCOL_REGEXP
+ "#{$1}://"
+ else
+ raise ArgumentError, "Invalid :protocol option: #{options[:protocol].inspect}"
end
- options[:protocol] || "http"
end
- def host_or_subdomain_and_domain(options)
- return options[:host] if !named_host?(options[:host]) || (options[:subdomain].nil? && options[:domain].nil?)
+ def normalize_host(options)
+ return options[:host] if !named_host?(options[:host]) || same_host?(options)
tld_length = options[:tld_length] || @@tld_length
host = ""
- unless options[:subdomain] == false
- host << (options[:subdomain] || extract_subdomain(options[:host], tld_length)).to_param
- host << "."
+ if options[:subdomain] == true || !options.key?(:subdomain)
+ host << extract_subdomain(options[:host], tld_length).to_param
+ elsif options[:subdomain].present?
+ host << options[:subdomain].to_param
end
+ host << "." unless host.empty?
host << (options[:domain] || extract_domain(options[:host], tld_length))
host
end
+
+ def normalize_port(options)
+ return nil if options[:port].nil? || options[:port] == false
+
+ case options[:protocol]
+ when "//"
+ nil
+ when "https://"
+ options[:port].to_i == 443 ? nil : options[:port]
+ else
+ options[:port].to_i == 80 ? nil : options[:port]
+ end
+ end
end
def initialize(env)
diff --git a/actionpack/lib/action_dispatch/journey/parser.y b/actionpack/lib/action_dispatch/journey/parser.y
index a2e1afed32..040f8d5922 100644
--- a/actionpack/lib/action_dispatch/journey/parser.y
+++ b/actionpack/lib/action_dispatch/journey/parser.y
@@ -36,6 +36,7 @@ rule
;
literal
: LITERAL { result = Literal.new(val.first) }
+ ;
dot
: DOT { result = Dot.new(val.first) }
;
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
index 6fda085681..50e1853094 100644
--- a/actionpack/lib/action_dispatch/journey/route.rb
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -102,6 +102,10 @@ module ActionDispatch
value === request.send(method).to_s
when Array
value.include?(request.send(method))
+ when TrueClass
+ request.send(method).present?
+ when FalseClass
+ request.send(method).blank?
else
value === request.send(method)
end
diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb
index 31868b1814..419e665d12 100644
--- a/actionpack/lib/action_dispatch/journey/router.rb
+++ b/actionpack/lib/action_dispatch/journey/router.rb
@@ -38,7 +38,9 @@ module ActionDispatch
env['REMOTE_ADDR']
end
- def [](k); env[k]; end
+ def [](k)
+ env[k]
+ end
end
attr_reader :request_class, :formatter
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 7489ce8028..1de3d14530 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -9,9 +9,11 @@ module ActionDispatch
'ActionController::RoutingError' => :not_found,
'AbstractController::ActionNotFound' => :not_found,
'ActionController::MethodNotAllowed' => :method_not_allowed,
+ 'ActionController::UnknownHttpMethod' => :method_not_allowed,
'ActionController::NotImplemented' => :not_implemented,
'ActionController::UnknownFormat' => :not_acceptable,
'ActionController::InvalidAuthenticityToken' => :unprocessable_entity,
+ 'ActionDispatch::ParamsParser::ParseError' => :bad_request,
'ActionController::BadRequest' => :bad_request,
'ActionController::ParameterMissing' => :bad_request
)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 80054c8a40..c3fd0c18ec 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -299,7 +299,7 @@ module ActionDispatch
end
end
- # Invokes Rack::Mount::Utils.normalize path and ensure that
+ # Invokes Journey::Router::Utils.normalize_path and ensure that
# (:locale) becomes (/:locale) instead of /(:locale). Except
# for root cases, where the latter is the correct one.
def self.normalize_path(path)
@@ -945,6 +945,8 @@ module ActionDispatch
VALID_ON_OPTIONS = [:new, :collection, :member]
RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except, :param, :concerns]
CANONICAL_ACTIONS = %w(index create new show update destroy)
+ RESOURCE_METHOD_SCOPES = [:collection, :member, :new]
+ RESOURCE_SCOPES = [:resource, :resources]
class Resource #:nodoc:
attr_reader :controller, :path, :options, :param
@@ -1499,11 +1501,11 @@ module ActionDispatch
end
def resource_scope? #:nodoc:
- [:resource, :resources].include? @scope[:scope_level]
+ RESOURCE_SCOPES.include? @scope[:scope_level]
end
def resource_method_scope? #:nodoc:
- [:collection, :member, :new].include? @scope[:scope_level]
+ RESOURCE_METHOD_SCOPES.include? @scope[:scope_level]
end
def with_exclusive_scope
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index d48a83e6c6..342b6ec23d 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -170,9 +170,10 @@ module ActionDispatch
def call(t, args)
if args.size == arg_size && !args.last.is_a?(Hash) && optimize_routes_generation?(t)
- @options.merge!(t.url_options) if t.respond_to?(:url_options)
- @options[:path] = optimized_helper(args)
- ActionDispatch::Http::URL.url_for(@options)
+ options = @options.dup
+ options.merge!(t.url_options) if t.respond_to?(:url_options)
+ options[:path] = optimized_helper(args)
+ ActionDispatch::Http::URL.url_for(options)
else
super
end
diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb
index b5e47d78d1..fd08f392aa 100644
--- a/actionpack/lib/action_pack/version.rb
+++ b/actionpack/lib/action_pack/version.rb
@@ -1,7 +1,7 @@
module ActionPack
# Returns the version of the currently loaded ActionPack as a Gem::Version
def self.version
- Gem::Version.new "4.0.0.beta1"
+ Gem::Version.new "4.1.0.beta"
end
module VERSION #:nodoc:
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index d3953c26b7..8fb5eb1548 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -808,7 +808,7 @@ module ActionView
options[:max_years_allowed] = @options[:max_years_allowed] || 1000
if (options[:end] - options[:start]).abs > options[:max_years_allowed]
- raise ArgumentError, "There're too many years options to be built. Are you sure you haven't mistyped something? You can provide the :max_years_allowed parameter"
+ raise ArgumentError, "There are too many years options to be built. Are you sure you haven't mistyped something? You can provide the :max_years_allowed parameter."
end
build_options_and_select(:year, val, options)
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index 7e65ebb4e4..719c9c09b5 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -380,7 +380,7 @@ module ActionView
# should produce the desired results.
def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
options = collection.map do |element|
- [value_for_collection(element, text_method), value_for_collection(element, value_method)]
+ [value_for_collection(element, text_method), value_for_collection(element, value_method), option_html_attributes(element)]
end
selected, disabled = extract_selected_and_disabled(selected)
select_deselect = {
diff --git a/actionpack/lib/action_view/path_set.rb b/actionpack/lib/action_view/path_set.rb
index d9c76366f8..91ee2ea8f5 100644
--- a/actionpack/lib/action_view/path_set.rb
+++ b/actionpack/lib/action_view/path_set.rb
@@ -1,5 +1,11 @@
module ActionView #:nodoc:
# = Action View PathSet
+ #
+ # This class is used to store and access paths in Action View. A number of
+ # operations are defined so that you can search among the paths in this
+ # set and also perform operations on other +PathSet+ objects.
+ #
+ # A +LookupContext+ will use a +PathSet+ to store the paths in its context.
class PathSet #:nodoc:
include Enumerable
diff --git a/actionpack/lib/action_view/renderer/abstract_renderer.rb b/actionpack/lib/action_view/renderer/abstract_renderer.rb
index 6fb8cbb46c..73c19a0ae2 100644
--- a/actionpack/lib/action_view/renderer/abstract_renderer.rb
+++ b/actionpack/lib/action_view/renderer/abstract_renderer.rb
@@ -1,4 +1,19 @@
module ActionView
+ # This class defines the interface for a renderer. Each class that
+ # subclasses +AbstractRenderer+ is used by the base +Renderer+ class to
+ # render a specific type of object.
+ #
+ # The base +Renderer+ class uses its +render+ method to delegate to the
+ # renderers. These currently consist of
+ #
+ # PartialRenderer - Used for rendering partials
+ # TemplateRenderer - Used for rendering other types of templates
+ # StreamingTemplateRenderer - Used for streaming
+ #
+ # Whenever the +render+ method is called on the base +Renderer+ class, a new
+ # renderer object of the correct type is created, and the +render+ method on
+ # that new object is called in turn. This abstracts the setup and rendering
+ # into a separate classes for partials and templates.
class AbstractRenderer #:nodoc:
delegate :find_template, :template_exists?, :with_fallbacks, :with_layout_format, :formats, :to => :@lookup_context
diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb
index 43a88b0623..821026268a 100644
--- a/actionpack/lib/action_view/renderer/partial_renderer.rb
+++ b/actionpack/lib/action_view/renderer/partial_renderer.rb
@@ -313,6 +313,13 @@ module ActionView
private
+ # Sets up instance variables needed for rendering a partial. This method
+ # finds the options and details and extracts them. The method also contains
+ # logic that handles the type of object passed in as the partial.
+ #
+ # If +options[:partial]+ is a string, then the +@path+ instance variable is
+ # set to that string. Otherwise, the +options[:partial]+ object must
+ # respond to +to_partial_path+ in order to setup the path.
def setup(context, options, block)
@view = context
partial = options[:partial]
@@ -413,6 +420,13 @@ module ActionView
end
end
+ # Obtains the path to where the object's partial is located. If the object
+ # responds to +to_partial_path+, then +to_partial_path+ will be called and
+ # will provide the path. If the object does not respond to +to_partial_path+,
+ # then an +ArgumentError+ is raised.
+ #
+ # If +prefix_partial_path_with_controller_namespace+ is true, then this
+ # method will prefix the partial paths with a namespace.
def partial_path(object = @object)
object = object.to_model if object.respond_to?(:to_model)
diff --git a/actionpack/lib/action_view/renderer/renderer.rb b/actionpack/lib/action_view/renderer/renderer.rb
index 30a0c4be70..964b18337e 100644
--- a/actionpack/lib/action_view/renderer/renderer.rb
+++ b/actionpack/lib/action_view/renderer/renderer.rb
@@ -2,6 +2,12 @@ module ActionView
# This is the main entry point for rendering. It basically delegates
# to other objects like TemplateRenderer and PartialRenderer which
# actually renders the template.
+ #
+ # The Renderer will parse the options from the +render+ or +render_body+
+ # method and render a partial or a template based on the options. The
+ # +TemplateRenderer+ and +PartialRenderer+ objects are wrappers which do all
+ # the setup and logic necessary to render a view and a new object is created
+ # each time +render+ is called.
class Renderer
attr_accessor :lookup_context
diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb
index 92baad4523..4a05c00f8b 100644
--- a/actionpack/test/abstract/layouts_test.rb
+++ b/actionpack/test/abstract/layouts_test.rb
@@ -8,6 +8,8 @@ module AbstractControllerTests
include AbstractController::Rendering
include AbstractController::Layouts
+ abstract!
+
self.view_paths = [ActionView::FixtureResolver.new(
"layouts/hello.erb" => "With String <%= yield %>",
"layouts/hello_override.erb" => "With Override <%= yield %>",
@@ -251,6 +253,10 @@ module AbstractControllerTests
assert_equal "Hello nil!", controller.response_body
end
+ test "when layout is specified as a proc, do not leak any methods into controller's action_methods" do
+ assert_equal Set.new(['index']), WithProc.action_methods
+ end
+
test "when layout is specified as a proc, call it and use the layout returned" do
controller = WithProc.new
controller.process(:index)
diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb
index 6758668b7a..3655b90e32 100644
--- a/actionpack/test/controller/force_ssl_test.rb
+++ b/actionpack/test/controller/force_ssl_test.rb
@@ -14,8 +14,42 @@ class ForceSSLControllerLevel < ForceSSLController
force_ssl
end
-class ForceSSLCustomDomain < ForceSSLController
- force_ssl :host => "secure.test.host"
+class ForceSSLCustomOptions < ForceSSLController
+ force_ssl :host => "secure.example.com", :only => :redirect_host
+ force_ssl :port => 8443, :only => :redirect_port
+ force_ssl :subdomain => 'secure', :only => :redirect_subdomain
+ force_ssl :domain => 'secure.com', :only => :redirect_domain
+ force_ssl :path => '/foo', :only => :redirect_path
+ force_ssl :status => :found, :only => :redirect_status
+ force_ssl :flash => { :message => 'Foo, Bar!' }, :only => :redirect_flash
+ force_ssl :alert => 'Foo, Bar!', :only => :redirect_alert
+ force_ssl :notice => 'Foo, Bar!', :only => :redirect_notice
+
+ def force_ssl_action
+ render :text => action_name
+ end
+
+ alias_method :redirect_host, :force_ssl_action
+ alias_method :redirect_port, :force_ssl_action
+ alias_method :redirect_subdomain, :force_ssl_action
+ alias_method :redirect_domain, :force_ssl_action
+ alias_method :redirect_path, :force_ssl_action
+ alias_method :redirect_status, :force_ssl_action
+ alias_method :redirect_flash, :force_ssl_action
+ alias_method :redirect_alert, :force_ssl_action
+ alias_method :redirect_notice, :force_ssl_action
+
+ def use_flash
+ render :text => flash[:message]
+ end
+
+ def use_alert
+ render :text => flash[:alert]
+ end
+
+ def use_notice
+ render :text => flash[:notice]
+ end
end
class ForceSSLOnlyAction < ForceSSLController
@@ -80,19 +114,77 @@ class ForceSSLControllerLevelTest < ActionController::TestCase
end
end
-class ForceSSLCustomDomainTest < ActionController::TestCase
- tests ForceSSLCustomDomain
+class ForceSSLCustomOptionsTest < ActionController::TestCase
+ tests ForceSSLCustomOptions
- def test_banana_redirects_to_https_with_custom_host
- get :banana
+ def setup
+ @request.env['HTTP_HOST'] = 'www.example.com:80'
+ end
+
+ def test_redirect_to_custom_host
+ get :redirect_host
assert_response 301
- assert_equal "https://secure.test.host/force_ssl_custom_domain/banana", redirect_to_url
+ assert_equal "https://secure.example.com/force_ssl_custom_options/redirect_host", redirect_to_url
end
- def test_cheeseburger_redirects_to_https_with_custom_host
- get :cheeseburger
+ def test_redirect_to_custom_port
+ get :redirect_port
+ assert_response 301
+ assert_equal "https://www.example.com:8443/force_ssl_custom_options/redirect_port", redirect_to_url
+ end
+
+ def test_redirect_to_custom_subdomain
+ get :redirect_subdomain
assert_response 301
- assert_equal "https://secure.test.host/force_ssl_custom_domain/cheeseburger", redirect_to_url
+ assert_equal "https://secure.example.com/force_ssl_custom_options/redirect_subdomain", redirect_to_url
+ end
+
+ def test_redirect_to_custom_domain
+ get :redirect_domain
+ assert_response 301
+ assert_equal "https://www.secure.com/force_ssl_custom_options/redirect_domain", redirect_to_url
+ end
+
+ def test_redirect_to_custom_path
+ get :redirect_path
+ assert_response 301
+ assert_equal "https://www.example.com/foo", redirect_to_url
+ end
+
+ def test_redirect_to_custom_status
+ get :redirect_status
+ assert_response 302
+ assert_equal "https://www.example.com/force_ssl_custom_options/redirect_status", redirect_to_url
+ end
+
+ def test_redirect_to_custom_flash
+ get :redirect_flash
+ assert_response 301
+ assert_equal "https://www.example.com/force_ssl_custom_options/redirect_flash", redirect_to_url
+
+ get :use_flash
+ assert_response 200
+ assert_equal "Foo, Bar!", @response.body
+ end
+
+ def test_redirect_to_custom_alert
+ get :redirect_alert
+ assert_response 301
+ assert_equal "https://www.example.com/force_ssl_custom_options/redirect_alert", redirect_to_url
+
+ get :use_alert
+ assert_response 200
+ assert_equal "Foo, Bar!", @response.body
+ end
+
+ def test_redirect_to_custom_notice
+ get :redirect_notice
+ assert_response 301
+ assert_equal "https://www.example.com/force_ssl_custom_options/redirect_notice", redirect_to_url
+
+ get :use_notice
+ assert_response 200
+ assert_equal "Foo, Bar!", @response.body
end
end
@@ -149,16 +241,79 @@ class ForceSSLFlashTest < ActionController::TestCase
assert_response 302
assert_equal "http://test.host/force_ssl_flash/cheeseburger", redirect_to_url
+ # FIXME: AC::TestCase#build_request_uri doesn't build a new uri if PATH_INFO exists
+ @request.env.delete('PATH_INFO')
+
get :cheeseburger
assert_response 301
assert_equal "https://test.host/force_ssl_flash/cheeseburger", redirect_to_url
+ # FIXME: AC::TestCase#build_request_uri doesn't build a new uri if PATH_INFO exists
+ @request.env.delete('PATH_INFO')
+
get :use_flash
assert_equal "hello", assigns["flash_copy"]["that"]
assert_equal "hello", assigns["flashy"]
end
end
+class ForceSSLDuplicateRoutesTest < ActionController::TestCase
+ tests ForceSSLControllerLevel
+
+ def test_force_ssl_redirects_to_same_path
+ with_routing do |set|
+ set.draw do
+ get '/foo', :to => 'force_ssl_controller_level#banana'
+ get '/bar', :to => 'force_ssl_controller_level#banana'
+ end
+
+ @request.env['PATH_INFO'] = '/bar'
+
+ get :banana
+ assert_response 301
+ assert_equal 'https://test.host/bar', redirect_to_url
+ end
+ end
+end
+
+class ForceSSLFormatTest < ActionController::TestCase
+ tests ForceSSLControllerLevel
+
+ def test_force_ssl_redirects_to_same_format
+ with_routing do |set|
+ set.draw do
+ get '/foo', :to => 'force_ssl_controller_level#banana'
+ end
+
+ get :banana, :format => :json
+ assert_response 301
+ assert_equal 'https://test.host/foo.json', redirect_to_url
+ end
+ end
+end
+
+class ForceSSLOptionalSegmentsTest < ActionController::TestCase
+ tests ForceSSLControllerLevel
+
+ def test_force_ssl_redirects_to_same_format
+ with_routing do |set|
+ set.draw do
+ scope '(:locale)' do
+ defaults :locale => 'en' do
+ get '/foo', :to => 'force_ssl_controller_level#banana'
+ end
+ end
+ end
+
+ @request.env['PATH_INFO'] = '/en/foo'
+ get :banana, :locale => 'en'
+ assert_equal 'en', @controller.params[:locale]
+ assert_response 301
+ assert_equal 'https://test.host/en/foo', redirect_to_url
+ end
+ end
+end
+
class RedirectToSSLTest < ActionController::TestCase
tests RedirectToSSL
def test_banana_redirects_to_https_if_not_https
diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb
index ba24e7fac5..088ad73f2f 100644
--- a/actionpack/test/controller/url_for_test.rb
+++ b/actionpack/test/controller/url_for_test.rb
@@ -89,6 +89,13 @@ module AbstractController
)
end
+ def test_subdomain_may_be_removed_with_blank_string
+ W.default_url_options[:host] = 'api.basecamphq.com'
+ assert_equal('http://basecamphq.com/c/a/i',
+ W.new.url_for(:subdomain => '', :controller => 'c', :action => 'a', :id => 'i')
+ )
+ end
+
def test_multiple_subdomains_may_be_removed
W.default_url_options[:host] = 'mobile.www.api.basecamphq.com'
assert_equal('http://basecamphq.com/c/a/i',
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index 6035f0361e..ff0baccd76 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -29,6 +29,8 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
raise RuntimeError
when "/method_not_allowed"
raise ActionController::MethodNotAllowed
+ when "/unknown_http_method"
+ raise ActionController::UnknownHttpMethod
when "/not_implemented"
raise ActionController::NotImplemented
when "/unprocessable_entity"
@@ -113,6 +115,10 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_response 405
assert_match(/ActionController::MethodNotAllowed/, body)
+ get "/unknown_http_method", {}, {'action_dispatch.show_exceptions' => true}
+ assert_response 405
+ assert_match(/ActionController::UnknownHttpMethod/, body)
+
get "/bad_request", {}, {'action_dispatch.show_exceptions' => true}
assert_response 400
assert_match(/ActionController::BadRequest/, body)
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 29703dd5b1..5b42ca0f21 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -1124,6 +1124,35 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal "Not Found", @response.body
end
+ def test_resources_with_format_false_from_scope
+ draw do
+ scope format: false do
+ resources :posts
+ resource :user
+ end
+ end
+
+ get "/posts"
+ assert_response :success
+ assert_equal "posts#index", @response.body
+ assert_equal "/posts", posts_path
+
+ get "/posts.html"
+ assert_response :not_found
+ assert_equal "Not Found", @response.body
+ assert_equal "/posts?format=html", posts_path(format: "html")
+
+ get "/user"
+ assert_response :success
+ assert_equal "users#show", @response.body
+ assert_equal "/user", user_path
+
+ get "/user.html"
+ assert_response :not_found
+ assert_equal "Not Found", @response.body
+ assert_equal "/user?format=html", user_path(format: "html")
+ end
+
def test_index
draw do
get '/info' => 'projects#info', :as => 'info'
@@ -3322,6 +3351,10 @@ class TestUrlConstraints < ActionDispatch::IntegrationTest
end
get '/' => ok, :as => :alternate_root, :constraints => { :port => 8080 }
+
+ get '/search' => ok, :constraints => { :subdomain => false }
+
+ get '/logs' => ok, :constraints => { :subdomain => true }
end
end
@@ -3348,6 +3381,24 @@ class TestUrlConstraints < ActionDispatch::IntegrationTest
get 'http://www.example.com:8080/'
assert_response :success
end
+
+ test "false constraint expressions check for absence of values" do
+ get 'http://example.com/search'
+ assert_response :success
+ assert_equal 'http://example.com/search', search_url
+
+ get 'http://api.example.com/search'
+ assert_response :not_found
+ end
+
+ test "true constraint expressions check for presence of values" do
+ get 'http://api.example.com/logs'
+ assert_response :success
+ assert_equal 'http://api.example.com/logs', logs_url
+
+ get 'http://example.com/logs'
+ assert_response :not_found
+ end
end
class TestInvalidUrls < ActionDispatch::IntegrationTest
diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb
index 45f8fc11b3..38bd234f37 100644
--- a/actionpack/test/dispatch/show_exceptions_test.rb
+++ b/actionpack/test/dispatch/show_exceptions_test.rb
@@ -8,8 +8,12 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
case req.path
when "/not_found"
raise AbstractController::ActionNotFound
+ when "/bad_params"
+ raise ActionDispatch::ParamsParser::ParseError.new("", StandardError.new)
when "/method_not_allowed"
raise ActionController::MethodNotAllowed
+ when "/unknown_http_method"
+ raise ActionController::UnknownHttpMethod
when "/not_found_original_exception"
raise ActionView::Template::Error.new('template', AbstractController::ActionNotFound.new)
else
@@ -33,6 +37,10 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
get "/", {}, {'action_dispatch.show_exceptions' => true}
assert_response 500
assert_equal "500 error fixture\n", body
+
+ get "/bad_params", {}, {'action_dispatch.show_exceptions' => true}
+ assert_response 400
+ assert_equal "400 error fixture\n", body
get "/not_found", {}, {'action_dispatch.show_exceptions' => true}
assert_response 404
@@ -41,6 +49,10 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true}
assert_response 405
assert_equal "", body
+
+ get "/unknown_http_method", {}, {'action_dispatch.show_exceptions' => true}
+ assert_response 405
+ assert_equal "", body
end
test "localize rescue error page" do
diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb
index 4123529092..f919592d24 100644
--- a/actionpack/test/dispatch/url_generation_test.rb
+++ b/actionpack/test/dispatch/url_generation_test.rb
@@ -56,6 +56,47 @@ module TestUrlGeneration
test "formatting host when protocol is present" do
assert_equal "http://www.example.com/foo", foo_url(host: "httpz://www.example.com", protocol: "http://")
end
+
+ test "default ports are removed from the host" do
+ assert_equal "http://www.example.com/foo", foo_url(host: "www.example.com:80", protocol: "http://")
+ assert_equal "https://www.example.com/foo", foo_url(host: "www.example.com:443", protocol: "https://")
+ end
+
+ test "port is extracted from the host" do
+ assert_equal "http://www.example.com:8080/foo", foo_url(host: "www.example.com:8080", protocol: "http://")
+ end
+
+ test "port option overides the host" do
+ assert_equal "http://www.example.com:8080/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: 8080)
+ end
+
+ test "port option disables the host when set to nil" do
+ assert_equal "http://www.example.com/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: nil)
+ end
+
+ test "port option disables the host when set to false" do
+ assert_equal "http://www.example.com/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: false)
+ end
+
+ test "keep subdomain when key is true" do
+ assert_equal "http://www.example.com/foo", foo_url(subdomain: true)
+ end
+
+ test "keep subdomain when key is missing" do
+ assert_equal "http://www.example.com/foo", foo_url
+ end
+
+ test "omit subdomain when key is nil" do
+ assert_equal "http://example.com/foo", foo_url(subdomain: nil)
+ end
+
+ test "omit subdomain when key is false" do
+ assert_equal "http://example.com/foo", foo_url(subdomain: false)
+ end
+
+ test "omit subdomain when key is blank" do
+ assert_equal "http://example.com/foo", foo_url(subdomain: "")
+ end
end
end
diff --git a/actionpack/test/fixtures/public/400.html b/actionpack/test/fixtures/public/400.html
new file mode 100644
index 0000000000..03be6bedaf
--- /dev/null
+++ b/actionpack/test/fixtures/public/400.html
@@ -0,0 +1 @@
+400 error fixture
diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb
index 94ae8549f7..1715902927 100644
--- a/actionpack/test/template/form_options_helper_test.rb
+++ b/actionpack/test/template/form_options_helper_test.rb
@@ -100,6 +100,13 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_collection_options_with_element_attributes
+ assert_dom_equal(
+ "<option value=\"USA\" class=\"bold\">USA</option>",
+ options_from_collection_for_select([[ "USA", "USA", { :class => 'bold' } ]], :first, :second)
+ )
+ end
+
def test_string_options_for_select
options = "<option value=\"Denmark\">Denmark</option><option value=\"USA\">USA</option><option value=\"Sweden\">Sweden</option>"
assert_dom_equal(
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 2237d747be..81f3391fcd 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -29,14 +29,6 @@ module RenderTestCases
assert_equal "Hello world!", @view.render(:file => "test/hello_world")
end
- def test_render_file_not_using_full_path
- assert_equal "Hello world!", @view.render(:file => "test/hello_world")
- end
-
- def test_render_file_without_specific_extension
- assert_equal "Hello world!", @view.render(:file => "test/hello_world")
- end
-
# Test if :formats, :locale etc. options are passed correctly to the resolvers.
def test_render_file_with_format
assert_match "<h1>No Comment</h1>", @view.render(:file => "comments/empty", :formats => [:html])