aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkamille-321 <yuji.kmjm@gmail.com>2019-02-19 11:50:31 +0900
committerkamille-321 <yuji.kmjm@gmail.com>2019-03-11 00:51:33 +0900
commit81bc621ed01637e8305fb53c9e504b1cc46c102f (patch)
treef0404468ccf06a3df9bd8fbd6bafb55a34ecce6d
parentb75d6ea5d35d61c60f2675ed956c51e71d2b07ad (diff)
downloadrails-81bc621ed01637e8305fb53c9e504b1cc46c102f.tar.gz
rails-81bc621ed01637e8305fb53c9e504b1cc46c102f.tar.bz2
rails-81bc621ed01637e8305fb53c9e504b1cc46c102f.zip
Fix query attribute method on user-defined attribute to be aware of typecasted value
change the line to check an attribute has user-defined type ref: https://github.com/rails/rails/pull/35320#discussion_r257924552 check query attribute method is working when given value does not respond to to_i method
-rw-r--r--activerecord/CHANGELOG.md14
-rw-r--r--activerecord/lib/active_record/attribute_methods/query.rb3
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb63
3 files changed, 78 insertions, 2 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index c0ef3cbe7c..a318cd3661 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,17 @@
+* Fix query attribute method on user-defined attribute to be aware of typecasted value.
+
+ For example the following code no longer return false as casted non-empty string.
+
+ ```
+ class Post < ActiveRecord::Base
+ attribute :user_defined_text, :text
+ end
+
+ Post.new(user_defined_text: "false").user_defined_text? # => true
+ ```
+
+ *Yuji Kamijima*
+
* Quote empty ranges like other empty enumerables.
*Patrick Rebsch*
diff --git a/activerecord/lib/active_record/attribute_methods/query.rb b/activerecord/lib/active_record/attribute_methods/query.rb
index 6757e9b66a..6811f54b10 100644
--- a/activerecord/lib/active_record/attribute_methods/query.rb
+++ b/activerecord/lib/active_record/attribute_methods/query.rb
@@ -16,8 +16,7 @@ module ActiveRecord
when true then true
when false, nil then false
else
- column = self.class.columns_hash[attr_name]
- if column.nil?
+ if !type_for_attribute(attr_name) { false }
if Numeric === value || value !~ /[^0-9]/
!value.to_i.zero?
else
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index 12ff6d4826..b7519bab81 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -439,6 +439,22 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
+ test "user defined text attribute predicate" do
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = Topic.table_name
+
+ attribute :user_defined_text, :text
+ end
+
+ topic = klass.new(user_defined_text: "text")
+ assert_predicate topic, :user_defined_text?
+
+ ActiveModel::Type::Boolean::FALSE_VALUES.each do |value|
+ topic = klass.new(user_defined_text: value)
+ assert_predicate topic, :user_defined_text?
+ end
+ end
+
test "number attribute predicate" do
[nil, 0, "0"].each do |value|
assert_equal false, Developer.new(salary: value).salary?
@@ -458,6 +474,53 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
+ test "user defined date attribute predicate" do
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = Topic.table_name
+
+ attribute :user_defined_date, :date
+ end
+
+ topic = klass.new(user_defined_date: Date.current)
+ assert_predicate topic, :user_defined_date?
+ end
+
+ test "user defined datetime attribute predicate" do
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = Topic.table_name
+
+ attribute :user_defined_datetime, :datetime
+ end
+
+ topic = klass.new(user_defined_datetime: Time.current)
+ assert_predicate topic, :user_defined_datetime?
+ end
+
+ test "user defined time attribute predicate" do
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = Topic.table_name
+
+ attribute :user_defined_time, :time
+ end
+
+ topic = klass.new(user_defined_time: Time.current)
+ assert_predicate topic, :user_defined_time?
+ end
+
+ test "user defined json attribute predicate" do
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = Topic.table_name
+
+ attribute :user_defined_json, :json
+ end
+
+ topic = klass.new(user_defined_json: { key: "value" })
+ assert_predicate topic, :user_defined_json?
+
+ topic = klass.new(user_defined_json: {})
+ assert_not_predicate topic, :user_defined_json?
+ end
+
test "custom field attribute predicate" do
object = Company.find_by_sql(<<~SQL).first
SELECT c1.*, c2.type as string_value, c2.rating as int_value