From 98a7dde064172dbf9b9c441175fcd45dca70d8db Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 28 May 2014 18:23:00 -0700 Subject: Ensure we always use instances of the adapter specific column class - Create a consistent API across adapters for building new columns - Use it for custom properties so we don't get `UndefinedMethodError`s in stuff I'm implementing elsewhere. --- .../lib/active_record/connection_adapters/abstract_adapter.rb | 4 ++++ .../active_record/connection_adapters/abstract_mysql_adapter.rb | 7 ++++--- .../connection_adapters/postgresql/schema_statements.rb | 6 +++++- .../lib/active_record/connection_adapters/sqlite3_adapter.rb | 2 +- activerecord/lib/active_record/properties.rb | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index a8e0cb93a0..b589cfee09 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -363,6 +363,10 @@ module ActiveRecord end end + def new_column(name, default, cast_type, sql_type = nil, null = true) + Column.new(name, default, cast_type, sql_type, null) + end + protected def lookup_cast_type(sql_type) # :nodoc: 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 82e62786ca..2677b6ee83 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -206,8 +206,7 @@ module ActiveRecord raise NotImplementedError end - def new_column(field, default, sql_type, null, collation, extra = "") # :nodoc: - cast_type = lookup_cast_type(sql_type) + def new_column(field, default, cast_type, sql_type = nil, null = true, collation = "", extra = "") # :nodoc: Column.new(field, default, cast_type, sql_type, null, collation, strict_mode?, extra) end @@ -425,7 +424,9 @@ module ActiveRecord execute_and_free(sql, 'SCHEMA') do |result| each_hash(result).map do |field| field_name = set_field_encoding(field[:Field]) - new_column(field_name, field[:Default], field[:Type], field[:Null] == "YES", field[:Collation], field[:Extra]) + sql_type = field[:Type] + cast_type = lookup_cast_type(sql_type) + new_column(field_name, field[:Default], cast_type, sql_type, field[:Null] == "YES", field[:Collation], field[:Extra]) end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index 484c44dc8d..b4d53eba26 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -181,10 +181,14 @@ module ActiveRecord oid = get_oid_type(oid.to_i, fmod.to_i, column_name, type) default_value = extract_value_from_default(default) default_function = extract_default_function(default_value, default) - PostgreSQLColumn.new(column_name, default_value, oid, type, notnull == 'f', default_function) + new_column(column_name, default_value, oid, type, notnull == 'f', default_function) end end + def new_column(name, default, cast_type, sql_type = nil, null = true, default_function = nil) # :nodoc: + PostgreSQLColumn.new(name, default, cast_type, sql_type, null, default_function) + end + # Returns the current database name. def current_database query('select current_database()', 'SCHEMA')[0][0] diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index a5e2619cb8..adf893d7e7 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -393,7 +393,7 @@ module ActiveRecord sql_type = field['type'] cast_type = lookup_cast_type(sql_type) - Column.new(field['name'], field['dflt_value'], cast_type, sql_type, field['notnull'].to_i == 0) + new_column(field['name'], field['dflt_value'], cast_type, sql_type, field['notnull'].to_i == 0) end end diff --git a/activerecord/lib/active_record/properties.rb b/activerecord/lib/active_record/properties.rb index c99594c823..cc1e8b45c1 100644 --- a/activerecord/lib/active_record/properties.rb +++ b/activerecord/lib/active_record/properties.rb @@ -65,7 +65,7 @@ module ActiveRecord def property(name, cast_type) name = name.to_s # Assign a new hash to ensure that subclasses do not share a hash - self.user_provided_columns = user_provided_columns.merge(name => ConnectionAdapters::Column.new(name, nil, cast_type)) + self.user_provided_columns = user_provided_columns.merge(name => connection.new_column(name, nil, cast_type)) end # Returns an array of column objects for the table associated with this class. -- cgit v1.2.3 From fc63e8074a4ae47a422a05567c905b6fd8c0b2aa Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Wed, 28 May 2014 20:06:57 -0700 Subject: Use github url for homepage of log4r [ci skip] --- activerecord/README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/README.rdoc b/activerecord/README.rdoc index e5b68750e4..c813b22f3b 100644 --- a/activerecord/README.rdoc +++ b/activerecord/README.rdoc @@ -130,7 +130,7 @@ This would also define the following accessors: `Product#name` and SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html]. -* Logging support for Log4r[http://log4r.rubyforge.org] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]. +* Logging support for Log4r[https://github.com/colbygk/log4r] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]. ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) ActiveRecord::Base.logger = Log4r::Logger.new('Application Log') -- cgit v1.2.3 From 8eb536e7b487351d7485879d436e9d747520ed90 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 29 May 2014 06:55:44 -0700 Subject: Result sets never override a model's column type MySQL and PostgreSQL provide a column type override in order to properly type cast computed columns included in a result set. This should never override the known types of full fledged columns. In addition to messing up computed properties, this would have led to inconsistent behavior between a record created with `new`, and a record created with `last` on the mysql adapter in the following cases: - `tinyint(1)` with `emulate_booleans` set to `false` - `text`, `string`, `binary`, and `decimal` columns --- activerecord/lib/active_record/querying.rb | 2 +- .../test/cases/adapters/mysql/consistency_test.rb | 48 ++++++++++++++++++++++ activerecord/test/cases/custom_properties_test.rb | 2 + 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 activerecord/test/cases/adapters/mysql/consistency_test.rb (limited to 'activerecord') diff --git a/activerecord/lib/active_record/querying.rb b/activerecord/lib/active_record/querying.rb index ef138c6f80..1fe54cea3f 100644 --- a/activerecord/lib/active_record/querying.rb +++ b/activerecord/lib/active_record/querying.rb @@ -40,7 +40,7 @@ module ActiveRecord column_types = {} if result_set.respond_to? :column_types - column_types = result_set.column_types + column_types = result_set.column_types.merge(columns_hash) else ActiveSupport::Deprecation.warn "the object returned from `select_all` must respond to `column_types`" end diff --git a/activerecord/test/cases/adapters/mysql/consistency_test.rb b/activerecord/test/cases/adapters/mysql/consistency_test.rb new file mode 100644 index 0000000000..083d533bb2 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql/consistency_test.rb @@ -0,0 +1,48 @@ +require "cases/helper" + +class MysqlConsistencyTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + class Consistency < ActiveRecord::Base + self.table_name = "mysql_consistency" + end + + setup do + @old_emulate_booleans = ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans + ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false + + @connection = ActiveRecord::Base.connection + @connection.create_table("mysql_consistency") do |t| + t.boolean "a_bool" + t.string "a_string" + end + Consistency.reset_column_information + Consistency.create! + end + + teardown do + ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = @old_emulate_booleans + @connection.drop_table "mysql_consistency" + end + + test "boolean columns with random value type cast to 0 when emulate_booleans is false" do + with_new = Consistency.new + with_last = Consistency.last + with_new.a_bool = 'wibble' + with_last.a_bool = 'wibble' + + assert_equal 0, with_new.a_bool + assert_equal 0, with_last.a_bool + end + + test "string columns call #to_s" do + with_new = Consistency.new + with_last = Consistency.last + thing = Object.new + with_new.a_string = thing + with_last.a_string = thing + + assert_equal thing.to_s, with_new.a_string + assert_equal thing.to_s, with_last.a_string + end +end diff --git a/activerecord/test/cases/custom_properties_test.rb b/activerecord/test/cases/custom_properties_test.rb index 397a8e0692..047c1b9b74 100644 --- a/activerecord/test/cases/custom_properties_test.rb +++ b/activerecord/test/cases/custom_properties_test.rb @@ -37,7 +37,9 @@ module ActiveRecord data.reload assert_equal 2, data.overloaded_float + assert_kind_of Fixnum, OverloadedType.last.overloaded_float assert_equal 2.0, UnoverloadedType.last.overloaded_float + assert_kind_of Float, UnoverloadedType.last.overloaded_float end def test_properties_assigned_in_constructor -- cgit v1.2.3