Permalink
Browse files

Merge branch 'master' into adequaterecord

* master: (26 commits)
  Avoid URI parsing
  Add missing require so requiring `active_support/cache` works again.
  depend_on_asset is not required anymore on sprockets-rails 2.1.2
  upgrading section for 4.1 is no longer WIP. [ci skip]
  Expand explanation of how to set secrets.yml. [ci skip]
  Guides: minor typo fixed [ci skip]
  Fixed problem where `1.day.eql?(1.day)` is false
  new CHANGELOGs entries are in the top [ci skip]
  Updates the maintenance policy with new Rails versions
  Dont abbreviate that which needs no abbreviation
  Dont encourage aliases now that we have variants
  Use short-form for the scaffold render calls and drop the needless test
  Drop in @jeremy's new database.yml template text
  Don't deprecate after all
  Less ambition, more deprecation
  Ensure we correctly and immediately load all ENV entries
  Give a deprecation message even when the lookup fails
  Rearrange the config merger some more
  entry is always a Hash
  Check env_url only once
  ...

Conflicts:
	Gemfile
  • Loading branch information...
tenderlove committed Apr 9, 2014
2 parents 3321d1a + 7b75b67 commit db5e578b647e1730ea2aecb1ca58fd9a434f6cf6
Showing with 377 additions and 164 deletions.
  1. +1 −0 Gemfile
  2. +8 −5 actionpack/lib/action_dispatch/middleware/ssl.rb
  3. +7 −0 actionpack/test/dispatch/ssl_test.rb
  4. +3 −3 activerecord/lib/active_record/connection_adapters/connection_specification.rb
  5. +6 −29 activerecord/lib/active_record/connection_handling.rb
  6. +6 −3 activerecord/lib/active_record/enum.rb
  7. +1 −1 activerecord/lib/active_record/validations/uniqueness.rb
  8. +45 −26 activerecord/test/cases/connection_adapters/connection_handler_test.rb
  9. +28 −7 activerecord/test/cases/enum_test.rb
  10. +34 −0 activesupport/CHANGELOG.md
  11. +1 −0 activesupport/lib/active_support/cache/strategy/local_cache.rb
  12. +4 −0 activesupport/lib/active_support/duration.rb
  13. +7 −0 activesupport/test/core_ext/duration_test.rb
  14. +4 −0 guides/CHANGELOG.md
  15. +5 −20 guides/source/asset_pipeline.md
  16. +3 −3 guides/source/maintenance_policy.md
  17. +7 −6 guides/source/upgrading_ruby_on_rails.md
  18. +2 −2 railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb
  19. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml
  20. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml
  21. +12 −3 railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml
  22. +24 −3 railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml
  23. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml
  24. +2 −3 railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml
  25. +21 −5 railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml
  26. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml
  27. +21 −5 railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml
  28. +2 −9 railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml
  29. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml
  30. +0 −1 railties/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb
  31. +2 −2 railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb
  32. +6 −6 railties/test/application/assets_test.rb
  33. +0 −7 railties/test/generators/scaffold_controller_generator_test.rb
