Permalink
Browse files

active_record: Type cast booleans and durations for string columns.

  • Loading branch information...
1 parent 93e24de commit 42be84ba40d95561554a4ccd62f482b028454025 @dylanahsmith dylanahsmith committed Jul 6, 2014
View
@@ -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.
@@ -24,7 +24,7 @@ def type_cast_for_database(value)
class Data # :nodoc:
def initialize(value)
- @value = value
+ @value = value.to_s
end
def to_s
@@ -17,8 +17,10 @@ def changed_in_place?(raw_old_value, new_value)
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
@@ -47,7 +47,7 @@ class BooleanType < ActiveRecord::Base
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 BooleanType < ActiveRecord::Base
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
@@ -6,10 +6,11 @@
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 @@ def test_where_with_blank_conditions
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

0 comments on commit 42be84b

Please sign in to comment.