aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/attribute_methods
diff options
context:
space:
mode:
authorCarlos Antonio da Silva <carlosantoniodasilva@gmail.com>2013-01-07 21:39:10 -0200
committerCarlos Antonio da Silva <carlosantoniodasilva@gmail.com>2013-01-07 21:54:49 -0200
commitc75b5a88a82c79fdf95dfea4d72bf3c5a829930e (patch)
treefde52ac75334414ecbf54089cb28a174a03b458d /activerecord/lib/active_record/attribute_methods
parent3aebe13b1b9c159e3598f49c104029c9bb89e0c5 (diff)
downloadrails-c75b5a88a82c79fdf95dfea4d72bf3c5a829930e.tar.gz
rails-c75b5a88a82c79fdf95dfea4d72bf3c5a829930e.tar.bz2
rails-c75b5a88a82c79fdf95dfea4d72bf3c5a829930e.zip
Refactor write attribute logic to convert number column value
This is an improvement for issue #8673: "Comparing a BigDecimal to true/false on write_attribute is slow" It seems to be an issue with Ruby itself, related to the "coerce" method being called in TrueClass/FalseClass due to the == condition, triggering method_missing, then raising a NameError that's later catched. This issue was also opened in Ruby tracker: https://bugs.ruby-lang.org/issues/7645. This refactoring avoid the coerce call by using a case statement, which gives us better readability as well. A simple benchmark: ---------- require 'benchmark/ips' require 'bigdecimal' Benchmark.ips do |x| x.report("== true") { BigDecimal('3') == true } x.report("TrueClass") { TrueClass === BigDecimal('3') } x.report("== 0") { BigDecimal('3') == 0 } x.report("Numeric") { Numeric === BigDecimal('3') } end Calculating ------------------------------------- == true 6427 i/100ms TrueClass 47297 i/100ms == 0 35923 i/100ms Numeric 55530 i/100ms ------------------------------------------------- == true 75878.5 (±21.6%) i/s - 359912 in 5.004392s TrueClass 1249547.0 (±13.1%) i/s - 6148610 in 5.035964s == 0 666856.3 (±13.3%) i/s - 3268993 in 5.013789s Numeric 1269300.9 (±11.3%) i/s - 6274890 in 5.028458s ---------- Master has a very different implementation, and there are apparently no similar conversions at this point, it's mainly delegated to the column type cast, but I'll check if something needs to be changed there as well. Closes #8673.
Diffstat (limited to 'activerecord/lib/active_record/attribute_methods')
-rw-r--r--activerecord/lib/active_record/attribute_methods/write.rb9
1 files changed, 5 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb
index 8c6fa90a28..16aed7348f 100644
--- a/activerecord/lib/active_record/attribute_methods/write.rb
+++ b/activerecord/lib/active_record/attribute_methods/write.rb
@@ -54,12 +54,13 @@ module ActiveRecord
end
def convert_number_column_value(value)
- if value == false
+ case value
+ when FalseClass
0
- elsif value == true
+ when TrueClass
1
- elsif value.is_a?(String) && value.blank?
- nil
+ when String
+ value.presence
else
value
end