aboutsummaryrefslogblamecommitdiffstats
path: root/activerecord/test/cases/migration/column_attributes_test.rb
blob: 93adbdd05b54e275edf797db3fc1a306260b0a7c (plain) (tree)
1
2
3
4
5
6
7
8
9
                                



                                                       

                                                 

                                             







                                                                        
                                                             
                                              

                                                      
                                           

                                                
                                              

         
                                                             
                                              
 
                                                    
                                           

                                              
                                              

         







                                                                                                       





                                                                                           











                                                                                                   
                                                                                                                                
                                                                                                                            
                                                                                                          
                                                  
                                                                                                        
            
                                                                                                        


                
                             













                                                                                     
                             















                                                                                                   



                                                                                               
 


                                                          
 

                                                                                      
 



                                                          



















                                                                                        
                             



















                                                                                      

                                                          




                                                   


                                               
 


                                                                                                               
 


                                                                                                                       

           


       
require "cases/migration/helper"

module ActiveRecord
  class Migration
    class ColumnAttributesTest < ActiveRecord::TestCase
      include ActiveRecord::Migration::TestHelper

      self.use_transactional_fixtures = false

      def test_add_column_newline_default
        string = "foo\nbar"
        add_column 'test_models', 'command', :string, :default => string
        TestModel.reset_column_information

        assert_equal string, TestModel.new.command
      end

      def test_add_remove_single_field_using_string_arguments
        assert_no_column TestModel, :last_name

        add_column 'test_models', 'last_name', :string
        assert_column TestModel, :last_name

        remove_column 'test_models', 'last_name'
        assert_no_column TestModel, :last_name
      end

      def test_add_remove_single_field_using_symbol_arguments
        assert_no_column TestModel, :last_name

        add_column :test_models, :last_name, :string
        assert_column TestModel, :last_name

        remove_column :test_models, :last_name
        assert_no_column TestModel, :last_name
      end

      def test_add_column_without_limit
        # TODO: limit: nil should work with all adapters.
        skip "MySQL wrongly enforces a limit of 255" if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
        add_column :test_models, :description, :string, limit: nil
        TestModel.reset_column_information
        assert_nil TestModel.columns_hash["description"].limit
      end

      if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
        def test_unabstracted_database_dependent_types
          add_column :test_models, :intelligence_quotient, :tinyint
          TestModel.reset_column_information
          assert_match(/tinyint/, TestModel.columns_hash['intelligence_quotient'].sql_type)
        end
      end

      # We specifically do a manual INSERT here, and then test only the SELECT
      # functionality. This allows us to more easily catch INSERT being broken,
      # but SELECT actually working fine.
      def test_native_decimal_insert_manual_vs_automatic
        correct_value = '0012345678901234567890.0123456789'.to_d

        connection.add_column "test_models", "wealth", :decimal, :precision => '30', :scale => '10'

        # Do a manual insertion
        if current_adapter?(:OracleAdapter)
          connection.execute "insert into test_models (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
        elsif current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003 #before MySQL 5.0.3 decimals stored as strings
          connection.execute "insert into test_models (wealth) values ('12345678901234567890.0123456789')"
        elsif current_adapter?(:PostgreSQLAdapter)
          connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)"
        else
          connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)"
        end

        # SELECT
        row = TestModel.first
        assert_kind_of BigDecimal, row.wealth

        # If this assert fails, that means the SELECT is broken!
        unless current_adapter?(:SQLite3Adapter)
          assert_equal correct_value, row.wealth
        end

        # Reset to old state
        TestModel.delete_all

        # Now use the Rails insertion
        TestModel.create :wealth => BigDecimal.new("12345678901234567890.0123456789")

        # SELECT
        row = TestModel.first
        assert_kind_of BigDecimal, row.wealth

        # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
        unless current_adapter?(:SQLite3Adapter)
          assert_equal correct_value, row.wealth
        end
      end

      def test_add_column_with_precision_and_scale
        connection.add_column 'test_models', 'wealth', :decimal, :precision => 9, :scale => 7

        wealth_column = TestModel.columns_hash['wealth']
        assert_equal 9, wealth_column.precision
        assert_equal 7, wealth_column.scale
      end

      if current_adapter?(:SQLite3Adapter)
        def test_change_column_preserve_other_column_precision_and_scale
          connection.add_column 'test_models', 'last_name', :string
          connection.add_column 'test_models', 'wealth', :decimal, :precision => 9, :scale => 7

          wealth_column = TestModel.columns_hash['wealth']
          assert_equal 9, wealth_column.precision
          assert_equal 7, wealth_column.scale

          connection.change_column 'test_models', 'last_name', :string, :null => false
          TestModel.reset_column_information

          wealth_column = TestModel.columns_hash['wealth']
          assert_equal 9, wealth_column.precision
          assert_equal 7, wealth_column.scale
        end
      end

      def test_native_types
        add_column "test_models", "first_name", :string
        add_column "test_models", "last_name", :string
        add_column "test_models", "bio", :text
        add_column "test_models", "age", :integer
        add_column "test_models", "height", :float
        add_column "test_models", "wealth", :decimal, :precision => '30', :scale => '10'
        add_column "test_models", "birthday", :datetime
        add_column "test_models", "favorite_day", :date
        add_column "test_models", "moment_of_truth", :datetime
        add_column "test_models", "male", :boolean

        TestModel.create :first_name => 'bob', :last_name => 'bobsen',
          :bio => "I was born ....", :age => 18, :height => 1.78,
          :wealth => BigDecimal.new("12345678901234567890.0123456789"),
          :birthday => 18.years.ago, :favorite_day => 10.days.ago,
          :moment_of_truth => "1782-10-10 21:40:18", :male => true

        bob = TestModel.first
        assert_equal 'bob', bob.first_name
        assert_equal 'bobsen', bob.last_name
        assert_equal "I was born ....", bob.bio
        assert_equal 18, bob.age

        # Test for 30 significant digits (beyond the 16 of float), 10 of them
        # after the decimal place.

        unless current_adapter?(:SQLite3Adapter)
          assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
        end

        assert_equal true, bob.male?

        assert_equal String, bob.first_name.class
        assert_equal String, bob.last_name.class
        assert_equal String, bob.bio.class
        assert_equal Fixnum, bob.age.class
        assert_equal Time, bob.birthday.class

        if current_adapter?(:OracleAdapter)
          # Oracle doesn't differentiate between date/time
          assert_equal Time, bob.favorite_day.class
        else
          assert_equal Date, bob.favorite_day.class
        end

        assert_instance_of TrueClass, bob.male?
        assert_kind_of BigDecimal, bob.wealth
      end

      if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
        def test_out_of_range_limit_should_raise
          assert_raise(ActiveRecordError) { add_column :test_models, :integer_too_big, :integer, :limit => 10 }

          unless current_adapter?(:PostgreSQLAdapter)
            assert_raise(ActiveRecordError) { add_column :test_models, :text_too_big, :integer, :limit => 0xfffffffff }
          end
        end
      end
    end
  end
end