aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md8
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb9
-rw-r--r--activerecord/test/cases/adapters/mysql/active_schema_test.rb9
-rw-r--r--activerecord/test/cases/adapters/mysql/connection_test.rb11
-rw-r--r--activerecord/test/cases/adapters/mysql2/active_schema_test.rb9
-rw-r--r--activerecord/test/cases/adapters/mysql2/connection_test.rb14
-rw-r--r--activerecord/test/cases/adapters/postgresql/connection_test.rb15
-rw-r--r--activerecord/test/cases/adapters/postgresql/domain_test.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/enum_test.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/range_test.rb16
-rw-r--r--activerecord/test/cases/adapters/postgresql/uuid_test.rb5
-rw-r--r--activerecord/test/support/connection_helper.rb14
-rw-r--r--activerecord/test/support/postgresql_helper.rb8
-rw-r--r--activesupport/CHANGELOG.md6
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb16
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb23
-rw-r--r--guides/CHANGELOG.md4
-rw-r--r--guides/source/active_record_querying.md59
-rw-r--r--guides/source/i18n.md9
-rw-r--r--guides/source/upgrading_ruby_on_rails.md6
20 files changed, 144 insertions, 109 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index acd3d395c5..f7718394af 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,11 @@
+* Treat blank UUID values as `nil`.
+
+ Example:
+
+ Sample.new(uuid_field: '') #=> <Sample id: nil, uuid_field: nil>
+
+ *Dmitry Lavrov*
+
* Enable support for materialized views on PostgreSQL >= 9.3.
*Dave Lee*
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index 57bdc3bb19..9e898015a6 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -330,6 +330,13 @@ This is not reliable and will be removed in the future.
end
end
+ class Uuid < Type
+ def type; :uuid end
+ def type_cast(value)
+ value.presence
+ end
+ end
+
class TypeMap
def initialize
@mapping = {}
@@ -418,10 +425,10 @@ This is not reliable and will be removed in the future.
register_type 'json', OID::Json.new
register_type 'cidr', OID::Cidr.new
register_type 'inet', OID::Inet.new
+ register_type 'uuid', OID::Uuid.new
register_type 'xml', SpecializedString.new(:xml)
register_type 'tsvector', SpecializedString.new(:tsvector)
register_type 'macaddr', SpecializedString.new(:macaddr)
- register_type 'uuid', SpecializedString.new(:uuid)
register_type 'citext', SpecializedString.new(:citext)
register_type 'ltree', SpecializedString.new(:ltree)
diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
index d1c644c016..7c0f11b033 100644
--- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
@@ -1,10 +1,10 @@
require "cases/helper"
+require 'support/connection_helper'
class ActiveSchemaTest < ActiveRecord::TestCase
- def setup
- @connection = ActiveRecord::Base.remove_connection
- ActiveRecord::Base.establish_connection(@connection)
+ include ConnectionHelper
+ def setup
ActiveRecord::Base.connection.singleton_class.class_eval do
alias_method :execute_without_stub, :execute
def execute(sql, name = nil) return sql end
@@ -12,8 +12,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase
end
teardown do
- ActiveRecord::Base.remove_connection
- ActiveRecord::Base.establish_connection(@connection)
+ reset_connection
end
def test_add_index
diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb
index 42ffb91095..412efa22ff 100644
--- a/activerecord/test/cases/adapters/mysql/connection_test.rb
+++ b/activerecord/test/cases/adapters/mysql/connection_test.rb
@@ -1,7 +1,9 @@
require "cases/helper"
+require 'support/connection_helper'
require 'support/ddl_helper'
class MysqlConnectionTest < ActiveRecord::TestCase
+ include ConnectionHelper
include DdlHelper
class Klass < ActiveRecord::Base
@@ -160,15 +162,6 @@ class MysqlConnectionTest < ActiveRecord::TestCase
private
- def run_without_connection
- original_connection = ActiveRecord::Base.remove_connection
- begin
- yield original_connection
- ensure
- ActiveRecord::Base.establish_connection(original_connection)
- end
- end
-
def with_example_table(&block)
definition ||= <<-SQL
`id` int(11) auto_increment PRIMARY KEY,
diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
index 81c614924f..cefc3e3c7e 100644
--- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
@@ -1,10 +1,10 @@
require "cases/helper"
+require 'support/connection_helper'
class ActiveSchemaTest < ActiveRecord::TestCase
- def setup
- @connection = ActiveRecord::Base.remove_connection
- ActiveRecord::Base.establish_connection(@connection)
+ include ConnectionHelper
+ def setup
ActiveRecord::Base.connection.singleton_class.class_eval do
alias_method :execute_without_stub, :execute
def execute(sql, name = nil) return sql end
@@ -12,8 +12,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase
end
teardown do
- ActiveRecord::Base.remove_connection
- ActiveRecord::Base.establish_connection(@connection)
+ reset_connection
end
def test_add_index
diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb
index 57d8b8dd99..182d9409c7 100644
--- a/activerecord/test/cases/adapters/mysql2/connection_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb
@@ -1,6 +1,9 @@
require "cases/helper"
+require 'support/connection_helper'
class MysqlConnectionTest < ActiveRecord::TestCase
+ include ConnectionHelper
+
def setup
super
@subscriber = SQLSubscriber.new
@@ -103,15 +106,4 @@ class MysqlConnectionTest < ActiveRecord::TestCase
assert_equal "'1970-01-01 00:00:00.000000'", @connection.quote(Time.at(0).to_datetime)
end
end
-
- private
-
- def run_without_connection
- original_connection = ActiveRecord::Base.remove_connection
- begin
- yield original_connection
- ensure
- ActiveRecord::Base.establish_connection(original_connection)
- end
- end
end
diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb
index 514ae20e3c..5f84c893c0 100644
--- a/activerecord/test/cases/adapters/postgresql/connection_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb
@@ -1,7 +1,10 @@
require "cases/helper"
+require 'support/connection_helper'
module ActiveRecord
class PostgresqlConnectionTest < ActiveRecord::TestCase
+ include ConnectionHelper
+
class NonExistentTable < ActiveRecord::Base
end
@@ -198,17 +201,5 @@ module ActiveRecord
ActiveRecord::Base.establish_connection(orig_connection.deep_merge({:variables => {:debug_print_plan => :default}}))
end
end
-
- private
-
- def run_without_connection
- original_connection = ActiveRecord::Base.remove_connection
- begin
- yield original_connection
- ensure
- ActiveRecord::Base.establish_connection(original_connection)
- end
- end
-
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/domain_test.rb b/activerecord/test/cases/adapters/postgresql/domain_test.rb
index ba25a64fac..214e89dd7f 100644
--- a/activerecord/test/cases/adapters/postgresql/domain_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/domain_test.rb
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
require "cases/helper"
-require 'support/postgresql_helper'
+require 'support/connection_helper'
require 'active_record/base'
require 'active_record/connection_adapters/postgresql_adapter'
class PostgresqlDomainTest < ActiveRecord::TestCase
- include PostgresqlHelper
+ include ConnectionHelper
class PostgresqlDomain < ActiveRecord::Base
self.table_name = "postgresql_domains"
@@ -27,7 +27,7 @@ class PostgresqlDomainTest < ActiveRecord::TestCase
teardown do
@connection.execute 'DROP TABLE IF EXISTS postgresql_domains'
@connection.execute 'DROP DOMAIN IF EXISTS custom_money'
- reset_pg_session
+ reset_connection
end
def test_column
diff --git a/activerecord/test/cases/adapters/postgresql/enum_test.rb b/activerecord/test/cases/adapters/postgresql/enum_test.rb
index fde01314a5..73da5a74ab 100644
--- a/activerecord/test/cases/adapters/postgresql/enum_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/enum_test.rb
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
require "cases/helper"
-require 'support/postgresql_helper'
+require 'support/connection_helper'
require 'active_record/base'
require 'active_record/connection_adapters/postgresql_adapter'
class PostgresqlEnumTest < ActiveRecord::TestCase
- include PostgresqlHelper
+ include ConnectionHelper
class PostgresqlEnum < ActiveRecord::Base
self.table_name = "postgresql_enums"
@@ -28,7 +28,7 @@ class PostgresqlEnumTest < ActiveRecord::TestCase
teardown do
@connection.execute 'DROP TABLE IF EXISTS postgresql_enums'
@connection.execute 'DROP TYPE IF EXISTS mood'
- reset_pg_session
+ reset_connection
end
def test_column
diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb
index b57568dbad..57c7da2657 100644
--- a/activerecord/test/cases/adapters/postgresql/range_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/range_test.rb
@@ -1,5 +1,5 @@
require "cases/helper"
-require 'support/postgresql_helper'
+require 'support/connection_helper'
require 'active_record/base'
require 'active_record/connection_adapters/postgresql_adapter'
@@ -10,13 +10,7 @@ if ActiveRecord::Base.connection.supports_ranges?
class PostgresqlRangeTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
- include PostgresqlHelper
-
- teardown do
- @connection.execute 'DROP TABLE IF EXISTS postgresql_ranges'
- @connection.execute 'DROP TYPE IF EXISTS floatrange'
- reset_pg_session
- end
+ include ConnectionHelper
def setup
@connection = PostgresqlRange.connection
@@ -99,6 +93,12 @@ _SQL
@empty_range = PostgresqlRange.find(105)
end
+ teardown do
+ @connection.execute 'DROP TABLE IF EXISTS postgresql_ranges'
+ @connection.execute 'DROP TYPE IF EXISTS floatrange'
+ reset_connection
+ end
+
def test_data_type_of_range_types
assert_equal :daterange, @first_range.column_for_attribute(:date_range).type
assert_equal :numrange, @first_range.column_for_attribute(:num_range).type
diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
index f79a7a598b..9e03ea6bee 100644
--- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
@@ -50,6 +50,11 @@ class PostgresqlUUIDTest < ActiveRecord::TestCase
assert_not column.array
end
+ def test_treat_blank_uuid_as_nil
+ UUIDType.create! guid: ''
+ assert_equal(nil, UUIDType.last.guid)
+ end
+
def test_uuid_formats
["A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11",
"{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}",
diff --git a/activerecord/test/support/connection_helper.rb b/activerecord/test/support/connection_helper.rb
new file mode 100644
index 0000000000..4a19e5df44
--- /dev/null
+++ b/activerecord/test/support/connection_helper.rb
@@ -0,0 +1,14 @@
+module ConnectionHelper
+ def run_without_connection
+ original_connection = ActiveRecord::Base.remove_connection
+ yield original_connection
+ ensure
+ ActiveRecord::Base.establish_connection(original_connection)
+ end
+
+ # Used to drop all cache query plans in tests.
+ def reset_connection
+ original_connection = ActiveRecord::Base.remove_connection
+ ActiveRecord::Base.establish_connection(original_connection)
+ end
+end
diff --git a/activerecord/test/support/postgresql_helper.rb b/activerecord/test/support/postgresql_helper.rb
deleted file mode 100644
index fa40a46499..0000000000
--- a/activerecord/test/support/postgresql_helper.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-module PostgresqlHelper
- # Make sure to drop all cached query plans to prevent invalid reference errors like:
- # cache lookup failed for type XYZ
- def reset_pg_session
- original_connection = ActiveRecord::Base.remove_connection
- ActiveRecord::Base.establish_connection(original_connection)
- end
-end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 556e94d184..f65d9ea120 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,9 @@
+* `ActiveSupport::SafeBuffer#prepend` acts like `String#prepend` and modifies
+ instance in-place, returning self. `ActiveSupport::SafeBuffer#prepend!` is
+ deprecated.
+
+ *Pavel Pravosud*
+
* `HashWithIndifferentAccess` better respects `#to_hash` on objects it's
given. In particular, `.new`, `#update`, `#merge`, `#replace` all accept
objects which respond to `#to_hash`, even if those objects are not Hashes
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb
index eb02b6a442..2c8995be9a 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -1,5 +1,6 @@
require 'erb'
require 'active_support/core_ext/kernel/singleton_class'
+require 'active_support/deprecation'
class ERB
module Util
@@ -124,7 +125,7 @@ module ActiveSupport #:nodoc:
class SafeBuffer < String
UNSAFE_STRING_METHODS = %w(
capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
- slice squeeze strip sub succ swapcase tr tr_s upcase prepend
+ slice squeeze strip sub succ swapcase tr tr_s upcase
)
alias_method :original_concat, :concat
@@ -169,15 +170,18 @@ module ActiveSupport #:nodoc:
self[0, 0]
end
- def concat(value)
- if !html_safe? || value.html_safe?
- super(value)
- else
- super(ERB::Util.h(value))
+ %w[concat prepend].each do |method_name|
+ define_method method_name do |value|
+ super(html_escape_interpolated_argument(value))
end
end
alias << concat
+ def prepend!(value)
+ ActiveSupport::Deprecation.deprecation_warning "ActiveSupport::SafeBuffer#prepend!", :prepend
+ prepend value
+ end
+
def +(other)
dup.concat(other)
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 072b970a2d..ea12f1ced5 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -608,6 +608,29 @@ class OutputSafetyTest < ActiveSupport::TestCase
assert !@other_combination.html_safe?
end
+ test "Prepending safe onto unsafe yields unsafe" do
+ @string.prepend "other".html_safe
+ assert !@string.html_safe?
+ assert_equal @string, "otherhello"
+ end
+
+ test "Prepending unsafe onto safe yields escaped safe" do
+ other = "other".html_safe
+ other.prepend "<foo>"
+ assert other.html_safe?
+ assert_equal other, "&lt;foo&gt;other"
+ end
+
+ test "Deprecated #prepend! method is still present" do
+ other = "other".html_safe
+
+ assert_deprecated do
+ other.prepend! "<foo>"
+ end
+
+ assert_equal other, "&lt;foo&gt;other"
+ end
+
test "Concatting safe onto unsafe yields unsafe" do
@other_string = "other"
diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md
index a7c215c295..246e1d3b96 100644
--- a/guides/CHANGELOG.md
+++ b/guides/CHANGELOG.md
@@ -1 +1,5 @@
+* Switched the order of `Applying a default scope` and `Merging of scopes` subsections so default scopes are introduced first.
+
+ *Alex Riabov*
+
Please check [4-1-stable](https://github.com/rails/rails/blob/4-1-stable/guides/CHANGELOG.md) for previous changes.
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 0a332d7dd9..2a76df156c 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1231,6 +1231,35 @@ Using a class method is the preferred way to accept arguments for scopes. These
category.posts.created_before(time)
```
+### Applying a default scope
+
+If we wish for a scope to be applied across all queries to the model we can use the
+`default_scope` method within the model itself.
+
+```ruby
+class Client < ActiveRecord::Base
+ default_scope { where("removed_at IS NULL") }
+end
+```
+
+When queries are executed on this model, the SQL query will now look something like
+this:
+
+```sql
+SELECT * FROM clients WHERE removed_at IS NULL
+```
+
+If you need to do more complex things with a default scope, you can alternatively
+define it as a class method:
+
+```ruby
+class Client < ActiveRecord::Base
+ def self.default_scope
+ # Should return an ActiveRecord::Relation.
+ end
+end
+```
+
### Merging of scopes
Just like `where` clauses scopes are merged using `AND` conditions.
@@ -1284,36 +1313,6 @@ User.where(state: 'inactive')
As you can see above the `default_scope` is being merged in both
`scope` and `where` conditions.
-
-### Applying a default scope
-
-If we wish for a scope to be applied across all queries to the model we can use the
-`default_scope` method within the model itself.
-
-```ruby
-class Client < ActiveRecord::Base
- default_scope { where("removed_at IS NULL") }
-end
-```
-
-When queries are executed on this model, the SQL query will now look something like
-this:
-
-```sql
-SELECT * FROM clients WHERE removed_at IS NULL
-```
-
-If you need to do more complex things with a default scope, you can alternatively
-define it as a class method:
-
-```ruby
-class Client < ActiveRecord::Base
- def self.default_scope
- # Should return an ActiveRecord::Relation.
- end
-end
-```
-
### Removing All Scoping
If we wish to remove scoping for any reason we can use the `unscoped` method. This is
diff --git a/guides/source/i18n.md b/guides/source/i18n.md
index bef738b75b..6bd033f0de 100644
--- a/guides/source/i18n.md
+++ b/guides/source/i18n.md
@@ -212,17 +212,16 @@ The most usual way of setting (and passing) the locale would be to include it in
This approach has almost the same set of advantages as setting the locale from the domain name: namely that it's RESTful and in accord with the rest of the World Wide Web. It does require a little bit more work to implement, though.
-Getting the locale from `params` and setting it accordingly is not hard; including it in every URL and thus **passing it through the requests** is. To include an explicit option in every URL (e.g. `link_to( books_url(locale: I18n.locale))`) would be tedious and probably impossible, of course.
+Getting the locale from `params` and setting it accordingly is not hard; including it in every URL and thus **passing it through the requests** is. To include an explicit option in every URL, e.g. `link_to(books_url(locale: I18n.locale))`, would be tedious and probably impossible, of course.
-Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its [`ApplicationController#default_url_options`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000515), which is useful precisely in this scenario: it enables us to set "defaults" for [`url_for`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000503) and helper methods dependent on it (by implementing/overriding this method).
+Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its [`ApplicationController#default_url_options`](http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Base.html#method-i-default_url_options), which is useful precisely in this scenario: it enables us to set "defaults" for [`url_for`](http://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html#method-i-url_for) and helper methods dependent on it (by implementing/overriding this method).
We can include something like this in our `ApplicationController` then:
```ruby
# app/controllers/application_controller.rb
-def default_url_options(options={})
- logger.debug "default_url_options is passed options: #{options.inspect}\n"
- { locale: I18n.locale }
+def default_url_options(options = {})
+ { locale: I18n.locale }.merge options
end
```
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index d58024df3d..88c9981dbb 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -104,9 +104,9 @@ Applications created before Rails 4.1 uses `Marshal` to serialize cookie values
the signed and encrypted cookie jars. If you want to use the new `JSON`-based format
in your application, you can add an initializer file with the following content:
- ```ruby
- Rails.application.config.cookies_serializer :hybrid
- ```
+```ruby
+Rails.application.config.action_dispatch.cookies_serializer = :hybrid
+```
This would transparently migrate your existing `Marshal`-serialized cookies into the
new `JSON`-based format.