aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actioncable/MIT-LICENSE2
-rw-r--r--actioncable/lib/action_cable.rb2
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/connection.coffee3
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee5
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/consumer.coffee6
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee14
-rw-r--r--actionmailer/MIT-LICENSE2
-rw-r--r--actionmailer/lib/action_mailer.rb2
-rw-r--r--actionpack/CHANGELOG.md12
-rw-r--r--actionpack/MIT-LICENSE2
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb2
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb34
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb12
-rw-r--r--actionpack/lib/action_dispatch.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb20
-rw-r--r--actionpack/lib/action_pack.rb2
-rw-r--r--actionpack/test/abstract_unit.rb6
-rw-r--r--actionpack/test/controller/metal/renderers_test.rb42
-rw-r--r--actionpack/test/controller/parameters/parameters_permit_test.rb8
-rw-r--r--actionpack/test/dispatch/ssl_test.rb45
-rw-r--r--actionview/CHANGELOG.md8
-rw-r--r--actionview/MIT-LICENSE2
-rw-r--r--actionview/lib/action_view.rb2
-rw-r--r--actionview/lib/action_view/helpers/tags/collection_check_boxes.rb4
-rw-r--r--actionview/lib/action_view/helpers/tags/collection_helpers.rb8
-rw-r--r--actionview/test/template/form_collections_helper_test.rb12
-rw-r--r--actionview/test/template/form_helper_test.rb36
-rw-r--r--activejob/MIT-LICENSE2
-rw-r--r--activejob/lib/active_job.rb2
-rw-r--r--activemodel/MIT-LICENSE2
-rw-r--r--activemodel/lib/active_model.rb2
-rw-r--r--activerecord/MIT-LICENSE4
-rw-r--r--activerecord/lib/active_record.rb2
-rw-r--r--activerecord/lib/active_record/autosave_association.rb21
-rw-r--r--activerecord/lib/active_record/enum.rb2
-rw-r--r--activerecord/lib/active_record/migration.rb4
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb4
-rw-r--r--activerecord/lib/active_record/sanitization.rb2
-rw-r--r--activerecord/test/cases/adapters/postgresql/uuid_test.rb9
-rw-r--r--activerecord/test/cases/autosave_association_test.rb47
-rw-r--r--activerecord/test/cases/migration/rename_table_test.rb2
-rw-r--r--activesupport/CHANGELOG.md5
-rw-r--r--activesupport/MIT-LICENSE4
-rw-r--r--activesupport/lib/active_support.rb2
-rw-r--r--activesupport/lib/active_support/multibyte/unicode.rb51
-rw-r--r--activesupport/test/multibyte_chars_test.rb32
-rw-r--r--activesupport/test/multibyte_grapheme_break_conformance.rb76
-rw-r--r--activesupport/test/multibyte_normalization_conformance.rb129
-rw-r--r--guides/source/initialization.md19
-rw-r--r--guides/source/testing.md2
-rw-r--r--railties/MIT-LICENSE4
-rw-r--r--railties/lib/rails/application/default_middleware_stack.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee2
-rw-r--r--railties/lib/rails/generators/rails/model/USAGE8
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/app/models/%namespaced_name%/application_record.rb.tt (renamed from railties/lib/rails/generators/rails/plugin/templates/app/models/application_record.rb.tt)0
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/app/models/.empty_directory0
-rw-r--r--railties/lib/rails/generators/rails/scaffold/USAGE2
-rw-r--r--railties/test/application/middleware/session_test.rb9
-rw-r--r--railties/test/generators/app_generator_test.rb7
60 files changed, 597 insertions, 159 deletions
diff --git a/actioncable/MIT-LICENSE b/actioncable/MIT-LICENSE
index a4910677eb..27a17cf41b 100644
--- a/actioncable/MIT-LICENSE
+++ b/actioncable/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2015 Basecamp, LLC
+Copyright (c) 2015-2016 Basecamp, LLC
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/actioncable/lib/action_cable.rb b/actioncable/lib/action_cable.rb
index f27698765c..97f485b32e 100644
--- a/actioncable/lib/action_cable.rb
+++ b/actioncable/lib/action_cable.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2015 Basecamp, LLC
+# Copyright (c) 2015-2016 Basecamp, LLC
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actioncable/lib/assets/javascripts/action_cable/connection.coffee b/actioncable/lib/assets/javascripts/action_cable/connection.coffee
index 2f69a9b26c..fbd7dbd35b 100644
--- a/actioncable/lib/assets/javascripts/action_cable/connection.coffee
+++ b/actioncable/lib/assets/javascripts/action_cable/connection.coffee
@@ -79,6 +79,3 @@ class ActionCable.Connection
return if @disconnected
@disconnected = true
@consumer.subscriptions.notifyAll("disconnected")
-
- toJSON: ->
- state: @getState()
diff --git a/actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee b/actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee
index b594802be1..99b9a1c6d5 100644
--- a/actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee
+++ b/actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee
@@ -69,11 +69,6 @@ class ActionCable.ConnectionMonitor
@consumer.connection.reopen()
, 200
- toJSON: ->
- interval = @getInterval()
- connectionIsStale = @connectionIsStale()
- {@startedAt, @stoppedAt, @pingedAt, @reconnectAttempts, connectionIsStale, interval}
-
now = ->
new Date().getTime()
diff --git a/actioncable/lib/assets/javascripts/action_cable/consumer.coffee b/actioncable/lib/assets/javascripts/action_cable/consumer.coffee
index 5cf8978d77..fcd8d0fb6c 100644
--- a/actioncable/lib/assets/javascripts/action_cable/consumer.coffee
+++ b/actioncable/lib/assets/javascripts/action_cable/consumer.coffee
@@ -23,9 +23,3 @@ class ActionCable.Consumer
send: (data) ->
@connection.send(data)
-
- inspect: ->
- JSON.stringify(this, null, 2)
-
- toJSON: ->
- {@url, @subscriptions, @connection, @connectionMonitor}
diff --git a/actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee b/actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee
index 0316f76a24..ae041ffa2b 100644
--- a/actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee
+++ b/actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee
@@ -9,7 +9,6 @@
class ActionCable.Subscriptions
constructor: (@consumer) ->
@subscriptions = []
- @history = []
create: (channelName, mixin) ->
channel = channelName
@@ -57,22 +56,9 @@ class ActionCable.Subscriptions
for subscription in subscriptions
subscription[callbackName]?(args...)
- if callbackName in ["initialized", "connected", "disconnected", "rejected"]
- {identifier} = subscription
- @record(notification: {identifier, callbackName, args})
-
sendCommand: (subscription, command) ->
{identifier} = subscription
if identifier is ActionCable.INTERNAL.identifiers.ping
@consumer.connection.isOpen()
else
@consumer.send({command, identifier})
-
- record: (data) ->
- data.time = new Date()
- @history = @history.slice(-19)
- @history.push(data)
-
- toJSON: ->
- history: @history
- identifiers: (subscription.identifier for subscription in @subscriptions)
diff --git a/actionmailer/MIT-LICENSE b/actionmailer/MIT-LICENSE
index 3ec7a617cf..8573eb1225 100644
--- a/actionmailer/MIT-LICENSE
+++ b/actionmailer/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2015 David Heinemeier Hansson
+Copyright (c) 2004-2016 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb
index 312dd1997c..55c017e338 100644
--- a/actionmailer/lib/action_mailer.rb
+++ b/actionmailer/lib/action_mailer.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2015 David Heinemeier Hansson
+# Copyright (c) 2004-2016 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 93f75ba635..ac767652b8 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,15 @@
+* Add tests and documentation for `ActionController::Renderers::use_renderers`.
+
+ *Benjamin Fleischer*
+
+* Fix `ActionController::Parameters#convert_parameters_to_hashes` to return filtered
+ or unfiltered values based on from where it is called, `to_h` or `to_unsafe_h`
+ respectively.
+
+ Fixes #22841
+
+ *Prathamesh Sonpatki*
+
* Add `ActionController::Parameters#include?`
*Justin Coyne*
diff --git a/actionpack/MIT-LICENSE b/actionpack/MIT-LICENSE
index 3ec7a617cf..8573eb1225 100644
--- a/actionpack/MIT-LICENSE
+++ b/actionpack/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2015 David Heinemeier Hansson
+Copyright (c) 2004-2016 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index d86a793e4c..f8e0d9cf6c 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -228,7 +228,7 @@ module ActionController
expires_in 100.years, public: public
yield if stale?(etag: "#{version}-#{request.fullpath}",
- last_modified: Time.parse('2011-01-01').utc,
+ last_modified: Time.new(2011, 1, 1).utc,
public: public)
end
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 22e0bb5955..1f77f9ecaa 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -26,6 +26,40 @@ module ActionController
end
module ClassMethods
+
+ # Adds, by name, a renderer or renderers to the +_renderers+ available
+ # to call within controller actions.
+ #
+ # It is useful when rendering from an <tt>ActionController::Metal</tt> controller or
+ # otherwise to add an available renderer proc to a specific controller.
+ #
+ # Both <tt>ActionController::Base</tt> and <tt>ActionController::API</tt>
+ # include <tt>ActionController::Renderers::All</tt>, making all renderers
+ # avaialable in the controller. See <tt>Renderers::RENDERERS</tt> and <tt>Renderers.add</tt>.
+ #
+ # Since <tt>ActionController::Metal</tt> controllers cannot render, the controller
+ # must include <tt>AbstractController::Rendering</tt>, <tt>ActionController::Rendering</tt>,
+ # and <tt>ActionController::Renderers</tt>, and have at lest one renderer.
+ #
+ # Rather than including <tt>ActionController::Renderers::All</tt> and including all renderers,
+ # you may specify which renderers to include by passing the renderer name or names to
+ # +use_renderers+. For example, a controller that includes only the <tt>:json</tt> renderer
+ # (+_render_with_renderer_json+) might look like:
+ #
+ # class MetalRenderingController < ActionController::Metal
+ # include AbstractController::Rendering
+ # include ActionController::Rendering
+ # include ActionController::Renderers
+ #
+ # use_renderers :json
+ #
+ # def show
+ # render json: record
+ # end
+ # end
+ #
+ # You must specify a +use_renderer+, else the +controller.renderer+ and
+ # +controller._renderers+ will be <tt>nil</tt>, and the action will fail.
def use_renderers(*args)
renderers = _renderers + args
self._renderers = renderers.freeze
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 7e2745c75a..4cd67a85cc 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -176,7 +176,7 @@ module ActionController
# safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
def to_h
if permitted?
- convert_parameters_to_hashes(@parameters)
+ convert_parameters_to_hashes(@parameters, :to_h)
else
slice(*self.class.always_permitted_parameters).permit!.to_h
end
@@ -186,7 +186,7 @@ module ActionController
# <tt>ActiveSupport::HashWithIndifferentAccess</tt> representation of this
# parameter.
def to_unsafe_h
- convert_parameters_to_hashes(@parameters)
+ convert_parameters_to_hashes(@parameters, :to_unsafe_h)
end
alias_method :to_unsafe_hash, :to_unsafe_h
@@ -595,16 +595,16 @@ module ActionController
end
end
- def convert_parameters_to_hashes(value)
+ def convert_parameters_to_hashes(value, using)
case value
when Array
- value.map { |v| convert_parameters_to_hashes(v) }
+ value.map { |v| convert_parameters_to_hashes(v, using) }
when Hash
value.transform_values do |v|
- convert_parameters_to_hashes(v)
+ convert_parameters_to_hashes(v, using)
end.with_indifferent_access
when Parameters
- value.to_h
+ value.send(using)
else
value
end
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index f6336c8c7a..7bc6575ccd 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2015 David Heinemeier Hansson
+# Copyright (c) 2004-2016 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 8f8f1bab8b..735b5939dd 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -4,16 +4,18 @@ module ActionDispatch
# requests:
#
# 1. TLS redirect: Permanently redirects http:// requests to https://
- # with the same URL host, path, etc. This is always enabled. Set
- # `config.ssl_options` to modify the destination URL
- # (e.g. `redirect: { host: "secure.widgets.com", port: 8080 }`)
+ # with the same URL host, path, etc. Enabled by default. Set `config.ssl_options`
+ # to modify the destination URL
+ # (e.g. `redirect: { host: "secure.widgets.com", port: 8080 }`), or set
+ # `redirect: false` to disable this feature.
#
# 2. Secure cookies: Sets the `secure` flag on cookies to tell browsers they
- # mustn't be sent along with http:// requests. This is always enabled.
+ # mustn't be sent along with http:// requests. Enabled by default. Set
+ # `config.ssl_options` with `secure_cookies: false` to disable this feature.
#
# 3. HTTP Strict Transport Security (HSTS): Tells the browser to remember
# this site as TLS-only and automatically redirect non-TLS requests.
- # Enabled by default. Pass `hsts: false` to disable.
+ # Enabled by default. Configure `config.ssl_options` with `hsts: false` to disable.
#
# Set `config.ssl_options` with `hsts: { … }` to configure HSTS:
# * `expires`: How long, in seconds, these settings will stick. Defaults to
@@ -41,7 +43,7 @@ module ActionDispatch
{ expires: HSTS_EXPIRES_IN, subdomains: false, preload: false }
end
- def initialize(app, redirect: {}, hsts: {}, **options)
+ def initialize(app, redirect: {}, hsts: {}, secure_cookies: true, **options)
@app = app
if options[:host] || options[:port]
@@ -54,6 +56,7 @@ module ActionDispatch
@redirect = redirect
end
+ @secure_cookies = secure_cookies
@hsts_header = build_hsts_header(normalize_hsts_options(hsts))
end
@@ -63,10 +66,11 @@ module ActionDispatch
if request.ssl?
@app.call(env).tap do |status, headers, body|
set_hsts_header! headers
- flag_cookies_as_secure! headers
+ flag_cookies_as_secure! headers if @secure_cookies
end
else
- redirect_to_https request
+ return redirect_to_https request if @redirect
+ @app.call(env)
end
end
diff --git a/actionpack/lib/action_pack.rb b/actionpack/lib/action_pack.rb
index f664dab620..941877d10d 100644
--- a/actionpack/lib/action_pack.rb
+++ b/actionpack/lib/action_pack.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2015 David Heinemeier Hansson
+# Copyright (c) 2004-2016 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index ef7aab72c6..604ba267d6 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -371,6 +371,12 @@ module RoutingTestHelpers
end
end
+class MetalRenderingController < ActionController::Metal
+ include AbstractController::Rendering
+ include ActionController::Rendering
+ include ActionController::Renderers
+end
+
class ResourcesController < ActionController::Base
def index() head :ok end
alias_method :show, :index
diff --git a/actionpack/test/controller/metal/renderers_test.rb b/actionpack/test/controller/metal/renderers_test.rb
new file mode 100644
index 0000000000..007866a559
--- /dev/null
+++ b/actionpack/test/controller/metal/renderers_test.rb
@@ -0,0 +1,42 @@
+require 'abstract_unit'
+require 'active_support/core_ext/hash/conversions'
+
+class MetalRenderingJsonController < MetalRenderingController
+ class Model
+ def to_json(options = {})
+ { a: 'b' }.to_json(options)
+ end
+
+ def to_xml(options = {})
+ { a: 'b' }.to_xml(options)
+ end
+ end
+
+ use_renderers :json
+
+ def one
+ render json: Model.new
+ end
+
+ def two
+ render xml: Model.new
+ end
+end
+
+class RenderersMetalTest < ActionController::TestCase
+ tests MetalRenderingJsonController
+
+ def test_render_json
+ get :one
+ assert_response :success
+ assert_equal({ a: 'b' }.to_json, @response.body)
+ assert_equal 'application/json', @response.content_type
+ end
+
+ def test_render_xml
+ get :two
+ assert_response :success
+ assert_equal(" ", @response.body)
+ assert_equal 'text/plain', @response.content_type
+ end
+end
diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb
index 598cac5156..896bda2597 100644
--- a/actionpack/test/controller/parameters/parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/parameters_permit_test.rb
@@ -298,6 +298,14 @@ class ParametersPermitTest < ActiveSupport::TestCase
assert_not @params.to_unsafe_h.is_a? ActionController::Parameters
end
+ test "to_unsafe_h returns unfiltered params even after accessing few keys" do
+ params = ActionController::Parameters.new("f"=>{"language_facet"=>["Tibetan"]})
+ expected = {"f"=>{"language_facet"=>["Tibetan"]}}
+
+ assert params['f'].is_a? ActionController::Parameters
+ assert_equal expected, params.to_unsafe_h
+ end
+
test "to_h only deep dups Ruby collections" do
company = Class.new do
attr_reader :dupped
diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb
index 7a5b8393dc..11251c86e7 100644
--- a/actionpack/test/dispatch/ssl_test.rb
+++ b/actionpack/test/dispatch/ssl_test.rb
@@ -12,25 +12,31 @@ class SSLTest < ActionDispatch::IntegrationTest
end
class RedirectSSLTest < SSLTest
- def assert_not_redirected(url, headers: {})
- self.app = build_app
+
+ def assert_not_redirected(url, headers: {}, redirect: {}, deprecated_host: nil,
+ deprecated_port: nil)
+
+ self.app = build_app ssl_options: { redirect: redirect,
+ host: deprecated_host, port: deprecated_port
+ }
+
get url, headers: headers
assert_response :ok
end
- def assert_redirected(host: nil, port: nil, status: 301, body: [],
- deprecated_host: nil, deprecated_port: nil,
+ def assert_redirected(redirect: {}, deprecated_host: nil, deprecated_port: nil,
from: 'http://a/b?c=d', to: from.sub('http', 'https'))
- self.app = build_app ssl_options: {
- redirect: { host: host, port: port, status: status, body: body },
+ redirect = { status: 301, body: [] }.merge(redirect)
+
+ self.app = build_app ssl_options: { redirect: redirect,
host: deprecated_host, port: deprecated_port
}
get from
- assert_response status
+ assert_response redirect[:status] || 301
assert_redirected_to to
- assert_equal body.join, @response.body
+ assert_equal redirect[:body].join, @response.body
end
test 'https is not redirected' do
@@ -46,31 +52,31 @@ class RedirectSSLTest < SSLTest
end
test 'redirect with non-301 status' do
- assert_redirected status: 307
+ assert_redirected redirect: { status: 307 }
end
test 'redirect with custom body' do
- assert_redirected body: ['foo']
+ assert_redirected redirect: { body: ['foo'] }
end
test 'redirect to specific host' do
- assert_redirected host: 'ssl', to: 'https://ssl/b?c=d'
+ assert_redirected redirect: { host: 'ssl' }, to: 'https://ssl/b?c=d'
end
test 'redirect to default port' do
- assert_redirected port: 443
+ assert_redirected redirect: { port: 443 }
end
test 'redirect to non-default port' do
- assert_redirected port: 8443, to: 'https://a:8443/b?c=d'
+ assert_redirected redirect: { port: 8443 }, to: 'https://a:8443/b?c=d'
end
test 'redirect to different host and non-default port' do
- assert_redirected host: 'ssl', port: 8443, to: 'https://ssl:8443/b?c=d'
+ assert_redirected redirect: { host: 'ssl', port: 8443 }, to: 'https://ssl:8443/b?c=d'
end
test 'redirect to different host including port' do
- assert_redirected host: 'ssl:443', to: 'https://ssl:443/b?c=d'
+ assert_redirected redirect: { host: 'ssl:443' }, to: 'https://ssl:443/b?c=d'
end
test ':host is deprecated, moved within redirect: { host: … }' do
@@ -84,6 +90,10 @@ class RedirectSSLTest < SSLTest
assert_redirected deprecated_port: 1, to: 'https://a:1/b?c=d'
end
end
+
+ test 'no redirect with redirect set to false' do
+ assert_not_redirected 'http://example.org', redirect: false
+ end
end
class StrictTransportSecurityTest < SSLTest
@@ -187,6 +197,11 @@ class SecureCookiesTest < SSLTest
assert_cookies 'problem=def; path=/; Secure; HttpOnly'
end
+ def test_cookies_as_not_secure_with_secure_cookies_disabled
+ get headers: { 'Set-Cookie' => DEFAULT }, ssl_options: { secure_cookies: false }
+ assert_cookies *DEFAULT.split("\n")
+ end
+
def test_no_cookies
get
assert_nil response.headers['Set-Cookie']
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 91d47cda11..dbdd4378d0 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,3 +1,11 @@
+* Fix `collection_radio_buttons` hidden_field name and make it appear
+ before the actual input radio tags to make the real value override
+ the hidden when passed.
+
+ Fixes #22773
+
+ *Santiago Pastorino*
+
* `ActionView::TestCase::Controller#params` returns an instance of
`ActionController::Parameters`.
diff --git a/actionview/MIT-LICENSE b/actionview/MIT-LICENSE
index 3ec7a617cf..8573eb1225 100644
--- a/actionview/MIT-LICENSE
+++ b/actionview/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2015 David Heinemeier Hansson
+Copyright (c) 2004-2016 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/actionview/lib/action_view.rb b/actionview/lib/action_view.rb
index c3bbac27fd..0a87500a52 100644
--- a/actionview/lib/action_view.rb
+++ b/actionview/lib/action_view.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2015 David Heinemeier Hansson
+# Copyright (c) 2004-2016 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb b/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb
index 3256d44e18..3dda47a458 100644
--- a/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb
+++ b/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb
@@ -23,6 +23,10 @@ module ActionView
def render_component(builder)
builder.check_box + builder.label
end
+
+ def hidden_field_name #:nodoc:
+ "#{super}[]"
+ end
end
end
end
diff --git a/actionview/lib/action_view/helpers/tags/collection_helpers.rb b/actionview/lib/action_view/helpers/tags/collection_helpers.rb
index b87b4281d6..1d3b1ecf0b 100644
--- a/actionview/lib/action_view/helpers/tags/collection_helpers.rb
+++ b/actionview/lib/action_view/helpers/tags/collection_helpers.rb
@@ -97,16 +97,20 @@ module ActionView
# Append a hidden field to make sure something will be sent back to the
# server if all radio buttons are unchecked.
if options.fetch('include_hidden', true)
- rendered_collection + hidden_field
+ hidden_field + rendered_collection
else
rendered_collection
end
end
def hidden_field #:nodoc:
- hidden_name = @html_options[:name] || "#{tag_name(false, @options[:index])}[]"
+ hidden_name = @html_options[:name] || hidden_field_name
@template_object.hidden_field_tag(hidden_name, "", id: nil)
end
+
+ def hidden_field_name #:nodoc:
+ "#{tag_name(false, @options[:index])}"
+ end
end
end
end
diff --git a/actionview/test/template/form_collections_helper_test.rb b/actionview/test/template/form_collections_helper_test.rb
index b59be8e36c..4f7ea88169 100644
--- a/actionview/test/template/form_collections_helper_test.rb
+++ b/actionview/test/template/form_collections_helper_test.rb
@@ -202,35 +202,35 @@ class FormCollectionsHelperTest < ActionView::TestCase
collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')]
with_collection_radio_buttons :user, :category_ids, collection, :id, :name
- assert_select "input[type=hidden][name='user[category_ids][]'][value='']", count: 1
+ assert_select "input[type=hidden][name='user[category_ids]'][value='']", count: 1
end
test 'collection radio buttons generates a hidden field using the given :name in :html_options' do
collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')]
- with_collection_radio_buttons :user, :category_ids, collection, :id, :name, {}, { name: "user[other_category_ids][]" }
+ with_collection_radio_buttons :user, :category_ids, collection, :id, :name, {}, { name: "user[other_category_ids]" }
- assert_select "input[type=hidden][name='user[other_category_ids][]'][value='']", count: 1
+ assert_select "input[type=hidden][name='user[other_category_ids]'][value='']", count: 1
end
test 'collection radio buttons generates a hidden field with index if it was provided' do
collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')]
with_collection_radio_buttons :user, :category_ids, collection, :id, :name, { index: 322 }
- assert_select "input[type=hidden][name='user[322][category_ids][]'][value='']", count: 1
+ assert_select "input[type=hidden][name='user[322][category_ids]'][value='']", count: 1
end
test 'collection radio buttons does not generate a hidden field if include_hidden option is false' do
collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')]
with_collection_radio_buttons :user, :category_ids, collection, :id, :name, include_hidden: false
- assert_select "input[type=hidden][name='user[category_ids][]'][value='']", count: 0
+ assert_select "input[type=hidden][name='user[category_ids]'][value='']", count: 0
end
test 'collection radio buttons does not generate a hidden field if include_hidden option is false with key as string' do
collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')]
with_collection_radio_buttons :user, :category_ids, collection, :id, :name, 'include_hidden' => false
- assert_select "input[type=hidden][name='user[category_ids][]'][value='']", count: 0
+ assert_select "input[type=hidden][name='user[category_ids]'][value='']", count: 0
end
# COLLECTION CHECK BOXES
diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb
index 1f7ff3ca7c..bd40fa06ac 100644
--- a/actionview/test/template/form_helper_test.rb
+++ b/actionview/test/template/form_helper_test.rb
@@ -1600,11 +1600,11 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "new_post", "new_post") do
+ "<input type='hidden' name='post[active]' value='' />" +
"<input id='post_active_true' name='post[active]' type='radio' value='true' />" +
"<label for='post_active_true'>true</label>" +
"<input checked='checked' id='post_active_false' name='post[active]' type='radio' value='false' />" +
- "<label for='post_active_false'>false</label>" +
- "<input type='hidden' name='post[active][]' value='' />"
+ "<label for='post_active_false'>false</label>"
end
assert_dom_equal expected, output_buffer
@@ -1622,13 +1622,13 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "new_post", "new_post") do
+ "<input type='hidden' name='post[active]' value='' />" +
"<label for='post_active_true'>"+
"<input id='post_active_true' name='post[active]' type='radio' value='true' />" +
"true</label>" +
"<label for='post_active_false'>"+
"<input checked='checked' id='post_active_false' name='post[active]' type='radio' value='false' />" +
- "false</label>" +
- "<input type='hidden' name='post[active][]' value='' />"
+ "false</label>"
end
assert_dom_equal expected, output_buffer
@@ -1648,13 +1648,13 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "new_post_1", "new_post") do
+ "<input type='hidden' name='post[active]' value='' />" +
"<label for='post_active_true'>"+
"<input id='post_active_true' name='post[active]' type='radio' value='true' />" +
"true</label>" +
"<label for='post_active_false'>"+
"<input checked='checked' id='post_active_false' name='post[active]' type='radio' value='false' />" +
"false</label>"+
- "<input type='hidden' name='post[active][]' value='' />" +
"<input id='post_id' name='post[id]' type='hidden' value='1' />"
end
@@ -1670,11 +1670,11 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "foo_new_post", "new_post") do
+ "<input type='hidden' name='post[active]' value='' />" +
"<input id='foo_post_active_true' name='post[active]' type='radio' value='true' />" +
"<label for='foo_post_active_true'>true</label>" +
"<input checked='checked' id='foo_post_active_false' name='post[active]' type='radio' value='false' />" +
- "<label for='foo_post_active_false'>false</label>" +
- "<input type='hidden' name='post[active][]' value='' />"
+ "<label for='foo_post_active_false'>false</label>"
end
assert_dom_equal expected, output_buffer
@@ -1689,11 +1689,11 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "new_post", "new_post") do
+ "<input type='hidden' name='post[1][active]' value='' />" +
"<input id='post_1_active_true' name='post[1][active]' type='radio' value='true' />" +
"<label for='post_1_active_true'>true</label>" +
"<input checked='checked' id='post_1_active_false' name='post[1][active]' type='radio' value='false' />" +
- "<label for='post_1_active_false'>false</label>" +
- "<input type='hidden' name='post[1][active][]' value='' />"
+ "<label for='post_1_active_false'>false</label>"
end
assert_dom_equal expected, output_buffer
@@ -1708,13 +1708,13 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "new_post", "new_post") do
+ "<input name='post[tag_ids][]' type='hidden' value='' />" +
"<input checked='checked' id='post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" +
"<label for='post_tag_ids_1'>Tag 1</label>" +
"<input id='post_tag_ids_2' name='post[tag_ids][]' type='checkbox' value='2' />" +
"<label for='post_tag_ids_2'>Tag 2</label>" +
"<input checked='checked' id='post_tag_ids_3' name='post[tag_ids][]' type='checkbox' value='3' />" +
- "<label for='post_tag_ids_3'>Tag 3</label>" +
- "<input name='post[tag_ids][]' type='hidden' value='' />"
+ "<label for='post_tag_ids_3'>Tag 3</label>"
end
assert_dom_equal expected, output_buffer
@@ -1732,6 +1732,7 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "new_post", "new_post") do
+ "<input name='post[tag_ids][]' type='hidden' value='' />" +
"<label for='post_tag_ids_1'>" +
"<input checked='checked' id='post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" +
"Tag 1</label>" +
@@ -1740,8 +1741,7 @@ class FormHelperTest < ActionView::TestCase
"Tag 2</label>" +
"<label for='post_tag_ids_3'>" +
"<input checked='checked' id='post_tag_ids_3' name='post[tag_ids][]' type='checkbox' value='3' />" +
- "Tag 3</label>" +
- "<input name='post[tag_ids][]' type='hidden' value='' />"
+ "Tag 3</label>"
end
assert_dom_equal expected, output_buffer
@@ -1762,6 +1762,7 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "new_post_1", "new_post") do
+ "<input name='post[tag_ids][]' type='hidden' value='' />"+
"<label for='post_tag_ids_1'>" +
"<input checked='checked' id='post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" +
"Tag 1</label>" +
@@ -1771,7 +1772,6 @@ class FormHelperTest < ActionView::TestCase
"<label for='post_tag_ids_3'>" +
"<input checked='checked' id='post_tag_ids_3' name='post[tag_ids][]' type='checkbox' value='3' />" +
"Tag 3</label>" +
- "<input name='post[tag_ids][]' type='hidden' value='' />"+
"<input id='post_id' name='post[id]' type='hidden' value='1' />"
end
@@ -1788,9 +1788,9 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "foo_new_post", "new_post") do
+ "<input name='post[tag_ids][]' type='hidden' value='' />" +
"<input checked='checked' id='foo_post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" +
- "<label for='foo_post_tag_ids_1'>Tag 1</label>" +
- "<input name='post[tag_ids][]' type='hidden' value='' />"
+ "<label for='foo_post_tag_ids_1'>Tag 1</label>"
end
assert_dom_equal expected, output_buffer
@@ -1806,9 +1806,9 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts", "new_post", "new_post") do
+ "<input name='post[1][tag_ids][]' type='hidden' value='' />" +
"<input checked='checked' id='post_1_tag_ids_1' name='post[1][tag_ids][]' type='checkbox' value='1' />" +
- "<label for='post_1_tag_ids_1'>Tag 1</label>" +
- "<input name='post[1][tag_ids][]' type='hidden' value='' />"
+ "<label for='post_1_tag_ids_1'>Tag 1</label>"
end
assert_dom_equal expected, output_buffer
diff --git a/activejob/MIT-LICENSE b/activejob/MIT-LICENSE
index 0cef8cdda0..a3ffb46b3f 100644
--- a/activejob/MIT-LICENSE
+++ b/activejob/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014-2015 David Heinemeier Hansson
+Copyright (c) 2014-2016 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/activejob/lib/active_job.rb b/activejob/lib/active_job.rb
index eb8091a805..f7e05f7cd3 100644
--- a/activejob/lib/active_job.rb
+++ b/activejob/lib/active_job.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2014-2015 David Heinemeier Hansson
+# Copyright (c) 2014-2016 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activemodel/MIT-LICENSE b/activemodel/MIT-LICENSE
index 3ec7a617cf..8573eb1225 100644
--- a/activemodel/MIT-LICENSE
+++ b/activemodel/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2015 David Heinemeier Hansson
+Copyright (c) 2004-2016 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index 4e1b3f7495..b95c174d6e 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2015 David Heinemeier Hansson
+# Copyright (c) 2004-2016 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activerecord/MIT-LICENSE b/activerecord/MIT-LICENSE
index 7c2197229d..1f496cf280 100644
--- a/activerecord/MIT-LICENSE
+++ b/activerecord/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2015 David Heinemeier Hansson
+Copyright (c) 2004-2016 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 264f869c68..f35e1d889e 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2015 David Heinemeier Hansson
+# Copyright (c) 2004-2016 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index fc12c3f45a..bac5a38a5d 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -331,15 +331,30 @@ module ActiveRecord
validation_context = self.validation_context unless [:create, :update].include?(self.validation_context)
unless valid = record.valid?(validation_context)
if reflection.options[:autosave]
+ indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
+
record.errors.each do |attribute, message|
- if index.nil? || (!reflection.options[:index_errors] && !ActiveRecord::Base.index_nested_attribute_errors)
- attribute = "#{reflection.name}.#{attribute}"
- else
+ if indexed_attribute
attribute = "#{reflection.name}[#{index}].#{attribute}"
+ else
+ attribute = "#{reflection.name}.#{attribute}"
end
errors[attribute] << message
errors[attribute].uniq!
end
+
+ record.errors.details.each_key do |attribute|
+ if indexed_attribute
+ reflection_attribute = "#{reflection.name}[#{index}].#{attribute}"
+ else
+ reflection_attribute = "#{reflection.name}.#{attribute}"
+ end
+
+ record.errors.details[attribute].each do |error|
+ errors.details[reflection_attribute] << error
+ errors.details[reflection_attribute].uniq!
+ end
+ end
else
errors.add(reflection.name)
end
diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb
index 7ded96f8fb..04519f4dc3 100644
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ -124,7 +124,7 @@ module ActiveRecord
def deserialize(value)
return if value.nil?
- mapping.key(value.to_i)
+ mapping.key(value)
end
def serialize(value)
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index ba238ea142..8c9eab436d 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -126,9 +126,9 @@ module ActiveRecord
class PendingMigrationError < MigrationError#:nodoc:
def initialize(message = nil)
if !message && defined?(Rails.env)
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate RAILS_ENV=#{::Rails.env}.")
+ super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate RAILS_ENV=#{::Rails.env}")
elsif !message
- super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate.")
+ super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate")
else
super
end
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 983bf019bc..b86cc094fc 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -649,8 +649,8 @@ module ActiveRecord
# they must differ only by #where (if no #group has been defined) or #having (if a #group is
# present). Neither relation may have a #limit, #offset, or #distinct set.
#
- # Post.where("id = 1").or(Post.where("id = 2"))
- # # SELECT `posts`.* FROM `posts` WHERE (('id = 1' OR 'id = 2'))
+ # Post.where("id = 1").or(Post.where("author_id = 3"))
+ # # SELECT `posts`.* FROM `posts` WHERE (('id = 1' OR 'author_id = 3'))
#
def or(other)
spawn.or!(other)
diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb
index 4e89ba4dd1..2bfc5ff7ae 100644
--- a/activerecord/lib/active_record/sanitization.rb
+++ b/activerecord/lib/active_record/sanitization.rb
@@ -213,7 +213,7 @@ module ActiveRecord
end
# TODO: Deprecate this
- def quoted_id
+ def quoted_id # :nodoc:
self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
index 049ed1732e..3d90790367 100644
--- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
@@ -146,8 +146,6 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase
end
setup do
- enable_extension!('uuid-ossp', connection)
-
connection.create_table('pg_uuids', id: :uuid, default: 'uuid_generate_v1()') do |t|
t.string 'name'
t.uuid 'other_uuid', default: 'uuid_generate_v4()'
@@ -172,7 +170,6 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase
drop_table "pg_uuids"
drop_table 'pg_uuids_2'
connection.execute 'DROP FUNCTION IF EXISTS my_uuid_generator();'
- disable_extension!('uuid-ossp', connection)
end
if ActiveRecord::Base.connection.supports_extensions?
@@ -217,8 +214,6 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase
include SchemaDumpingHelper
setup do
- enable_extension!('uuid-ossp', connection)
-
connection.create_table('pg_uuids', id: false) do |t|
t.primary_key :id, :uuid, default: nil
t.string 'name'
@@ -227,7 +222,6 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase
teardown do
drop_table "pg_uuids"
- disable_extension!('uuid-ossp', connection)
end
if ActiveRecord::Base.connection.supports_extensions?
@@ -260,8 +254,6 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::PostgreSQLTestCase
end
setup do
- enable_extension!('uuid-ossp', connection)
-
connection.transaction do
connection.create_table('pg_uuid_posts', id: :uuid) do |t|
t.string 'title'
@@ -276,7 +268,6 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::PostgreSQLTestCase
teardown do
drop_table "pg_uuid_comments"
drop_table "pg_uuid_posts"
- disable_extension!('uuid-ossp', connection)
end
if ActiveRecord::Base.connection.supports_extensions?
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 0df8f1f798..3608063b01 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -433,6 +433,53 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
ActiveRecord::Base.index_nested_attribute_errors = old_attribute_config
end
+ def test_errors_details_should_be_set
+ molecule = Molecule.new
+ valid_electron = Electron.new(name: 'electron')
+ invalid_electron = Electron.new
+
+ molecule.electrons = [valid_electron, invalid_electron]
+
+ assert_not invalid_electron.valid?
+ assert valid_electron.valid?
+ assert_not molecule.valid?
+ assert_equal [{error: :blank}], molecule.errors.details["electrons.name"]
+ end
+
+ def test_errors_details_should_be_indexed_when_passed_as_array
+ guitar = Guitar.new
+ tuning_peg_valid = TuningPeg.new
+ tuning_peg_valid.pitch = 440.0
+ tuning_peg_invalid = TuningPeg.new
+
+ guitar.tuning_pegs = [tuning_peg_valid, tuning_peg_invalid]
+
+ assert_not tuning_peg_invalid.valid?
+ assert tuning_peg_valid.valid?
+ assert_not guitar.valid?
+ assert_equal [{error: :not_a_number, value: nil}] , guitar.errors.details["tuning_pegs[1].pitch"]
+ assert_equal [], guitar.errors.details["tuning_pegs.pitch"]
+ end
+
+ def test_errors_details_should_be_indexed_when_global_flag_is_set
+ old_attribute_config = ActiveRecord::Base.index_nested_attribute_errors
+ ActiveRecord::Base.index_nested_attribute_errors = true
+
+ molecule = Molecule.new
+ valid_electron = Electron.new(name: 'electron')
+ invalid_electron = Electron.new
+
+ molecule.electrons = [valid_electron, invalid_electron]
+
+ assert_not invalid_electron.valid?
+ assert valid_electron.valid?
+ assert_not molecule.valid?
+ assert_equal [{error: :blank}], molecule.errors.details["electrons[1].name"]
+ assert_equal [], molecule.errors.details["electrons.name"]
+ ensure
+ ActiveRecord::Base.index_nested_attribute_errors = old_attribute_config
+ end
+
def test_valid_adding_with_nested_attributes
molecule = Molecule.new
valid_electron = Electron.new(name: 'electron')
diff --git a/activerecord/test/cases/migration/rename_table_test.rb b/activerecord/test/cases/migration/rename_table_test.rb
index 8eb027d53f..b926a92849 100644
--- a/activerecord/test/cases/migration/rename_table_test.rb
+++ b/activerecord/test/cases/migration/rename_table_test.rb
@@ -80,12 +80,10 @@ module ActiveRecord
end
def test_renaming_table_doesnt_attempt_to_rename_non_existent_sequences
- enable_extension!('uuid-ossp', connection)
connection.create_table :cats, id: :uuid
assert_nothing_raised { rename_table :cats, :felines }
ActiveSupport::Deprecation.silence { assert connection.table_exists? :felines }
ensure
- disable_extension!('uuid-ossp', connection)
connection.drop_table :cats, if_exists: true
connection.drop_table :felines, if_exists: true
end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index cee1e57c93..4963dd25d1 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Support extended grapheme clusters and UAX 29.
+
+ *Adam Roben*
+
+
## Rails 5.0.0.beta1 (December 18, 2015) ##
* Add petabyte and exabyte numeric conversion.
diff --git a/activesupport/MIT-LICENSE b/activesupport/MIT-LICENSE
index 7bffebb076..40235833ba 100644
--- a/activesupport/MIT-LICENSE
+++ b/activesupport/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2005-2015 David Heinemeier Hansson
+Copyright (c) 2005-2016 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 2019afeb00..94fe893149 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2005-2015 David Heinemeier Hansson
+# Copyright (c) 2005-2016 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activesupport/lib/active_support/multibyte/unicode.rb b/activesupport/lib/active_support/multibyte/unicode.rb
index 586002b03b..72b20fff06 100644
--- a/activesupport/lib/active_support/multibyte/unicode.rb
+++ b/activesupport/lib/active_support/multibyte/unicode.rb
@@ -87,19 +87,44 @@ module ActiveSupport
pos += 1
previous = codepoints[pos-1]
current = codepoints[pos]
- if (
- # CR X LF
- ( previous == database.boundary[:cr] and current == database.boundary[:lf] ) or
- # L X (L|V|LV|LVT)
- ( database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
- # (LV|V) X (V|T)
- ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
- # (LVT|T) X (T)
- ( in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current ) or
- # X Extend
- (database.boundary[:extend] === current)
- )
- else
+
+ should_break =
+ # GB3. CR X LF
+ if previous == database.boundary[:cr] and current == database.boundary[:lf]
+ false
+ # GB4. (Control|CR|LF) ÷
+ elsif previous and in_char_class?(previous, [:control,:cr,:lf])
+ true
+ # GB5. ÷ (Control|CR|LF)
+ elsif in_char_class?(current, [:control,:cr,:lf])
+ true
+ # GB6. L X (L|V|LV|LVT)
+ elsif database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt])
+ false
+ # GB7. (LV|V) X (V|T)
+ elsif in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t])
+ false
+ # GB8. (LVT|T) X (T)
+ elsif in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current
+ false
+ # GB8a. Regional_Indicator X Regional_Indicator
+ elsif database.boundary[:regional_indicator] === previous and database.boundary[:regional_indicator] === current
+ false
+ # GB9. X Extend
+ elsif database.boundary[:extend] === current
+ false
+ # GB9a. X SpacingMark
+ elsif database.boundary[:spacingmark] === current
+ false
+ # GB9b. Prepend X
+ elsif database.boundary[:prepend] === previous
+ false
+ # GB10. Any ÷ Any
+ else
+ true
+ end
+
+ if should_break
unpacked << codepoints[marker..pos-1]
marker = pos
end
diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb
index 8d4d9d736c..c1e0b19248 100644
--- a/activesupport/test/multibyte_chars_test.rb
+++ b/activesupport/test/multibyte_chars_test.rb
@@ -612,28 +612,54 @@ class MultibyteCharsExtrasTest < ActiveSupport::TestCase
['abc', 3],
['こにちわ', 4],
[[0x0924, 0x094D, 0x0930].pack('U*'), 2],
+ # GB3
[%w(cr lf), 1],
+ # GB4
+ [%w(cr n), 2],
+ [%w(lf n), 2],
+ [%w(control n), 2],
+ [%w(cr extend), 2],
+ [%w(lf extend), 2],
+ [%w(control extend), 2],
+ # GB 5
+ [%w(n cr), 2],
+ [%w(n lf), 2],
+ [%w(n control), 2],
+ [%w(extend cr), 2],
+ [%w(extend lf), 2],
+ [%w(extend control), 2],
+ # GB 6
[%w(l l), 1],
[%w(l v), 1],
[%w(l lv), 1],
[%w(l lvt), 1],
+ # GB7
[%w(lv v), 1],
[%w(lv t), 1],
[%w(v v), 1],
[%w(v t), 1],
+ # GB8
[%w(lvt t), 1],
[%w(t t), 1],
+ # GB8a
+ [%w(r r), 1],
+ # GB9
[%w(n extend), 1],
+ # GB9a
+ [%w(n spacingmark), 1],
+ # GB10
[%w(n n), 2],
+ # Other
[%w(n cr lf n), 3],
- [%w(n l v t), 2]
+ [%w(n l v t), 2],
+ [%w(cr extend n), 3],
].each do |input, expected_length|
if input.kind_of?(Array)
str = string_from_classes(input)
else
str = input
end
- assert_equal expected_length, chars(str).grapheme_length
+ assert_equal expected_length, chars(str).grapheme_length, input.inspect
end
end
@@ -698,7 +724,7 @@ class MultibyteCharsExtrasTest < ActiveSupport::TestCase
# Characters from the character classes as described in UAX #29
character_from_class = {
:l => 0x1100, :v => 0x1160, :t => 0x11A8, :lv => 0xAC00, :lvt => 0xAC01, :cr => 0x000D, :lf => 0x000A,
- :extend => 0x094D, :n => 0x64
+ :extend => 0x094D, :n => 0x64, :spacingmark => 0x0903, :r => 0x1F1E6, :control => 0x0001
}
classes.collect do |k|
character_from_class[k.intern]
diff --git a/activesupport/test/multibyte_grapheme_break_conformance.rb b/activesupport/test/multibyte_grapheme_break_conformance.rb
new file mode 100644
index 0000000000..7d185e2cae
--- /dev/null
+++ b/activesupport/test/multibyte_grapheme_break_conformance.rb
@@ -0,0 +1,76 @@
+# encoding: utf-8
+
+require 'abstract_unit'
+
+require 'fileutils'
+require 'open-uri'
+require 'tmpdir'
+
+class Downloader
+ def self.download(from, to)
+ unless File.exist?(to)
+ $stderr.puts "Downloading #{from} to #{to}"
+ unless File.exist?(File.dirname(to))
+ system "mkdir -p #{File.dirname(to)}"
+ end
+ open(from) do |source|
+ File.open(to, 'w') do |target|
+ source.each_line do |l|
+ target.write l
+ end
+ end
+ end
+ end
+ end
+end
+
+class MultibyteGraphemeBreakConformanceTest < ActiveSupport::TestCase
+ TEST_DATA_URL = "http://www.unicode.org/Public/#{ActiveSupport::Multibyte::Unicode::UNICODE_VERSION}/ucd/auxiliary"
+ TEST_DATA_FILE = '/GraphemeBreakTest.txt'
+ CACHE_DIR = File.join(Dir.tmpdir, 'cache')
+
+ def setup
+ FileUtils.mkdir_p(CACHE_DIR)
+ Downloader.download(TEST_DATA_URL + TEST_DATA_FILE, CACHE_DIR + TEST_DATA_FILE)
+ end
+
+ def test_breaks
+ each_line_of_break_tests do |*cols|
+ *clusters, comment = *cols
+ packed = ActiveSupport::Multibyte::Unicode.pack_graphemes(clusters)
+ assert_equal clusters, ActiveSupport::Multibyte::Unicode.unpack_graphemes(packed), comment
+ end
+ end
+
+ protected
+ def each_line_of_break_tests(&block)
+ lines = 0
+ max_test_lines = 0 # Don't limit below 21, because that's the header of the testfile
+ File.open(File.join(CACHE_DIR, TEST_DATA_FILE), 'r') do | f |
+ until f.eof? || (max_test_lines > 21 and lines > max_test_lines)
+ lines += 1
+ line = f.gets.chomp!
+ next if (line.empty? || line =~ /^\#/)
+
+ cols, comment = line.split("#")
+ # Cluster breaks are represented by ÷
+ clusters = cols.split("÷").map{|e| e.strip}.reject{|e| e.empty? }
+ clusters = clusters.map do |cluster|
+ # Codepoints within each cluster are separated by ×
+ codepoints = cluster.split("×").map{|e| e.strip}.reject{|e| e.empty? }
+ # codepoints are in hex in the test suite, pack wants them as integers
+ codepoints.map{|codepoint| codepoint.to_i(16)}
+ end
+
+ # The tests contain a solitary U+D800 <Non Private Use High
+ # Surrogate, First> character, which Ruby does not allow to stand
+ # alone in a UTF-8 string. So we'll just skip it.
+ next if clusters.flatten.include?(0xd800)
+
+ clusters << comment.strip
+
+ yield(*clusters)
+ end
+ end
+ end
+end
diff --git a/activesupport/test/multibyte_normalization_conformance.rb b/activesupport/test/multibyte_normalization_conformance.rb
new file mode 100644
index 0000000000..839aec7fa8
--- /dev/null
+++ b/activesupport/test/multibyte_normalization_conformance.rb
@@ -0,0 +1,129 @@
+# encoding: utf-8
+
+require 'abstract_unit'
+require 'multibyte_test_helpers'
+
+require 'fileutils'
+require 'open-uri'
+require 'tmpdir'
+
+class Downloader
+ def self.download(from, to)
+ unless File.exist?(to)
+ $stderr.puts "Downloading #{from} to #{to}"
+ unless File.exist?(File.dirname(to))
+ system "mkdir -p #{File.dirname(to)}"
+ end
+ open(from) do |source|
+ File.open(to, 'w') do |target|
+ source.each_line do |l|
+ target.write l
+ end
+ end
+ end
+ end
+ end
+end
+
+class MultibyteNormalizationConformanceTest < ActiveSupport::TestCase
+ include MultibyteTestHelpers
+
+ UNIDATA_URL = "http://www.unicode.org/Public/#{ActiveSupport::Multibyte::Unicode::UNICODE_VERSION}/ucd"
+ UNIDATA_FILE = '/NormalizationTest.txt'
+ CACHE_DIR = File.join(Dir.tmpdir, 'cache')
+
+ def setup
+ FileUtils.mkdir_p(CACHE_DIR)
+ Downloader.download(UNIDATA_URL + UNIDATA_FILE, CACHE_DIR + UNIDATA_FILE)
+ @proxy = ActiveSupport::Multibyte::Chars
+ end
+
+ def test_normalizations_C
+ each_line_of_norm_tests do |*cols|
+ col1, col2, col3, col4, col5, comment = *cols
+
+ # CONFORMANCE:
+ # 1. The following invariants must be true for all conformant implementations
+ #
+ # NFC
+ # c2 == NFC(c1) == NFC(c2) == NFC(c3)
+ assert_equal_codepoints col2, @proxy.new(col1).normalize(:c), "Form C - Col 2 has to be NFC(1) - #{comment}"
+ assert_equal_codepoints col2, @proxy.new(col2).normalize(:c), "Form C - Col 2 has to be NFC(2) - #{comment}"
+ assert_equal_codepoints col2, @proxy.new(col3).normalize(:c), "Form C - Col 2 has to be NFC(3) - #{comment}"
+ #
+ # c4 == NFC(c4) == NFC(c5)
+ assert_equal_codepoints col4, @proxy.new(col4).normalize(:c), "Form C - Col 4 has to be C(4) - #{comment}"
+ assert_equal_codepoints col4, @proxy.new(col5).normalize(:c), "Form C - Col 4 has to be C(5) - #{comment}"
+ end
+ end
+
+ def test_normalizations_D
+ each_line_of_norm_tests do |*cols|
+ col1, col2, col3, col4, col5, comment = *cols
+ #
+ # NFD
+ # c3 == NFD(c1) == NFD(c2) == NFD(c3)
+ assert_equal_codepoints col3, @proxy.new(col1).normalize(:d), "Form D - Col 3 has to be NFD(1) - #{comment}"
+ assert_equal_codepoints col3, @proxy.new(col2).normalize(:d), "Form D - Col 3 has to be NFD(2) - #{comment}"
+ assert_equal_codepoints col3, @proxy.new(col3).normalize(:d), "Form D - Col 3 has to be NFD(3) - #{comment}"
+ # c5 == NFD(c4) == NFD(c5)
+ assert_equal_codepoints col5, @proxy.new(col4).normalize(:d), "Form D - Col 5 has to be NFD(4) - #{comment}"
+ assert_equal_codepoints col5, @proxy.new(col5).normalize(:d), "Form D - Col 5 has to be NFD(5) - #{comment}"
+ end
+ end
+
+ def test_normalizations_KC
+ each_line_of_norm_tests do | *cols |
+ col1, col2, col3, col4, col5, comment = *cols
+ #
+ # NFKC
+ # c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
+ assert_equal_codepoints col4, @proxy.new(col1).normalize(:kc), "Form D - Col 4 has to be NFKC(1) - #{comment}"
+ assert_equal_codepoints col4, @proxy.new(col2).normalize(:kc), "Form D - Col 4 has to be NFKC(2) - #{comment}"
+ assert_equal_codepoints col4, @proxy.new(col3).normalize(:kc), "Form D - Col 4 has to be NFKC(3) - #{comment}"
+ assert_equal_codepoints col4, @proxy.new(col4).normalize(:kc), "Form D - Col 4 has to be NFKC(4) - #{comment}"
+ assert_equal_codepoints col4, @proxy.new(col5).normalize(:kc), "Form D - Col 4 has to be NFKC(5) - #{comment}"
+ end
+ end
+
+ def test_normalizations_KD
+ each_line_of_norm_tests do | *cols |
+ col1, col2, col3, col4, col5, comment = *cols
+ #
+ # NFKD
+ # c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
+ assert_equal_codepoints col5, @proxy.new(col1).normalize(:kd), "Form KD - Col 5 has to be NFKD(1) - #{comment}"
+ assert_equal_codepoints col5, @proxy.new(col2).normalize(:kd), "Form KD - Col 5 has to be NFKD(2) - #{comment}"
+ assert_equal_codepoints col5, @proxy.new(col3).normalize(:kd), "Form KD - Col 5 has to be NFKD(3) - #{comment}"
+ assert_equal_codepoints col5, @proxy.new(col4).normalize(:kd), "Form KD - Col 5 has to be NFKD(4) - #{comment}"
+ assert_equal_codepoints col5, @proxy.new(col5).normalize(:kd), "Form KD - Col 5 has to be NFKD(5) - #{comment}"
+ end
+ end
+
+ protected
+ def each_line_of_norm_tests(&block)
+ lines = 0
+ max_test_lines = 0 # Don't limit below 38, because that's the header of the testfile
+ File.open(File.join(CACHE_DIR, UNIDATA_FILE), 'r') do | f |
+ until f.eof? || (max_test_lines > 38 and lines > max_test_lines)
+ lines += 1
+ line = f.gets.chomp!
+ next if (line.empty? || line =~ /^\#/)
+
+ cols, comment = line.split("#")
+ cols = cols.split(";").map{|e| e.strip}.reject{|e| e.empty? }
+ next unless cols.length == 5
+
+ # codepoints are in hex in the test suite, pack wants them as integers
+ cols.map!{|c| c.split.map{|codepoint| codepoint.to_i(16)}.pack("U*") }
+ cols << comment
+
+ yield(*cols)
+ end
+ end
+ end
+
+ def inspect_codepoints(str)
+ str.to_s.unpack("U*").map{|cp| cp.to_s(16) }.join(' ')
+ end
+end
diff --git a/guides/source/initialization.md b/guides/source/initialization.md
index 7bf7eebb62..6232ef4c57 100644
--- a/guides/source/initialization.md
+++ b/guides/source/initialization.md
@@ -530,16 +530,17 @@ This file is responsible for requiring all the individual frameworks of Rails:
require "rails"
%w(
- active_record
- action_controller
- action_view
- action_mailer
- active_job
- rails/test_unit
- sprockets
-).each do |framework|
+ active_record/railtie
+ action_controller/railtie
+ action_view/railtie
+ action_mailer/railtie
+ active_job/railtie
+ action_cable/engine
+ rails/test_unit/railtie
+ sprockets/railtie
+).each do |railtie|
begin
- require "#{framework}/railtie"
+ require "#{railtie}"
rescue LoadError
end
end
diff --git a/guides/source/testing.md b/guides/source/testing.md
index a4b62955c5..84f80e3c37 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -654,7 +654,7 @@ The easiest way to see functional tests in action is to generate a controller
scaffold:
```bash
-$ bin/rails generate scaffold_controller article title:string body:test
+$ bin/rails generate scaffold_controller article title:string body:text
...
create app/controllers/articles_controller.rb
...
diff --git a/railties/MIT-LICENSE b/railties/MIT-LICENSE
index 7c2197229d..1f496cf280 100644
--- a/railties/MIT-LICENSE
+++ b/railties/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2015 David Heinemeier Hansson
+Copyright (c) 2004-2016 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb
index ed6a1f82d3..4f1cc0703d 100644
--- a/railties/lib/rails/application/default_middleware_stack.rb
+++ b/railties/lib/rails/application/default_middleware_stack.rb
@@ -68,7 +68,7 @@ module Rails
middleware.use ::ActionDispatch::Cookies unless config.api_only
if !config.api_only && config.session_store
- if config.force_ssl && !config.session_options.key?(:secure)
+ if config.force_ssl && config.ssl_options.fetch(:secure_cookies, true) && !config.session_options.key?(:secure)
config.session_options[:secure] = true
end
middleware.use config.session_store, config.session_options
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 064b109a6f..297ccb1dbf 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -281,6 +281,8 @@ module Rails
return [] if options[:skip_sprockets]
gems = []
+ gems << GemfileEntry.version('sass-rails', '~> 5.0',
+ 'Use SCSS for stylesheets')
gems << GemfileEntry.version('uglifier',
'>= 1.3.0',
diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee
index 49a7cfa69b..07934d026f 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee
+++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee
@@ -1,4 +1,4 @@
-# Action Cable provides the framework to deal with WebSockets in Rails.
+# Action Cable provides the framework to deal with WebSockets in Rails.
# You can generate new channels where WebSocket features live using the rails generate channel command.
#
# Turn on the cable connection by removing the comments after the require statements (and ensure it's also on in config/routes.rb).
diff --git a/railties/lib/rails/generators/rails/model/USAGE b/railties/lib/rails/generators/rails/model/USAGE
index 11daa5c3cb..025bcf4774 100644
--- a/railties/lib/rails/generators/rails/model/USAGE
+++ b/railties/lib/rails/generators/rails/model/USAGE
@@ -8,14 +8,14 @@ Description:
As a special case, specifying 'password:digest' will generate a
password_digest field of string type, and configure your generated model and
- tests for use with ActiveModel has_secure_password (assuming the default ORM
+ tests for use with Active Model has_secure_password (assuming the default ORM
and test framework are being used).
You don't have to think up every attribute up front, but it helps to
sketch out a few so you can start working with the model immediately.
This generator invokes your configured ORM and test framework, which
- defaults to ActiveRecord and TestUnit.
+ defaults to Active Record and TestUnit.
Finally, if --parent option is given, it's used as superclass of the
created model. This allows you create Single Table Inheritance models.
@@ -91,7 +91,7 @@ Available field types:
Examples:
`rails generate model account`
- For ActiveRecord and TestUnit it creates:
+ For Active Record and TestUnit it creates:
Model: app/models/account.rb
Test: test/models/account_test.rb
@@ -104,7 +104,7 @@ Examples:
`rails generate model admin/account`
- For ActiveRecord and TestUnit it creates:
+ For Active Record and TestUnit it creates:
Module: app/models/admin.rb
Model: app/models/admin/account.rb
diff --git a/railties/lib/rails/generators/rails/plugin/templates/app/models/application_record.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/models/%namespaced_name%/application_record.rb.tt
index 8aa3de78f1..8aa3de78f1 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/app/models/application_record.rb.tt
+++ b/railties/lib/rails/generators/rails/plugin/templates/app/models/%namespaced_name%/application_record.rb.tt
diff --git a/railties/lib/rails/generators/rails/plugin/templates/app/models/.empty_directory b/railties/lib/rails/generators/rails/plugin/templates/app/models/.empty_directory
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/lib/rails/generators/rails/plugin/templates/app/models/.empty_directory
+++ /dev/null
diff --git a/railties/lib/rails/generators/rails/scaffold/USAGE b/railties/lib/rails/generators/rails/scaffold/USAGE
index d2e495758d..c9283eda87 100644
--- a/railties/lib/rails/generators/rails/scaffold/USAGE
+++ b/railties/lib/rails/generators/rails/scaffold/USAGE
@@ -16,7 +16,7 @@ Description:
As a special case, specifying 'password:digest' will generate a
password_digest field of string type, and configure your generated model,
- controller, views, and test suite for use with ActiveModel
+ controller, views, and test suite for use with Active Model
has_secure_password (assuming they are using Rails defaults).
Timestamps are added by default, so you don't have to specify them by hand
diff --git a/railties/test/application/middleware/session_test.rb b/railties/test/application/middleware/session_test.rb
index 25eadfc387..f847e80471 100644
--- a/railties/test/application/middleware/session_test.rb
+++ b/railties/test/application/middleware/session_test.rb
@@ -20,12 +20,19 @@ module ApplicationTests
@app ||= Rails.application
end
- test "config.force_ssl sets cookie to secure only" do
+ test "config.force_ssl sets cookie to secure only by default" do
add_to_config "config.force_ssl = true"
require "#{app_path}/config/environment"
assert app.config.session_options[:secure], "Expected session to be marked as secure"
end
+ test "config.force_ssl doesn't set cookie to secure only when changed from default" do
+ add_to_config "config.force_ssl = true"
+ add_to_config "config.ssl_options = { secure_cookies: false }"
+ require "#{app_path}/config/environment"
+ assert !app.config.session_options[:secure]
+ end
+
test "session is not loaded if it's not used" do
make_basic_app
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 314d8c50b0..e5480180ce 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -361,6 +361,13 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_generator_has_assets_gems
+ run_generator
+
+ assert_gem 'sass-rails'
+ assert_gem 'uglifier'
+ end
+
def test_generator_if_skip_sprockets_is_given
run_generator [destination_root, "--skip-sprockets"]
assert_no_file "config/initializers/assets.rb"