aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb2
-rw-r--r--activerecord/lib/active_record/attributes.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb16
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb3
-rw-r--r--activerecord/lib/active_record/log_subscriber.rb4
-rw-r--r--activerecord/lib/active_record/relation.rb5
-rw-r--r--activerecord/lib/active_record/sanitization.rb7
-rw-r--r--activerecord/lib/active_record/secure_token.rb2
-rw-r--r--activerecord/lib/active_record/statement_cache.rb4
10 files changed, 40 insertions, 18 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index d5702accaf..ce7f575150 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -134,7 +134,7 @@ module ActiveRecord
# Serialized attributes should always be written in case they've been
# changed in place.
def keys_for_partial_write
- changed
+ changed & persistable_attribute_names
end
def _field_changed?(attr, old_value)
diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb
index aafb990bc1..b263a89d79 100644
--- a/activerecord/lib/active_record/attributes.rb
+++ b/activerecord/lib/active_record/attributes.rb
@@ -9,6 +9,8 @@ module ActiveRecord
class_attribute :user_provided_defaults, instance_accessor: false # :internal:
self.user_provided_columns = {}
self.user_provided_defaults = {}
+
+ delegate :persistable_attribute_names, to: :class
end
module ClassMethods # :nodoc:
@@ -96,6 +98,10 @@ module ActiveRecord
@columns_hash ||= Hash[columns.map { |c| [c.name, c] }]
end
+ def persistable_attribute_names # :nodoc:
+ @persistable_attribute_names ||= connection.schema_cache.columns_hash(table_name).keys
+ end
+
def reset_column_information # :nodoc:
super
clear_caches_calculated_from_columns
@@ -130,6 +136,7 @@ module ActiveRecord
@columns_hash = nil
@content_columns = nil
@default_attributes = nil
+ @persistable_attribute_names = nil
end
def raw_default_values
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
index 59cdd8e98c..6e631ed9f7 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -285,11 +285,11 @@ module ActiveRecord
def insert_fixture(fixture, table_name)
columns = schema_cache.columns_hash(table_name)
- key_list = []
- value_list = fixture.map do |name, value|
- key_list << quote_column_name(name)
- quote(value, columns[name])
+ binds = fixture.map do |name, value|
+ [columns[name], value]
end
+ key_list = fixture.keys.map { |name| quote_column_name(name) }
+ value_list = prepare_binds_for_database(binds).map { |_, value| quote(value) }
execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index 143d7d9574..7c1a779577 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -10,6 +10,12 @@ module ActiveRecord
return value.quoted_id if value.respond_to?(:quoted_id)
if column
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Passing a column to `quote` has been deprecated. It is only used
+ for type casting, which should be handled elsewhere. See
+ https://github.com/rails/arel/commit/6160bfbda1d1781c3b08a33ec4955f170e95be11
+ for more information.
+ MSG
value = column.cast_type.type_cast_for_database(value)
end
@@ -90,6 +96,16 @@ module ActiveRecord
value.to_s(:db)
end
+ def prepare_binds_for_database(binds) # :nodoc:
+ binds.map do |column, value|
+ if column
+ column_name = column.name
+ value = column.cast_type.type_cast_for_database(value)
+ end
+ [column_name, value]
+ end
+ end
+
private
def types_which_need_no_typecasting
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index e52b666296..c941c9f1eb 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -113,7 +113,8 @@ module ActiveRecord
class BindCollector < Arel::Collectors::Bind
def compile(bvs, conn)
- super(bvs.map { |bv| conn.quote(*bv.reverse) })
+ casted_binds = conn.prepare_binds_for_database(bvs)
+ super(casted_binds.map { |_, value| conn.quote(value) })
end
end
diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb
index eb64d197f0..a5c7279db9 100644
--- a/activerecord/lib/active_record/log_subscriber.rb
+++ b/activerecord/lib/active_record/log_subscriber.rb
@@ -22,10 +22,10 @@ module ActiveRecord
def render_bind(column, value)
if column
- if column.binary?
+ if column.binary? && value
# This specifically deals with the PG adapter that casts bytea columns into a Hash.
value = value[:value] if value.is_a?(Hash)
- value = value ? "<#{value.bytesize} bytes of binary data>" : "<NULL binary data>"
+ value = "<#{value.bytesize} bytes of binary data>"
end
[column.name, value]
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index ab3debc03b..dd78814c6a 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -558,8 +558,9 @@ module ActiveRecord
end
arel = relation.arel
- binds = (arel.bind_values + relation.bind_values).dup
- binds.map! { |bv| connection.quote(*bv.reverse) }
+ binds = arel.bind_values + relation.bind_values
+ binds = connection.prepare_binds_for_database(binds)
+ binds.map! { |_, value| connection.quote(value) }
collect = visitor.accept(arel.ast, Arel::Collectors::Bind.new)
collect.substitute_binds(binds).join
end
diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb
index 768a72a947..313e767dcb 100644
--- a/activerecord/lib/active_record/sanitization.rb
+++ b/activerecord/lib/active_record/sanitization.rb
@@ -3,14 +3,11 @@ module ActiveRecord
extend ActiveSupport::Concern
module ClassMethods
- def quote_value(value, column) #:nodoc:
- connection.quote(value, column)
- end
-
# Used to sanitize objects before they're used in an SQL SELECT statement. Delegates to <tt>connection.quote</tt>.
def sanitize(object) #:nodoc:
connection.quote(object)
end
+ alias_method :quote_value, :sanitize
protected
@@ -156,7 +153,7 @@ module ActiveRecord
# TODO: Deprecate this
def quoted_id
- self.class.quote_value(id, column_for_attribute(self.class.primary_key))
+ self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
end
end
end
diff --git a/activerecord/lib/active_record/secure_token.rb b/activerecord/lib/active_record/secure_token.rb
index b1a13fe673..be3c3bc847 100644
--- a/activerecord/lib/active_record/secure_token.rb
+++ b/activerecord/lib/active_record/secure_token.rb
@@ -24,7 +24,7 @@ module ActiveRecord
# validates_presence_of can. You're encouraged to add a unique index in the database to deal with
# this even more unlikely scenario.
def has_secure_token(attribute = :token)
- # Load securerandom only when has_secure_key is used.
+ # Load securerandom only when has_secure_token is used.
require 'active_support/core_ext/securerandom'
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) }
diff --git a/activerecord/lib/active_record/statement_cache.rb b/activerecord/lib/active_record/statement_cache.rb
index 192a19f05d..3047a81ec4 100644
--- a/activerecord/lib/active_record/statement_cache.rb
+++ b/activerecord/lib/active_record/statement_cache.rb
@@ -47,8 +47,8 @@ module ActiveRecord
def sql_for(binds, connection)
val = @values.dup
- binds = binds.dup
- @indexes.each { |i| val[i] = connection.quote(*binds.shift.reverse) }
+ binds = connection.prepare_binds_for_database(binds)
+ @indexes.each { |i| val[i] = connection.quote(binds.shift.last) }
val.join
end
end