aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDylan Thacker-Smith <Dylan.Smith@shopify.com>2014-07-06 01:49:19 -0400
committerDylan Thacker-Smith <Dylan.Smith@shopify.com>2014-07-06 02:43:34 -0400
commit42be84ba40d95561554a4ccd62f482b028454025 (patch)
tree8357e189744a38339c730a8dce039bdf6e6c6156
parent93e24dea60368db17f92eac79122b36c30655297 (diff)
downloadrails-42be84ba40d95561554a4ccd62f482b028454025.tar.gz
rails-42be84ba40d95561554a4ccd62f482b028454025.tar.bz2
rails-42be84ba40d95561554a4ccd62f482b028454025.zip
active_record: Type cast booleans and durations for string columns.
-rw-r--r--activerecord/CHANGELOG.md11
-rw-r--r--activerecord/lib/active_record/type/binary.rb2
-rw-r--r--activerecord/lib/active_record/type/string.rb4
-rw-r--r--activerecord/test/cases/adapters/mysql2/boolean_test.rb4
-rw-r--r--activerecord/test/cases/relation/where_test.rb33
5 files changed, 49 insertions, 5 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 21075d0636..42f2b72a08 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,14 @@
+* Avoid type casting boolean and ActiveSupport::Duration values to numeric
+ values for string columns. Otherwise, in some database, the string column
+ values will be coerced to a numeric allowing false or 0.seconds match any
+ string starting with a non-digit.
+
+ Example:
+
+ App.where(apikey: false) # => SELECT * FROM users WHERE apikey = '0'
+
+ *Dylan Thacker-Smith*
+
* Add a `:required` option to singular associations, providing a nicer
API for presence validations on associations.
diff --git a/activerecord/lib/active_record/type/binary.rb b/activerecord/lib/active_record/type/binary.rb
index 7416c554c7..d29ff4e494 100644
--- a/activerecord/lib/active_record/type/binary.rb
+++ b/activerecord/lib/active_record/type/binary.rb
@@ -24,7 +24,7 @@ module ActiveRecord
class Data # :nodoc:
def initialize(value)
- @value = value
+ @value = value.to_s
end
def to_s
diff --git a/activerecord/lib/active_record/type/string.rb b/activerecord/lib/active_record/type/string.rb
index 8cc533bc41..e1791169d8 100644
--- a/activerecord/lib/active_record/type/string.rb
+++ b/activerecord/lib/active_record/type/string.rb
@@ -17,8 +17,10 @@ module ActiveRecord
def type_cast_for_database(value)
case value
- when ::Numeric then value.to_s
+ when ::Numeric, ActiveSupport::Duration then value.to_s
when ::String then ::String.new(value)
+ when true then "1"
+ when false then "0"
else super
end
end
diff --git a/activerecord/test/cases/adapters/mysql2/boolean_test.rb b/activerecord/test/cases/adapters/mysql2/boolean_test.rb
index 267aa232d9..f3c711a64b 100644
--- a/activerecord/test/cases/adapters/mysql2/boolean_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/boolean_test.rb
@@ -47,7 +47,7 @@ class Mysql2BooleanTest < ActiveRecord::TestCase
assert_equal "1", attributes["published"]
assert_equal 1, @connection.type_cast(true, boolean_column)
- assert_equal 1, @connection.type_cast(true, string_column)
+ assert_equal "1", @connection.type_cast(true, string_column)
end
test "test type casting without emulated booleans" do
@@ -60,7 +60,7 @@ class Mysql2BooleanTest < ActiveRecord::TestCase
assert_equal "1", attributes["published"]
assert_equal 1, @connection.type_cast(true, boolean_column)
- assert_equal 1, @connection.type_cast(true, string_column)
+ assert_equal "1", @connection.type_cast(true, string_column)
end
test "with booleans stored as 1 and 0" do
diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb
index 937f226b1d..a6a36a6fd9 100644
--- a/activerecord/test/cases/relation/where_test.rb
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -6,10 +6,11 @@ require 'models/post'
require 'models/comment'
require 'models/edge'
require 'models/topic'
+require 'models/binary'
module ActiveRecord
class WhereTest < ActiveRecord::TestCase
- fixtures :posts, :edges, :authors
+ fixtures :posts, :edges, :authors, :binaries
def test_where_copies_bind_params
author = authors(:david)
@@ -179,5 +180,35 @@ module ActiveRecord
assert_equal 4, Edge.where(blank).order("sink_id").to_a.size
end
end
+
+ def test_where_with_integer_for_string_column
+ count = Post.where(:title => 0).count
+ assert_equal 0, count
+ end
+
+ def test_where_with_float_for_string_column
+ count = Post.where(:title => 0.0).count
+ assert_equal 0, count
+ end
+
+ def test_where_with_boolean_for_string_column
+ count = Post.where(:title => false).count
+ assert_equal 0, count
+ end
+
+ def test_where_with_decimal_for_string_column
+ count = Post.where(:title => BigDecimal.new(0)).count
+ assert_equal 0, count
+ end
+
+ def test_where_with_duration_for_string_column
+ count = Post.where(:title => 0.seconds).count
+ assert_equal 0, count
+ end
+
+ def test_where_with_integer_for_binary_column
+ count = Binary.where(:data => 0).count
+ assert_equal 0, count
+ end
end
end