aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/associations/has_one_association.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb14
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb31
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb9
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb9
-rw-r--r--activerecord/lib/active_record/core.rb2
-rw-r--r--activerecord/lib/active_record/log_subscriber.rb2
-rw-r--r--activerecord/lib/active_record/store.rb7
10 files changed, 57 insertions, 30 deletions
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index 0008600418..944caacab6 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -26,11 +26,13 @@ module ActiveRecord
load_target
return self.target if !(target || record)
- if (target != record) || record.changed?
+
+ assigning_another_record = target != record
+ if assigning_another_record || record.changed?
save &&= owner.persisted?
transaction_if(save) do
- remove_target!(options[:dependent]) if target && !target.destroyed?
+ remove_target!(options[:dependent]) if target && !target.destroyed? && assigning_another_record
if record
set_owner_attributes(record)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 86c27557b4..b5acf211d5 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -16,6 +16,7 @@ module ActiveRecord
autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
autoload :IndexDefinition
autoload :ColumnDefinition
+ autoload :ChangeColumnDefinition
autoload :TableDefinition
autoload :Table
autoload :AlterTable
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 138ab811dc..ee6ca4fb6f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -206,6 +206,12 @@ module ActiveRecord
true
end
+ def type_cast(value, column)
+ return super unless value == true || value == false
+
+ value ? 1 : 0
+ end
+
# MySQL 4 technically support transaction isolation, but it is affected by a bug
# where the transaction level gets persisted for the whole session:
#
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 88c9494fc6..7b18b95c44 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -160,12 +160,6 @@ module ActiveRecord
# QUOTING ==================================================
- def type_cast(value, column)
- return super unless value == true || value == false
-
- value ? 1 : 0
- end
-
def quote_string(string) #:nodoc:
@connection.quote(string)
end
@@ -476,7 +470,11 @@ module ActiveRecord
def exec_stmt(sql, name, binds)
cache = {}
- log(sql, name, binds) do
+ type_casted_binds = binds.map { |col, val|
+ [col, type_cast(val, col)]
+ }
+
+ log(sql, name, type_casted_binds) do
if binds.empty?
stmt = @connection.prepare(sql)
else
@@ -487,7 +485,7 @@ module ActiveRecord
end
begin
- stmt.execute(*binds.map { |col, val| type_cast(val, col) })
+ stmt.execute(*type_casted_binds.map { |_, val| val })
rescue Mysql::Error => e
# Older versions of MySQL leave the prepared statement in a bad
# place when an error occurs. To support older mysql versions, we
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index e9daa5d7ff..c1f978a081 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -86,8 +86,11 @@ module ActiveRecord
case value
when Range
- return super(value, column) unless /range$/ =~ column.sql_type
- PostgreSQLColumn.range_to_string(value)
+ if /range$/ =~ column.sql_type
+ PostgreSQLColumn.range_to_string(value)
+ else
+ super(value, column)
+ end
when NilClass
if column.array && array_member
'NULL'
@@ -101,12 +104,21 @@ module ActiveRecord
when 'point' then PostgreSQLColumn.point_to_string(value)
when 'json' then PostgreSQLColumn.json_to_string(value)
else
- return super(value, column) unless column.array
- PostgreSQLColumn.array_to_string(value, column, self)
+ if column.array
+ PostgreSQLColumn.array_to_string(value, column, self)
+ else
+ super(value, column)
+ end
end
when String
- return super(value, column) unless 'bytea' == column.sql_type
- { :value => value, :format => 1 }
+ if 'bytea' == column.sql_type
+ # Return a bind param hash with format as binary.
+ # See http://deveiate.org/code/pg/PGconn.html#method-i-exec_prepared-doc
+ # for more information
+ { value: value, format: 1 }
+ else
+ super(value, column)
+ end
when Hash
case column.sql_type
when 'hstore' then PostgreSQLColumn.hstore_to_string(value)
@@ -114,8 +126,11 @@ module ActiveRecord
else super(value, column)
end
when IPAddr
- return super(value, column) unless ['inet','cidr'].include? column.sql_type
- PostgreSQLColumn.cidr_to_string(value)
+ if %w(inet cidr).include? column.sql_type
+ PostgreSQLColumn.cidr_to_string(value)
+ else
+ super(value, column)
+ end
else
super(value, column)
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 3668aecd4b..eecebdb4e5 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -783,11 +783,12 @@ module ActiveRecord
def exec_cache(sql, name, binds)
stmt_key = prepare_statement(sql)
+ type_casted_binds = binds.map { |col, val|
+ [col, type_cast(val, col)]
+ }
- log(sql, name, binds, stmt_key) do
- @connection.send_query_prepared(stmt_key, binds.map { |col, val|
- type_cast(val, col)
- })
+ log(sql, name, type_casted_binds, stmt_key) do
+ @connection.send_query_prepared(stmt_key, type_casted_binds.map { |_, val| val })
@connection.block
@connection.get_last_result
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index e5ad08b6b0..35a579f29b 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -291,8 +291,11 @@ module ActiveRecord
end
def exec_query(sql, name = nil, binds = [])
- log(sql, name, binds) do
+ type_casted_binds = binds.map { |col, val|
+ [col, type_cast(val, col)]
+ }
+ log(sql, name, type_casted_binds) do
# Don't cache statements if they are not prepared
if without_prepared_statement?(binds)
stmt = @connection.prepare(sql)
@@ -307,9 +310,7 @@ module ActiveRecord
stmt = cache[:stmt]
cols = cache[:cols] ||= stmt.columns
stmt.reset!
- stmt.bind_params binds.map { |col, val|
- type_cast(val, col)
- }
+ stmt.bind_params type_casted_binds.map { |_, val| val }
end
ActiveRecord::Result.new(cols, stmt.to_a)
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index d93c26c130..96b5686ae0 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -109,7 +109,7 @@ module ActiveRecord
elsif abstract_class?
"#{super}(abstract)"
elsif !connected?
- "#{super}(no database connection)"
+ "#{super} (call '#{super}.connection' to establish a connection)"
elsif table_exists?
attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
"#{super}(#{attr_list})"
diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb
index 927fbab8f0..654ef21b07 100644
--- a/activerecord/lib/active_record/log_subscriber.rb
+++ b/activerecord/lib/active_record/log_subscriber.rb
@@ -23,6 +23,8 @@ module ActiveRecord
def render_bind(column, value)
if column
if column.binary?
+ # This specifically deals with the PG adapter that casts bytea columns into a Hash.
+ value = value[:value] if value.is_a?(Hash)
value = "<#{value.bytesize} bytes of binary data>"
end
diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb
index 301bc503c7..186a737561 100644
--- a/activerecord/lib/active_record/store.rb
+++ b/activerecord/lib/active_record/store.rb
@@ -15,9 +15,10 @@ module ActiveRecord
# You can set custom coder to encode/decode your serialized attributes to/from different formats.
# JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
#
- # NOTE - If you are using special PostgreSQL columns like +hstore+ or +json+ there is no need for
- # the serialization provieded by +store+. You can simply use +store_accessor+ instead to generate
- # the accessor methods.
+ # NOTE - If you are using PostgreSQL specific columns like +hstore+ or +json+ there is no need for
+ # the serialization provided by +store+. Simply use +store_accessor+ instead to generate
+ # the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
+ # using a symbol.
#
# Examples:
#