TLDR: always return an object that responds to the query methods from
request.format, and do not touch Mime::Type[] lookup to avoid bugs.
---
Long version:
The initial issue was about being able to do checks like
request.format.html? for request with an unknown format, where
request.format would be nil.
This is where the issue came from at first in #7837 and #8085
(merged in cba05887dc3b56a46a9fe2779b6b228880b49622), but the
implementation went down the path of adding this to the mime type
lookup logic.
This unfortunately introduced subtle bugs, for instance in the merged
commit a test related to send_file had to be changed to accomodate the
introduction of the NullType.
Later another bug was found in #13064, related to the content-type being
shown as #<Mime::NullType:...> for templates with localized extensions
but no format included. This one was fixed in #13133, merged in
43962d6ec50f918c9970bd3cd4b6ee5c7f7426ed.
Besides that, custom handlers were not receiving the proper template
formats anymore when passing through the rendering process, because of
the NullType addition. That was found while migrating an application
from 3.2 to 4.0 that uses the Markerb gem (a custom handler that
generates both text and html emails from a markdown template).
---
This changes the implementation moving away from returning this null
object from the mime lookup, and still fixes the initial issue where
request.format.zomg? would raise an exception for unknown formats due to
request.format being nil.
When a route is mounted inside a resources block, it's automatically
prefixed, so a following code:
resources :users do
mount Blog::Engine => '/blog'
end
will generate a user_blog path helper.
In order to access engine helpers, we also use "mounted_helpers", a list
of helpers associated with each mounted engine, so a path to blog's post
can be generated using user_blog.post_path(user, post).
The problem I'm fixing here is that mount used a raw :as option, without
taking nestings into account. As a result, blog was added to a route set
as a `user_blog`, but helper was generated for just `blog`.
This commit applies the proper logic for defining a helper for a mounted
engine nested in resources or resource block.
(closes#8533)
Before ec16ba75a5493b9da972eea08bae630eba35b62f,
ActionView::Helpers::TranslationHelper#translate has raised errors with
specifying options[:raise] to true.
This should work by this fix:
begin
t(:"translations.missing", raise: true)
rescue I18n::MissingTranslationData
p :hello!
end
By default, variants in the templates will be picked up if a variant is set
and there's a match. The format will be:
app/views/projects/show.html.erb
app/views/projects/show.html+tablet.erb
app/views/projects/show.html+phone.erb
If request.variant = :tablet is set, we'll automatically be rendering the
html+tablet template.
In the controller, we can also tailer to the variants with this syntax:
class ProjectsController < ActionController::Base
def show
respond_to do |format|
format.html do |html|
@stars = @project.stars
html.tablet { @notifications = @project.notifications }
html.phone { @chat_heads = @project.chat_heads }
end
format.js
format.atom
end
end
end
The variant itself is nil by default, but can be set in before filters, like
so:
class ApplicationController < ActionController::Base
before_action do
if request.user_agent =~ /iPad/
request.variant = :tablet
end
end
end
This is modeled loosely on custom mime types, but it's specifically not
intended to be used together. If you're going to make a custom mime type,
you don't need a variant. Variants are for variations on a single mime
types.
This PR fixes#13064 regression bug introduced by the #8085
Now in _process_format when the format is a Mime::NullType nothing is written in self.content_type.
In this way the method Response#assign_default_content_type_and_charset can
write the the default mime_type.
A path redirect may contain any and all parts of a url which have different
escaping rules for each part. This commit tries to escape each part correctly
by splitting the string into three chunks - path (which may also include a host),
query and fragment; then it applies the correct escape pattern to each part.
Whilst using `URI.parse` would be better, unfortunately the possible presence
of %{name} parameters in the path redirect string prevents us from using it so
we have to use a regular expression instead.
Fixes#13110.
Extract **notable changes**, **deprecations** and **removals** from
each CHANGELOG.
I tried to reference the commits and pull requests for new features
and deprecations.
In the process I also made some minor changes to the CHANGELOGS.
The 4_1_release_notes guide is declared WIP.
Mention it in the changelog and add a test checking for regressions.
Hash#fetch isn't adding the defaultly returned value.
However, in the session, saving it is the behavior we should expect.
See discussion in #12692
Example:
# application routes.rb
mount BlogEngine => '/blog'
# engine routes.rb
get '/admin' => redirect('admin/dashboard')
This now redirects to the path `/blog/admin/dashboard`, whereas before it
would've generated an invalid url because there would be no slash between
the host name and the path. It also allows redirects to work where the
application is deployed to a subdirectory of a website.
Fixes#7977
This fixes an issue where the respond_with worked directly with the given
options hash, so that if a user relied on it after calling respond_with,
the hash wouldn't be the same.
Fixes#12029
In some instances, `assert_redirected_to` assertion was returning an
incorrect and misleading failure message when the assertion failed.
This was due to a disconnect in how the assertion computes the redirect
string for the failure message and how `redirect_to` computes the
string that is actually used for redirection.
I made the `_compute_redirect_to_loaction` method used by `redirect_to`
public and call that from the method `assert_redirect_to` uses to
calculate the URL.
The reveals a new test failure due to the regex used by
`_compute_redirect_to_location` allow `_` in the URL scheme.
The parameters are rendered as hidden form fields within the generated
form. This is useful for when a record has multiple buttons associated
with it, each of which target the same controller method, but which
need to submit different attributes.
:only and :except options for controller filters are now added before
:if and :unless. This prevents running :if and :unless procs when not
on the specified. Closes#11786.
Fix an issue where Journey was failing to clear the named routes hash when the
routes were reloaded and since it doesn't overwrite existing routes then if a
route changed but wasn't renamed it kept the old definition. This was being
masked by the optimised url helpers so it only became apparent when passing an
options hash to the url helper.
When generating an unnamed url (i.e. using `url_for` with an options
hash) we should skip anything other than standard Rails routes otherwise
it will match the first mounted application or redirect and generate a
url with query parameters rather than raising an error if the options
hash doesn't match any defined routes.
Fixes#8018
When helper try to require missing file rails will throw exception about
missing helper.
# app/helpers/my_helper.rb
require 'missing'
module MyHelper
end
And when we try do load helper
class ApplicationController
helper :my
end
Rails will throw exception. This is wrong because there is a helper
file.
Missing helper file helpers/my_helper.rb
Now when helper try to require non-existed file rails will throw proper
exception.
No such file to load -- missing
In order to get raw_post to be not empty after
ParamsParser#parse_formatted_parameters,
added rewinding of body stream input on parsing json params.
Closes#11345
Merge `:action` from routing scope and assign endpoint if both `:controller`
and `:action` are present. The endpoint assignment only occurs if there is
no `:to` present in the options hash so should only affect routes using the
shorthand syntax (i.e. endpoint is inferred from the the path).
Fixes#9856
Previously when app was mounted as following:
class Foo
def call(env)
[200, {}, [env['PATH_INFO']]]
end
end
RackMountRailsBug::Application.routes.draw do
mount RackTest.new => "/foo"
end
trailing slash was removed from PATH_INFO. For example requesting
GET /foo/bar/
on routes defined above would result in a response containing "/foo/bar"
instead of "/foo/bar/".
This commit fixes the issue.
(closes#3215)
This reverts commit b4239622afc4f3f73808fd0c97512f3a534e07dd, reversing
changes made to f99ce3c188f5dde57e2ff63e6a22363c62f0a4cd.
Reason: This broke the build
https://travis-ci.org/rails/rails/jobs/6629894
This commit adds support for passing additional url options along
with a :status option and any of the flash-related options to
`redirect_to` (i.e. :flash, :alert & :notice).
Closes#7570.
ActionView::Digestor now passes arguments correctly to
LookupContext::find method. This makes cache digests
respect the format option correctly.
FixtureFinder in tests also changed to reflect this.
The `force_ssl` command now builds the redirect url from `request.fullpath`.
This ensures that the format is maintained and it doesn't redirect to a route
that has the same parameters but is defined earlier in `routes.rb`. Also any
optional segments are maintained.
Fixes#7528.
Fixes#9061.
Fixes#10305.
If a file field tag is passed the multiple option, it is turned into an
array field (appending "[]"), but if the file field is passed an
explicit name as an option, leave the name alone (do not append "[]").
Fixes#9830
Add a note about getting the "no layout" behavior by returning "false"
to make it easier for people that might need to change their code.
Related to #8458. [ci skip]
* This unused variable is already removed from the code here. d18e8b1a3839c5c214e96c7e37e0d86febe15f99
* So removing it from CHANGELOG to be consistent with code
When setting the layout either by referencing a method or supplying a
Proc there is no way to fall back to the default lookup behavior if
desired. This patch allows fallback to the layout lookup behavior when
returning nil from the proc or method.
If the host in `default_url_options` is accidentally set with a protocol such as
```
host: "http://example.com"
```
then the generated url will have the protocol twice `http://http://example.com` which is not what the user intended. Likely they wanted to define a host `host: "example.com"` and a `protocol: "http://"` but did not know the convention.
This may not the most common problem, but when it happens it can go undetected for a while. I accidentally added `http://` out of habit recently only to find all the links in my emails were broken after deploying a demo site to production. Rather than allow this accident go undetected, we can fix the problem in line by properly setting the protocol and host.
I was able to find this related question on stack overflow: http://stackoverflow.com/questions/5878329/rails-3-devise-how-do-i-make-the-email-confirmation-links-use-secure-https-n where the answer was highly upvoted.
This is based off of work in #7415 cc/ @pixeltrix
ATP Action Mailer and Action Pack
The env hash passed to `Http::Headers#new` must be in env format.
Also be aware that the passed hash is modified directly.
docs and test-cases for setting headers/env in functional tests.
Follow up to #9700.
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][]" ...>
Closes#9466.
Passing `format: true` used to override the constraints: { format: /json/ }
with `/.+/`. This patch only sets the format if there is no constraint present.
Closes#7554.
This patch determines the `controller#action` directly
in the `match` method when the shorthand syntax is used.
this prevents problems with namespaces and scopes.
This seemed to be introduced in master by
9dd64f2e0c1b3ce85b503b0f81c50c93f89ffbcd, so there's no need to add a
changelog entry for fixing it.
[ci skip]
This reverts commit bb842e8d2111e50b21a14b8bd6d89371a4b9cd68, reversing
changes made to 40c287c7983c20c498f6a8a2ea49e9a6455347f7.
This was causing issues in one of our apps we just upgraded.
ActionController::RoutingError: No route matches [GET]
"/images/favicon.ico"
favicon_link_tag now returns '/images/favicon.ico' and in 3.2 returned
'/favicon.ico'
Browsers by default look for favicon.ico in the root directory
Conflicts:
actionpack/CHANGELOG.md
actionpack/lib/action_view/helpers/asset_tag_helper.rb
Previous implementation of time_zone_options_for_select did not dup the
ActiveSupport::TimeZone.all array. When :priority_zones were provided
the method would reject! the zones from the memoized TimeZones array
thus affecting future requests to the server. Essentially whatever
zones were specified as :priority_zones would show up for the first
request but then disappear from the time zone options on future
requests.
Print a message in both `rake routes` and at GET "/rails/info/routes"
that lets you know you have no routes defined, as well as linking to the
Rails Guide on the topic.
Currently, the img_alt method in ActionView keeps underscores
in the alt attribute. Because underscores are pronounced in
Apple's VoiceOver Utility, this has serious implications for
accessibility. This patch makes underscored or hyphenated file
names (both common in projects) read more naturally in screen
readers by replacing them with spaces. See method documentation
for details.
Added documentation to image_alt method
The current implementation only works correctly if you supply the `:controller`
with directory notation (eg. `:controller => 'admin/posts'`).
The ruby constant notation (eg. `:controller => 'Admin::Posts`) leads to unexpected problems with `url_for`.
This patch prints a warning for every non supported `:controller` option. I also added documentation how
to work with namespaced controllers. The warning links to that documentation in the rails guide.
previously when a partial was placed inside a directory
(eg. '/dir/_partial'), `assert_template` did not replace
the '_' prefix when looking through rendered tempaltes,
which resulted in an error.
I modified it to replace both, the leading '_' and the last '_'
after a '/'.
When debugging routes ,it can sometimes be difficult to understand exactly how the paths are matched. This PR adds a JS based path matching widget to the `/rails/info/routes` output. You can enter in a path, and it will tell you which of the routes that path matches, while preserving order (top match wins).
The matching widget in action:
![](http://f.cl.ly/items/3A2F0v2m3m1Z1p3P3O3k/path-match.gif)
Prior to this PR the only way to check matching paths is via mental math, or typing in a path in the url bar and seeing where it goes. This feature will be an invaluable debugging tool by dramatically decreasing the time needed to check a path match.
ATP actionpack
This commit changes 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.
Closes#8814
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.
A declarative API for specifying dependencies that affect template
cache digest computation. In your controller, specify any of said
dependencies:
view_cache_dependency { "phone" if using_phone? }
When the block is evaluated, the resulting value is included in the
cache digest calculation, allowing you to generate different digests
for effectively the same template. (Mostly useful if you're mucking
with template load paths.)
Previously rendering a partial without giving :object or :collection
would generate a local variable with the partial name by default.
This was noticed due to warnings in Ruby 2.0 of not used variables,
which turned out to be the generation of not used variables inside
partials that do not contain objects related to them.
Proxy servers add X-Forwarded-For headers, resulting in a list of IPs. We
remove trusted IP values, and then take the last given value, assuming that
it is the most likely to be the correct, unfaked value. See [1] for a very
thorough discussion of why that is the best option we have at the moment.
[1]: http://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection/Fixes#7979
If a request has an unknown format, the methods html?, xml?, json? ...etc
not raise an Exception.
This patch add a class Mime::NullType, that is returned when request.format is unknown
and it responds false to the methods that ends with '?' and true to 'nil?'.
It refers to #7837, this issue is considered a improvement not a bug.
Move the Journey code underneath the ActionDispatch namespace so
that we don't pollute the global namespace with names that may
be used for models.
Fixesrails/journey#49.
Removes support for :encode, :replace_at, and :replace_dot
options from the mail_to helper. Support for these options
has been extracted to the 'actionview-encoded_mail_to' gem.
cache_if(condition, option, &block) and cache_unless(condition, option, &block).
In the PR #8371 was introduced conditional options :if and :unless in
the cache method.
Example:
<%= cache @model, if: some_condition(@model) do %>
...
<%end%>
This is a good feature but *cache_if* and and *cache_unless*
are more concise and close to the standard of rails view helpers
(ex: link_to_if and link_to_unless).
Example:
<%= cache_if condition, @model do %>
...
<%end%>
This doesn't actually remove old url helper methods as they are
defined in a different module.
This reverts commit 96bcef947bf713b7d9fc88f26dff69f568111262.
Conflicts:
actionpack/CHANGELOG.md
If env['RAW_POST_DATA'] is nil, #raw_post will attempt to set it to
the result of #body (which will return env['rack.input'] if
env['RAW_POST_DATA'] is nil). #raw_post will then attempt to rewind
the result of another call to #body. Since env['RAW_POST_DATA'] has
already been set, the result of #body is not env['rack.input'] anymore.
This causes env['rack.input'] to never be rewound.
Such request can happen on Internet Explorer. When we redirect
after multipart form submission, the request type is changed
to GET, but Content-Type is preserved as multipart. GET request
cannot have multipart body and that caused Rails to fail.
It's similar fix to Rack's one:
8025a4ae94/lib/rack/request.rb (L224)
This commit inverts the precedence in ActionDispatch::Static so that
dynamic content will be served before static content. This is so that
precompiled assets do not inadvertently get included when running in
development mode - it should have no effect in production where static
files are usually handled by the web server.
Closes#6421
be ignored. A regular expression constraint gets overwritten when the
routes.rb file is processed. Changed the overwriting to an ||= instead
of an = assignment.