View
@@ -12,6 +12,7 @@ gem 'jquery-rails', '~> 3.1.0'
gem 'turbolinks'
gem 'coffee-rails', '~> 4.0.0'
gem 'arel', path: '/Users/aaron/git/arel'
+gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: '2-1-stable'
# require: false so bcrypt is loaded only when has_secure_password is used.
# This is to avoid ActiveModel (and by extension the entire framework)
@@ -32,11 +32,14 @@ def call(env)
private
def redirect_to_https(request)
- url = URI(request.url)
- url.scheme = "https"
- url.host = @host if @host
- url.port = @port if @port
- headers = { 'Content-Type' => 'text/html', 'Location' => url.to_s }
+ host = @host || request.host
+ port = @port || request.port
+
+ location = "https://#{host}"
+ location << ":#{port}" if port != 80
+ location << request.fullpath
+
+ headers = { 'Content-Type' => 'text/html', 'Location' => location }
[301, headers, []]
end
@@ -196,6 +196,13 @@ def test_redirect_to_host_and_port
response.headers['Location']
end
+ def test_redirect_to_host_with_port
+ self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org:443")
+ get "http://example.org/path?key=value"
+ assert_equal "https://ssl.example.org:443/path?key=value",
+ response.headers['Location']
+ end
+
def test_redirect_to_secure_host_when_on_subdomain
self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org")
get "http://ssl.example.org/path?key=value"
@@ -33,7 +33,7 @@ class ConnectionUrlResolver # :nodoc:
def initialize(url)
raise "Database URL cannot be empty" if url.blank?
@uri = URI.parse(url)
- @adapter = @uri.scheme
+ @adapter = @uri.scheme.gsub('-', '_')
@adapter = "postgresql" if @adapter == "postgres"
if @uri.opaque
@@ -220,10 +220,10 @@ def resolve_string_connection(spec)
# an environment key or a URL spec, so we have deprecated
# this ambiguous behaviour and in the future this function
# can be removed in favor of resolve_url_connection.
- if configurations.key?(spec)
+ if configurations.key?(spec) || spec !~ /:/
ActiveSupport::Deprecation.warn "Passing a string to ActiveRecord::Base.establish_connection " \
"for a configuration lookup is deprecated, please pass a symbol (#{spec.to_sym.inspect}) instead"
- resolve_connection(configurations[spec])
+ resolve_symbol_connection(spec)
else
resolve_url_connection(spec)
end
@@ -58,9 +58,9 @@ def establish_connection(spec = nil)
end
class MergeAndResolveDefaultUrlConfig # :nodoc:
- def initialize(raw_configurations, url = ENV['DATABASE_URL'])
+ def initialize(raw_configurations)
@raw_config = raw_configurations.dup
- @url = url
+ @env = DEFAULT_ENV.call.to_s
end
# Returns fully resolved connection hashes.
@@ -71,33 +71,10 @@ def resolve
private
def config
- if @url
- raw_merged_into_default
- else
- @raw_config
- end
- end
-
- def raw_merged_into_default
- default = default_url_hash
-
- @raw_config.each do |env, values|
- default[env] = values || {}
- default[env].merge!("url" => @url) { |h, v1, v2| v1 || v2 } if default[env].is_a?(Hash)
- end
- default
- end
-
- # When the raw configuration is not present and ENV['DATABASE_URL']
- # is available we return a hash with the connection information in
- # the connection URL. This hash responds to any string key with
- # resolved connection information.
- def default_url_hash
- Hash.new do |hash, key|
- hash[key] = if key.is_a? String
- ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver.new(@url).to_hash
- else
- nil
+ @raw_config.dup.tap do |cfg|
+ if url = ENV['DATABASE_URL']
+ cfg[@env] ||= {}
+ cfg[@env]["url"] ||= url
end
end
end
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/deep_dup'
+
module ActiveRecord
# Declare an enum attribute where the values map to integers in the database,
# but can be queried by name. Example:
@@ -70,8 +72,9 @@ def self.extended(base)
base.defined_enums = {}
end
- def enum_mapping_for(attr_name) # :nodoc:
- defined_enums[attr_name.to_s]
+ def inherited(base)
+ base.defined_enums = defined_enums.deep_dup
+ super
end
def enum(definitions)
@@ -136,7 +139,7 @@ def _enum_methods_module
mod = Module.new do
private
def save_changed_attribute(attr_name, value)
- if (mapping = self.class.enum_mapping_for(attr_name))
+ if (mapping = self.class.defined_enums[attr_name.to_s])
if attribute_changed?(attr_name)
old = changed_attributes[attr_name]
@@ -93,7 +93,7 @@ def deserialize_attribute(record, attribute, value)
end
def map_enum_attribute(klass, attribute, value)
- mapping = klass.enum_mapping_for(attribute.to_s)
+ mapping = klass.defined_enums[attribute.to_s]
value = mapping[value] if value && mapping
value
end
@@ -25,35 +25,45 @@ def spec(spec, config)
ConnectionSpecification::Resolver.new(klass.new(config).resolve).spec(spec)
end
- def test_resolver_with_database_uri_and_known_key
+ def test_resolver_with_database_uri_and_current_env_symbol_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
- config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
- actual = resolve(:production, config)
+ config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
+ actual = resolve(:default_env, config)
expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
assert_equal expected, actual
end
- def test_resolver_with_database_uri_and_known_string_key
+ def test_resolver_with_database_uri_and_and_current_env_string_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
- config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
- actual = assert_deprecated { resolve("production", config) }
+ config = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo" } }
+ actual = assert_deprecated { resolve("default_env", config) }
expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
assert_equal expected, actual
end
- def test_resolver_with_database_uri_and_unknown_symbol_key
+ def test_resolver_with_database_uri_and_known_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
- config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
+ config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
actual = resolve(:production, config)
- expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
+ expected = { "adapter"=>"not_postgres", "database"=>"not_foo", "host"=>"localhost" }
assert_equal expected, actual
end
- def test_resolver_with_database_uri_and_unknown_string_key
+ def test_resolver_with_database_uri_and_unknown_symbol_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
assert_raises AdapterNotSpecified do
- spec("production", config)
+ resolve(:production, config)
+ end
+ end
+
+ def test_resolver_with_database_uri_and_unknown_string_key
+ ENV['DATABASE_URL'] = "postgres://localhost/foo"
+ config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
+ assert_deprecated do
+ assert_raises AdapterNotSpecified do
+ spec("production", config)
+ end
end
end
@@ -73,16 +83,24 @@ def test_jdbc_url
def test_environment_does_not_exist_in_config_url_does_exist
ENV['DATABASE_URL'] = "postgres://localhost/foo"
- config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
+ config = { "not_default_env" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = klass.new(config).resolve
expect_prod = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
- assert_equal expect_prod, actual["production"]
+ assert_equal expect_prod, actual["default_env"]
+ end
+
+ def test_url_with_hyphenated_scheme
+ ENV['DATABASE_URL'] = "ibm-db://localhost/foo"
+ config = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
+ actual = resolve(:default_env, config)
+ expected = { "adapter"=>"ibm_db", "database"=>"foo", "host"=>"localhost" }
+ assert_equal expected, actual
end
def test_string_connection
- config = { "production" => "postgres://localhost/foo" }
+ config = { "default_env" => "postgres://localhost/foo" }
actual = klass.new(config).resolve
- expected = { "production" =>
+ expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost"
@@ -92,9 +110,9 @@ def test_string_connection
end
def test_url_sub_key
- config = { "production" => { "url" => "postgres://localhost/foo" } }
+ config = { "default_env" => { "url" => "postgres://localhost/foo" } }
actual = klass.new(config).resolve
- expected = { "production" =>
+ expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost"
@@ -123,9 +141,10 @@ def test_blank_with_database_url
expected = { "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost" }
- assert_equal expected, actual["production"]
- assert_equal expected, actual["development"]
- assert_equal expected, actual["test"]
+ assert_equal expected, actual["default_env"]
+ assert_equal nil, actual["production"]
+ assert_equal nil, actual["development"]
+ assert_equal nil, actual["test"]
assert_equal nil, actual[:production]
assert_equal nil, actual[:development]
assert_equal nil, actual[:test]
@@ -134,9 +153,9 @@ def test_blank_with_database_url
def test_url_sub_key_with_database_url
ENV['DATABASE_URL'] = "NOT-POSTGRES://localhost/NOT_FOO"
- config = { "production" => { "url" => "postgres://localhost/foo" } }
+ config = { "default_env" => { "url" => "postgres://localhost/foo" } }
actual = klass.new(config).resolve
- expected = { "production" =>
+ expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost"
@@ -148,9 +167,9 @@ def test_url_sub_key_with_database_url
def test_merge_no_conflicts_with_database_url
ENV['DATABASE_URL'] = "postgres://localhost/foo"
- config = {"production" => { "pool" => "5" } }
+ config = {"default_env" => { "pool" => "5" } }
actual = klass.new(config).resolve
- expected = { "production" =>
+ expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost",
@@ -163,9 +182,9 @@ def test_merge_no_conflicts_with_database_url
def test_merge_conflicts_with_database_url
ENV['DATABASE_URL'] = "postgres://localhost/foo"
- config = {"production" => { "adapter" => "NOT-POSTGRES", "database" => "NOT-FOO", "pool" => "5" } }
+ config = {"default_env" => { "adapter" => "NOT-POSTGRES", "database" => "NOT-FOO", "pool" => "5" } }
actual = klass.new(config).resolve
- expected = { "production" =>
+ expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost",
@@ -252,17 +252,38 @@ def self.name; 'Book'; end
end
test "enums are distinct per class" do
- Plane = Class.new(ActiveRecord::Base) do
- enum status: [:grounded, :operational]
+ klass1 = Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+ enum status: [:proposed, :written]
+ end
+
+ klass2 = Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+ enum status: [:drafted, :uploaded]
end
- assert_equal({ "proposed" => 0, "written" => 1, "published" => 2 }, Book.statuses)
- assert_equal({ "grounded" => 0, "operational" => 1 }, Plane.statuses)
+
+ book1 = klass1.proposed.create!
+ book1.status = :written
+ assert_equal ['proposed', 'written'], book1.status_change
+
+ book2 = klass2.drafted.create!
+ book2.status = :uploaded
+ assert_equal ['drafted', 'uploaded'], book2.status_change
end
test "enums are inheritable" do
- Encyclopedia = Class.new(Book) do
- enum status: [:published, :reprinted]
+ subklass1 = Class.new(Book)
+
+ subklass2 = Class.new(Book) do
+ enum status: [:drafted, :uploaded]
end
- assert_equal({ "published" => 0, "reprinted" => 1 }, Encyclopedia.statuses)
+
+ book1 = subklass1.proposed.create!
+ book1.status = :written
+ assert_equal ['proposed', 'written'], book1.status_change
+
+ book2 = subklass2.drafted.create!
+ book2.status = :uploaded
+ assert_equal ['drafted', 'uploaded'], book2.status_change
end
end
View
@@ -1,3 +1,37 @@
+* Fixed `ActiveSupport::Duration#eql?` so that `1.second.eql?(1.second)` is
+ true.
+
+ This fixes the current situation of:
+
+ 1.second.eql?(1.second) #=> false
+
+ `eql?` also requires that the other object is an `ActiveSupport::Duration`.
+ This requirement makes `ActiveSupport::Duration`'s behavior consistent with
+ the behavior of Ruby's numeric types:
+
+ 1.eql?(1.0) #=> false
+ 1.0.eql?(1) #=> false
+
+ 1.second.eql?(1) #=> false (was true)
+ 1.eql?(1.second) #=> false
+
+ { 1 => "foo", 1.0 => "bar" }
+ #=> { 1 => "foo", 1.0 => "bar" }
+
+ { 1 => "foo", 1.second => "bar" }
+ # now => { 1 => "foo", 1.second => "bar" }
+ # was => { 1 => "bar" }
+
+ And though the behavior of these hasn't changed, for reference:
+
+ 1 == 1.0 #=> true
+ 1.0 == 1 #=> true
+
+ 1 == 1.second #=> true
+ 1.second == 1 #=> true
+
+ *Emily Dobervich*
+
* `ActiveSupport::SafeBuffer#prepend` acts like `String#prepend` and modifies
instance in-place, returning self. `ActiveSupport::SafeBuffer#prepend!` is
deprecated.
@@ -1,5 +1,6 @@
require 'active_support/core_ext/object/duplicable'
require 'active_support/core_ext/string/inflections'
+require 'active_support/per_thread_registry'
module ActiveSupport
module Cache
@@ -49,6 +49,10 @@ def ==(other)
end
end
+ def eql?(other)
+ other.is_a?(Duration) && self == other
+ end
+
def self.===(other) #:nodoc:
other.is_a?(Duration)
rescue ::NoMethodError
Oops, something went wrong.

0 comments on commit db5e578

Please sign in to comment.