diff options
author | Sean Griffin <sean@thoughtbot.com> | 2014-12-26 15:33:57 -0700 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2014-12-26 15:33:57 -0700 |
commit | 3179b4a868c370bf879c15c53b78f25fadec9b41 (patch) | |
tree | 5f8fa85b609f182cfbb9c2d4985c93a981208c2a /activerecord | |
parent | a60770d3bf3a8aeac16c110f3a7d05a6d52a86d6 (diff) | |
download | rails-3179b4a868c370bf879c15c53b78f25fadec9b41.tar.gz rails-3179b4a868c370bf879c15c53b78f25fadec9b41.tar.bz2 rails-3179b4a868c370bf879c15c53b78f25fadec9b41.zip |
Perform casting of single values within the predicate builder
As part of the larger refactoring to remove type casting from Arel, we
need to do the casting of values eagerly. The predicate builder is the
closest place that knows about the Active Record class, and can
therefore have the type information.
/cc @mrgilman
[Sean Griffin & Melanie Gilman]
Diffstat (limited to 'activerecord')
6 files changed, 38 insertions, 7 deletions
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 65c4c11e64..fc2cc11c08 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -8,15 +8,15 @@ module ActiveRecord require 'active_record/relation/predicate_builder/range_handler' require 'active_record/relation/predicate_builder/relation_handler' - delegate :resolve_column_aliases, to: :table + delegate :resolve_column_aliases, :type_cast_for_database, to: :table def initialize(table) @table = table @handlers = [] - register_handler(BasicObject, BasicObjectHandler.new) - register_handler(Class, ClassHandler.new) - register_handler(Base, BaseHandler.new) + register_handler(BasicObject, BasicObjectHandler.new(self)) + register_handler(Class, ClassHandler.new(self)) + register_handler(Base, BaseHandler.new(self)) register_handler(Range, RangeHandler.new) register_handler(Relation, RelationHandler.new) register_handler(Array, ArrayHandler.new(self)) diff --git a/activerecord/lib/active_record/relation/predicate_builder/base_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/base_handler.rb index d50ea519f9..6fa5b16f73 100644 --- a/activerecord/lib/active_record/relation/predicate_builder/base_handler.rb +++ b/activerecord/lib/active_record/relation/predicate_builder/base_handler.rb @@ -1,9 +1,17 @@ module ActiveRecord class PredicateBuilder class BaseHandler # :nodoc: + def initialize(predicate_builder) + @predicate_builder = predicate_builder + end + def call(attribute, value) - attribute.eq(value.id) + predicate_builder.build(attribute, value.id) end + + protected + + attr_reader :predicate_builder end end end diff --git a/activerecord/lib/active_record/relation/predicate_builder/basic_object_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/basic_object_handler.rb index 79cde00303..57a8b63001 100644 --- a/activerecord/lib/active_record/relation/predicate_builder/basic_object_handler.rb +++ b/activerecord/lib/active_record/relation/predicate_builder/basic_object_handler.rb @@ -1,9 +1,18 @@ module ActiveRecord class PredicateBuilder class BasicObjectHandler # :nodoc: + def initialize(predicate_builder) + @predicate_builder = predicate_builder + end + def call(attribute, value) + value = predicate_builder.type_cast_for_database(attribute.name, value) attribute.eq(value) end + + protected + + attr_reader :predicate_builder end end end diff --git a/activerecord/lib/active_record/relation/predicate_builder/class_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/class_handler.rb index 3fe1642ed0..ed313fc9d4 100644 --- a/activerecord/lib/active_record/relation/predicate_builder/class_handler.rb +++ b/activerecord/lib/active_record/relation/predicate_builder/class_handler.rb @@ -1,11 +1,19 @@ module ActiveRecord class PredicateBuilder class ClassHandler # :nodoc: + def initialize(predicate_builder) + @predicate_builder = predicate_builder + end + def call(attribute, value) print_deprecation_warning - attribute.eq(value.name) + predicate_builder.build(attribute, value.name) end + protected + + attr_reader :predicate_builder + private def print_deprecation_warning diff --git a/activerecord/lib/active_record/table_metadata.rb b/activerecord/lib/active_record/table_metadata.rb index bf705d3565..811e6964a9 100644 --- a/activerecord/lib/active_record/table_metadata.rb +++ b/activerecord/lib/active_record/table_metadata.rb @@ -8,6 +8,12 @@ module ActiveRecord @association = association end + def type_cast_for_database(attribute_name, value) + return value if value.is_a?(Arel::Nodes::BindParam) || klass.nil? + type = klass.type_for_attribute(attribute_name.to_s) + Arel::Nodes::Quoted.new(type.type_cast_for_database(value)) + end + def resolve_column_aliases(hash) hash = hash.dup hash.keys.grep(Symbol) do |key| diff --git a/activerecord/test/cases/relation/where_chain_test.rb b/activerecord/test/cases/relation/where_chain_test.rb index 619055f1e7..3a02e8230d 100644 --- a/activerecord/test/cases/relation/where_chain_test.rb +++ b/activerecord/test/cases/relation/where_chain_test.rb @@ -24,7 +24,7 @@ module ActiveRecord end def test_not_null - expected = Post.arel_table[@name].not_eq(nil) + expected = Post.arel_table[@name].not_eq(Arel::Nodes::Quoted.new(nil)) relation = Post.where.not(title: nil) assert_equal([expected], relation.where_values) end |