Commit ee1dd1e7 authored by Antonio Terceiro's avatar Antonio Terceiro

Imported Upstream version 4.1.8

parent f026fca4
* Attachments can be added while rendering the mail template.
Fixes #16974.
*Christian Felder*
## Rails 4.1.6 (September 11, 2014) ##
* Make ActionMailer::Previews methods class methods. Previously they were
......
......@@ -759,7 +759,6 @@ def _raise_error
def mail(headers = {}, &block)
return @_message if @_mail_was_called && headers.blank? && !block
@_mail_was_called = true
m = @_message
# At the beginning, do not consider class default for content_type
......@@ -787,6 +786,8 @@ def mail(headers = {}, &block)
# Render the templates and blocks
responses = collect_responses(headers, &block)
@_mail_was_called = true
create_parts_from_responses(m, responses)
# Setup content type, reapply charset and handle parts order
......
......@@ -7,7 +7,7 @@ def self.gem_version
module VERSION
MAJOR = 4
MINOR = 1
TINY = 7
TINY = 8
PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
......
......@@ -29,7 +29,7 @@ def message
# Access the message attachments list.
def attachments
@_message.attachments
mailer.attachments
end
# Returns +text+ wrapped at +len+ columns and indented +indent+ spaces.
......
......@@ -246,6 +246,19 @@ def welcome
assert_match(/Can't add attachments after `mail` was called./, e.message)
end
test "adding inline attachments while rendering mail works" do
class LateInlineAttachmentMailer < ActionMailer::Base
def on_render
mail from: "welcome@example.com", to: "to@example.com"
end
end
mail = LateInlineAttachmentMailer.on_render
assert_equal ["image/jpeg; filename=controller_attachments.jpg",
"image/jpeg; filename=attachments.jpg"], mail.attachments.inline.map {|a| a['Content-Type'].to_s }
end
test "accessing attachments works after mail was called" do
class LateAttachmentAccessorMailer < ActionMailer::Base
def welcome
......
<h1>Adding an inline image while rendering</h1>
<% controller.attachments.inline["controller_attachments.jpg"] = 'via controller.attachments.inline' %>
<%= image_tag attachments['controller_attachments.jpg'].url %>
<% attachments.inline["attachments.jpg"] = 'via attachments.inline' %>
<%= image_tag attachments['attachments.jpg'].url %>
* Fix regression where path was getting overwritten when route anchor was false, and X-Cascade pass
fixes #17035.
*arthurnn*
* Fix a bug where malformed query strings lead to 500.
fixes #11502.
*Yuki Nishijima*
## Rails 4.1.6 (September 11, 2014) ##
* Prepend a JS comment to JSONP callbacks. Addresses CVE-2014-4671
......
......@@ -315,7 +315,7 @@ def parse_query(qs)
private
def check_method(name)
HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS[0...-1].join(', ')}, and #{HTTP_METHODS[-1]}")
name
end
end
......
......@@ -34,7 +34,7 @@ def generate(type, name, options, recall = {}, parameterize = nil)
end
message = "No route matches #{Hash[constraints.sort].inspect}"
message << " missing required keys: #{missing_keys.sort.inspect}" if name
message << " missing required keys: #{missing_keys.sort.inspect}" unless missing_keys.empty?
raise ActionController::UrlGenerationError, message
end
......
......@@ -63,9 +63,9 @@ def call(env)
unless route.path.anchored
env['SCRIPT_NAME'] = (script_name.to_s + match.to_s).chomp('/')
path_info = match.post_match
env['PATH_INFO'] = path_info
env['PATH_INFO'] = "/" + path_info unless path_info.start_with? "/"
matched_path = match.post_match
env['PATH_INFO'] = matched_path
env['PATH_INFO'] = "/" + matched_path unless matched_path.start_with? "/"
end
env[@params_key] = (set_params || {}).merge parameters
......
......@@ -6,16 +6,17 @@ class ExceptionWrapper
cattr_accessor :rescue_responses
@@rescue_responses = Hash.new(:internal_server_error)
@@rescue_responses.merge!(
'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
'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,
'ActionController::InvalidCrossOriginRequest' => :unprocessable_entity,
'ActionDispatch::ParamsParser::ParseError' => :bad_request,
'ActionController::BadRequest' => :bad_request,
'ActionController::ParameterMissing' => :bad_request
)
cattr_accessor :rescue_templates
......
......@@ -9,8 +9,12 @@ def initialize(public_path)
def call(env)
status = env["PATH_INFO"][1..-1]
request = ActionDispatch::Request.new(env)
content_type = request.formats.first
body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status.to_i, Rack::Utils::HTTP_STATUS_CODES[500]) }
content_type = begin
request.formats.first
rescue ActionController::BadRequest
Mime::HTML
end
render(status, content_type, body)
end
......
......@@ -19,7 +19,7 @@ def match?(path)
paths = "#{full_path}#{ext}"
matches = Dir[paths]
match = matches.detect { |m| File.file?(m) }
match = matches.detect { |m| File.file?(m) && File.readable?(m) }
if match
match.sub!(@compiled_root, '')
::Rack::Utils.escape(match)
......@@ -42,7 +42,7 @@ def unescape_path(path)
end
def escape_glob_chars(path)
path.gsub(/[*?{}\[\]]/, "\\\\\\&")
path.gsub(/[*?{}\[\]\\]/, "\\\\\\&")
end
private
......
......@@ -38,7 +38,7 @@ module RoutingAssertions
# # Test a custom route
# assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
def assert_recognizes(expected_options, path, extras={}, msg=nil)
request = recognized_request_for(path, extras)
request = recognized_request_for(path, extras, msg)
expected_options = expected_options.clone
......@@ -69,9 +69,9 @@ def assert_recognizes(expected_options, path, extras={}, msg=nil)
#
# # Asserts that the generated route gives us our custom route
# assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" }
def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)
def assert_generates(expected_path, options, defaults={}, extras={}, message=nil)
if expected_path =~ %r{://}
fail_on(URI::InvalidURIError) do
fail_on(URI::InvalidURIError, message) do
uri = URI.parse(expected_path)
expected_path = uri.path.to_s.empty? ? "/" : uri.path
end
......@@ -174,7 +174,7 @@ def method_missing(selector, *args, &block)
private
# Recognizes the route for a given path.
def recognized_request_for(path, extras = {})
def recognized_request_for(path, extras = {}, msg)
if path.is_a?(Hash)
method = path[:method]
path = path[:path]
......@@ -186,7 +186,7 @@ def recognized_request_for(path, extras = {})
request = ActionController::TestRequest.new
if path =~ %r{://}
fail_on(URI::InvalidURIError) do
fail_on(URI::InvalidURIError, msg) do
uri = URI.parse(path)
request.env["rack.url_scheme"] = uri.scheme || "http"
request.host = uri.host if uri.host
......@@ -200,7 +200,7 @@ def recognized_request_for(path, extras = {})
request.request_method = method if method
params = fail_on(ActionController::RoutingError) do
params = fail_on(ActionController::RoutingError, msg) do
@routes.recognize_path(path, { :method => method, :extras => extras })
end
request.path_parameters = params.with_indifferent_access
......@@ -208,10 +208,10 @@ def recognized_request_for(path, extras = {})
request
end
def fail_on(exception_class)
def fail_on(exception_class, message)
yield
rescue exception_class => e
raise Minitest::Assertion, e.message
raise Minitest::Assertion, message || e.message
end
end
end
......
......@@ -7,7 +7,7 @@ def self.gem_version
module VERSION
MAJOR = 4
MINOR = 1
TINY = 7
TINY = 8
PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
......
......@@ -615,6 +615,8 @@ def self.call(*)
get 'bar', :to => 'application_integration_test/test#index', :as => :bar
mount MountedApp => '/mounted', :as => "mounted"
get 'fooz' => proc { |env| [ 200, {'X-Cascade' => 'pass'}, [ "omg" ] ] }, anchor: false
get 'fooz', :to => 'application_integration_test/test#index'
end
def app
......@@ -631,6 +633,12 @@ def app
assert_equal '/mounted/baz', mounted.baz_path
end
test "path after cascade pass" do
get '/fooz'
assert_equal 'index', response.body
assert_equal '/fooz', path
end
test "route helpers after controller access" do
get '/'
assert_equal '/', empty_string_path
......
......@@ -459,6 +459,22 @@ def url_for(options = {})
end
end
test "exception on invalid HTTP method unaffected by I18n settings" do
old_locales = I18n.available_locales
old_enforce = I18n.config.enforce_available_locales
begin
I18n.available_locales = [:nl]
I18n.config.enforce_available_locales = true
assert_raise(ActionController::UnknownHttpMethod) do
stub_request('REQUEST_METHOD' => '_RANDOM_METHOD').method
end
ensure
I18n.available_locales = old_locales
I18n.config.enforce_available_locales = old_enforce
end
end
test "post masquerading as patch" do
request = stub_request 'REQUEST_METHOD' => 'PATCH', "rack.methodoverride.original_method" => "POST"
assert_equal "POST", request.method
......
......@@ -74,10 +74,26 @@ def test_assert_recognizes_with_query_constraint
assert_recognizes({ :controller => 'query_articles', :action => 'index', :use_query => 'true' }, '/query/articles', { :use_query => 'true' })
end
def test_assert_recognizes_raises_message
err = assert_raise(Assertion) do
assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'http://test.host/secure/articles', {}, "This is a really bad msg")
end
assert_match err.message, "This is a really bad msg"
end
def test_assert_routing
assert_routing('/articles', :controller => 'articles', :action => 'index')
end
def test_assert_routing_raises_message
err = assert_raise(Assertion) do
assert_routing('/thisIsNotARoute', { :controller => 'articles', :action => 'edit', :id => '1' }, { :id => '1' }, {}, "This is a really bad msg")
end
assert_match err.message, "This is a really bad msg"
end
def test_assert_routing_with_defaults
assert_routing('/articles/1/edit', { :controller => 'articles', :action => 'edit', :id => '1' }, { :id => '1' })
end
......
......@@ -8,7 +8,7 @@ def call(env)
case req.path
when "/not_found"
raise AbstractController::ActionNotFound
when "/bad_params"
when "/bad_params", "/bad_params?x[y]=1&x[y][][w]=2"
raise ActionDispatch::ParamsParser::ParseError.new("", StandardError.new)
when "/method_not_allowed"
raise ActionController::MethodNotAllowed
......@@ -53,6 +53,12 @@ def call(env)
get "/unknown_http_method", {}, {'action_dispatch.show_exceptions' => true}
assert_response 405
assert_equal "", body
# Use #post instead of #get as Rack::Test::Session parses
# a query string before ActionDispatch::Request does it.
post "/bad_params?x[y]=1&x[y][][w]=2", {}, {'action_dispatch.show_exceptions' => true}
assert_response 400
assert_equal "400 error fixture\n", body
end
test "localize rescue error page" do
......
# encoding: utf-8
require 'abstract_unit'
require 'fileutils'
require 'rbconfig'
module StaticTests
......@@ -164,6 +165,46 @@ def public_path
include StaticTests
def test_custom_handler_called_when_file_is_not_readable
filename = 'unreadable.html.erb'
target = File.join(@root, filename)
FileUtils.touch target
File.chmod 0200, target
assert File.exist? target
assert !File.readable?(target)
path = "/#{filename}"
env = {
"REQUEST_METHOD"=>"GET",
"REQUEST_PATH"=> path,
"PATH_INFO"=> path,
"REQUEST_URI"=> path,
"HTTP_VERSION"=>"HTTP/1.1",
"SERVER_NAME"=>"localhost",
"SERVER_PORT"=>"8080",
"QUERY_STRING"=>""
}
assert_equal(DummyApp.call(nil), @app.call(env))
ensure
File.unlink target
end
def test_custom_handler_called_when_file_is_outside_root_backslash
filename = 'shared.html.erb'
assert File.exist?(File.join(@root, '..', filename))
path = "/%5C..%2F#{filename}"
env = {
"REQUEST_METHOD"=>"GET",
"REQUEST_PATH"=> path,
"PATH_INFO"=> path,
"REQUEST_URI"=> path,
"HTTP_VERSION"=>"HTTP/1.1",
"SERVER_NAME"=>"localhost",
"SERVER_PORT"=>"8080",
"QUERY_STRING"=>""
}
assert_equal(DummyApp.call(nil), @app.call(env))
end
def test_custom_handler_called_when_file_is_outside_root
filename = 'shared.html.erb'
assert File.exist?(File.join(@root, '..', filename))
......
......@@ -205,6 +205,16 @@ def test_knows_what_parts_are_missing_from_named_route
assert_match(/missing required keys: \[:id\]/, error.message)
end
def test_does_not_include_missing_keys_message
route_name = "gorby_thunderhorse"
error = assert_raises(ActionController::UrlGenerationError) do
@formatter.generate(route_name, { }, { })
end
assert_no_match(/missing required keys: \[\]/, error.message)
end
def test_X_Cascade
add_routes @router, [ "/messages(.:format)" ]
resp = @router.call({ 'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/lol' })
......
* Update `select_tag` to work correctly with `:include_blank` option passing a string.
Fixes #16483.
*Frank Groeneveld*
## Rails 4.1.6 (September 11, 2014) ##
* Fix that render layout: 'messages/layout' should also be added to the dependency tracker tree.
......
......@@ -7,7 +7,7 @@ def self.gem_version
module VERSION
MAJOR = 4
MINOR = 1
TINY = 7
TINY = 8
PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
......
......@@ -35,10 +35,10 @@ module FormTagHelper
# This is helpful when you're fragment-caching the form. Remote forms get the
# authenticity token from the <tt>meta</tt> tag, so embedding is unnecessary unless you
# support browsers without JavaScript.
# * A list of parameters to feed to the URL the form will be posted to.
# * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the
# submit behavior. By default this behavior is an ajax submit.
# * <tt>:enforce_utf8</tt> - If set to false, a hidden input with name utf8 is not output.
# * Any other key creates standard HTML attributes for the tag.
#
# ==== Examples
# form_tag('/posts')
......@@ -126,12 +126,18 @@ def select_tag(name, option_tags = nil, options = {})
option_tags ||= ""
html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
if options.delete(:include_blank)
option_tags = content_tag(:option, '', :value => '').safe_concat(option_tags)
if options.include?(:include_blank)
include_blank = options.delete(:include_blank)
if include_blank == true
include_blank = ''
end
option_tags = content_tag(:option, include_blank, value: '').safe_concat(option_tags)
end
if prompt = options.delete(:prompt)
option_tags = content_tag(:option, prompt, :value => '').safe_concat(option_tags)
option_tags = content_tag(:option, prompt, value: '').safe_concat(option_tags)
end
content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
......
......@@ -34,7 +34,7 @@ module SanitizeHelper
# Add table tags to the default allowed tags
#
# class Application < Rails::Application
# config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
# config.action_view.sanitized_allowed_tags = ['table', 'tr', 'td']
# end
#
# Remove tags to the default allowed tags
......@@ -174,7 +174,7 @@ def white_list_sanitizer
# Adds valid HTML attributes that the +sanitize+ helper checks for URIs.
#
# class Application < Rails::Application
# config.action_view.sanitized_uri_attributes = 'lowsrc', 'target'
# config.action_view.sanitized_uri_attributes = ['lowsrc', 'target']
# end
#
def sanitized_uri_attributes=(attributes)
......@@ -184,7 +184,7 @@ def sanitized_uri_attributes=(attributes)
# Adds to the Set of 'bad' tags for the +sanitize+ helper.
#
# class Application < Rails::Application
# config.action_view.sanitized_bad_tags = 'embed', 'object'
# config.action_view.sanitized_bad_tags = ['embed', 'object']
# end
#
def sanitized_bad_tags=(attributes)
......@@ -194,7 +194,7 @@ def sanitized_bad_tags=(attributes)
# Adds to the Set of allowed tags for the +sanitize+ helper.
#
# class Application < Rails::Application
# config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
# config.action_view.sanitized_allowed_tags = ['table', 'tr', 'td']
# end
#
def sanitized_allowed_tags=(attributes)
......@@ -214,7 +214,7 @@ def sanitized_allowed_attributes=(attributes)
# Adds to the Set of allowed CSS properties for the #sanitize and +sanitize_css+ helpers.
#
# class Application < Rails::Application
# config.action_view.sanitized_allowed_css_properties = 'expression'
# config.action_view.sanitized_allowed_css_properties = ['expression']
# end
#
def sanitized_allowed_css_properties=(attributes)
......@@ -224,7 +224,7 @@ def sanitized_allowed_css_properties=(attributes)
# Adds to the Set of allowed CSS keywords for the +sanitize+ and +sanitize_css+ helpers.
#
# class Application < Rails::Application
# config.action_view.sanitized_allowed_css_keywords = 'expression'
# config.action_view.sanitized_allowed_css_keywords = ['expression']
# end
#
def sanitized_allowed_css_keywords=(attributes)
......@@ -234,7 +234,7 @@ def sanitized_allowed_css_keywords=(attributes)
# Adds to the Set of allowed shorthand CSS properties for the +sanitize+ and +sanitize_css+ helpers.
#
# class Application < Rails::Application
# config.action_view.sanitized_shorthand_css_properties = 'expression'
# config.action_view.sanitized_shorthand_css_properties = ['expression']
# end
#
def sanitized_shorthand_css_properties=(attributes)
......@@ -244,7 +244,7 @@ def sanitized_shorthand_css_properties=(attributes)
# Adds to the Set of allowed protocols for the +sanitize+ helper.
#
# class Application < Rails::Application
# config.action_view.sanitized_allowed_protocols = 'ssh', 'feed'
# config.action_view.sanitized_allowed_protocols = ['ssh', 'feed']
# end
#
def sanitized_allowed_protocols=(attributes)
......
......@@ -25,7 +25,7 @@ def render
private
def value(object)
object.send @method_name if object
object.public_send @method_name if object
end
def value_before_type_cast(object)
......
......@@ -5,6 +5,7 @@ module ActionView
# = Action View Translation Helpers
module Helpers
module TranslationHelper
include TagHelper
# Delegates to <tt>I18n#translate</tt> but also performs three additional functions.
#
# First, it will ensure that any thrown +MissingTranslation+ messages will be turned
......
......@@ -1512,6 +1512,20 @@ def test_form_for_with_symbol_object_name
assert_dom_equal expected, output_buffer
end
def test_form_tags_do_not_call_private_properties_on_form_object
obj = Class.new do
private
def private_property
raise "This method should not be called."
end
end.new
form_for(obj, as: "other_name", url: '/', html: { id: "edit-other-name" }) do |f|
assert_raise(NoMethodError) { f.hidden_field(:private_property) }
end
end
def test_form_for_with_method_as_part_of_html_options
form_for(@post, url: '/', html: { id: 'create-post', method: :delete }) do |f|
concat f.text_field(:title)
......
......@@ -222,6 +222,12 @@ def test_select_tag_with_include_blank
assert_dom_equal expected, actual
end
def test_select_tag_with_include_blank_string
actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>".html_safe, include_blank: 'Choose'
expected = %(<select id="places" name="places"><option value="">Choose</option><option>Home</option><option>Work</option><option>Pub</option></select>)
assert_dom_equal expected, actual
end
def test_select_tag_with_prompt
actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>".html_safe, :prompt => "string"
expected = %(<select id="places" name="places"><option value="">string</option><option>Home</option><option>Work</option><option>Pub</option></select>)
......
require 'abstract_unit'
class TranslationHelperTest < ActiveSupport::TestCase
include ActionView::Helpers::TagHelper
include ActionView::Helpers::TranslationHelper
attr_reader :request, :view
......
......@@ -7,7 +7,7 @@ def self.gem_version
module VERSION
MAJOR = 4
MINOR = 1
TINY = 7
TINY = 8
PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
......
* Do not use `RENAME INDEX` syntax for MariaDB 10.0.
Fixes #15931.
*Jeff Browning*
* Allow included modules to override association methods.
Fixes #16684.
*Yves Senn*
* Schema loading rake tasks (like `db:schema:load` and `db:setup`) maintain
the database connection to the current environment.
Fixes #16757.
*Joshua Cody*, *Yves Senn*
* `db:purge` with MySQL respects `Rails.env`.
*Yves Senn*
* Fixed automatic maintaining test schema to properly handle sql structure
schema format.
Fixes #15394.
*Wojciech Wnętrzak*
* Fix has_many :through relation merging failing when dynamic conditions are
passed as a lambda with an arity of one.
Fixes #16128.
*Agis Anastasopoulos*
## Rails 4.1.6 (September 11, 2014) ##
* Fixed a regression where whitespaces were stripped from DISTINCT queries in
......
......@@ -15,7 +15,11 @@ def target_scope
scope = super
chain.drop(1).each do |reflection|
relation = reflection.klass.all
relation.merge!(reflection.scope) if reflection.scope
reflection_scope = reflection.scope
if reflection_scope && reflection_scope.arity.zero?
relation.merge!(reflection_scope)
end
scope.merge!(
relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
......
......@@ -29,7 +29,7 @@ def self.set_name_cache(name, value)
end
}