diff options
6 files changed, 60 insertions, 9 deletions
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 291b0649e1..a66de990ad 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Standardize the interpretation of boolean columns in the Mysql and Sqlite adapters. (Use MysqlAdapter.emulate_booleans = false to disable this behavior) + * Added new symbol-driven approach to activating observers with Base#observers= [DHH]. Example: ActiveRecord::Base.observers = :cacher, :garbage_collector diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index fed51fea18..b9c06a21cb 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -158,7 +158,9 @@ module ActiveRecord # The type parameter should either contain :integer, :float, :datetime, :date, :text, or :string # The sql_type is just used for extracting the limit, such as 10 in "varchar(10)" def initialize(name, default, sql_type = nil, null = true) - @name, @default, @type, @null = name, type_cast(default), simplified_type(sql_type), null + @name, @type, @null = name, simplified_type(sql_type), null + # have to do this one separately because type_cast depends on #type + @default = type_cast(default) @limit = extract_limit(sql_type) unless sql_type.nil? end @@ -337,6 +339,9 @@ module ActiveRecord # raises an exception or returns false. def rollback_db_transaction() end + def quoted_true() "'t'" end + def quoted_false() "'f'" end + def quote(value, column = nil) case value when String @@ -348,8 +353,8 @@ module ActiveRecord "'#{quote_string(value)}'" # ' (for ruby-mode) end when NilClass then "NULL" - when TrueClass then (column && column.type == :boolean ? "'t'" : "1") - when FalseClass then (column && column.type == :boolean ? "'f'" : "0") + when TrueClass then (column && column.type == :boolean ? quoted_true : "1") + when FalseClass then (column && column.type == :boolean ? quoted_false : "0") when Float, Fixnum, Bignum then value.to_s when Date then "'#{value.to_s}'" when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'" @@ -502,7 +507,7 @@ module ActiveRecord def add_column_options!(sql, options) sql << " NOT NULL" if options[:null] == false - sql << " DEFAULT '#{options[:default]}'" unless options[:default].nil? + sql << " DEFAULT #{quote(options[:default], options[:column])}" unless options[:default].nil? end protected @@ -574,7 +579,7 @@ module ActiveRecord end def add_column_options!(sql, options) - base.add_column_options!(sql, options) + base.add_column_options!(sql, options.merge(:column => self)) end end diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 426d035bae..eea47817f6 100755 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -41,6 +41,14 @@ module ActiveRecord end module ConnectionAdapters + class MysqlColumn < Column #:nodoc: + private + def simplified_type(field_type) + return :boolean if MysqlAdapter.emulate_booleans && field_type.downcase == "tinyint(1)" + super + end + end + # The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with # the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/). # @@ -56,7 +64,17 @@ module ActiveRecord # * <tt>:sslcert</tt> -- Necessary to use MySQL with an SSL connection # * <tt>:sslcapath</tt> -- Necessary to use MySQL with an SSL connection # * <tt>:sslcipher</tt> -- Necessary to use MySQL with an SSL connection + # + # By default, the MysqlAdapter will consider all columns of type tinyint(1) + # as boolean. If you wish to disable this emulation (which was the default + # behavior in versions 0.13.1 and earlier) you can add the following line + # to your environment.rb file: + # + # ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false class MysqlAdapter < AbstractAdapter + @@emulate_booleans = true + cattr_accessor :emulate_booleans + LOST_CONNECTION_ERROR_MESSAGES = [ "Server shutdown in progress", "Broken pipe", @@ -126,7 +144,7 @@ module ActiveRecord def columns(table_name, name = nil) sql = "SHOW FIELDS FROM #{table_name}" columns = [] - execute(sql, name).each { |field| columns << Column.new(field[0], field[4], field[1], field[2] == "YES") } + execute(sql, name).each { |field| columns << MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") } columns end @@ -184,6 +202,9 @@ module ActiveRecord end + def quoted_true() "1" end + def quoted_false() "0" end + def quote_column_name(name) "`#{name}`" end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index e426149e02..ab42490020 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -99,7 +99,7 @@ module ActiveRecord :time => { :name => "datetime" }, :date => { :name => "date" }, :binary => { :name => "blob" }, - :boolean => { :name => "integer" } + :boolean => { :name => "boolean" } } end diff --git a/activerecord/test/fixtures/db_definitions/mysql.sql b/activerecord/test/fixtures/db_definitions/mysql.sql index d581ee3ae8..393a6e808e 100755 --- a/activerecord/test/fixtures/db_definitions/mysql.sql +++ b/activerecord/test/fixtures/db_definitions/mysql.sql @@ -26,7 +26,7 @@ CREATE TABLE `topics` ( `bonus_time` time default NULL, `last_read` date default NULL, `content` text, - `approved` tinyint(1) default 1, + `approved` tinyint default 1, `replies_count` int(11) default 0, `parent_id` int(11) default NULL, `type` varchar(50) default NULL, @@ -190,4 +190,4 @@ CREATE TABLE `fk_test_has_fk` ( `fk_id` INTEGER NOT NULL, FOREIGN KEY (`fk_id`) REFERENCES `fk_test_has_pk`(`id`) -) TYPE=InnoDB;
\ No newline at end of file +) TYPE=InnoDB; diff --git a/activerecord/test/migration_test.rb b/activerecord/test/migration_test.rb index 502348877c..b24b7a7d44 100644 --- a/activerecord/test/migration_test.rb +++ b/activerecord/test/migration_test.rb @@ -68,6 +68,29 @@ if ActiveRecord::Base.connection.supports_migrations? ensure Person.connection.drop_table :testings rescue nil end + + def test_create_table_with_defaults + Person.connection.create_table :testings do |t| + t.column :one, :string, :default => "hello" + t.column :two, :boolean, :default => true + t.column :three, :boolean, :default => false + t.column :four, :integer, :default => 1 + end + + columns = Person.connection.columns(:testings) + one = columns.detect { |c| c.name == "one" } + two = columns.detect { |c| c.name == "two" } + three = columns.detect { |c| c.name == "three" } + four = columns.detect { |c| c.name == "four" } + + assert_equal "hello", one.default + assert_equal true, two.default + assert_equal false, three.default + assert_equal 1, four.default + + ensure + Person.connection.drop_table :testings rescue nil + end def test_add_column_not_null Person.connection.create_table :testings do |t| |