30

Railsアプリでrailsgeneratemigrationsコマンドを使用してテーブルを作成しました。その移行ファイルは次のとおりです。

class CreateListings < ActiveRecord::Migration
  def change
    create_table :listings do |t|
      t.string :name
      t.string :telephone
      t.string :latitude
      t.string :longitude

      t.timestamps
    end
  end
end

次に、緯度と経度を整数として保存したかったので、実行しようとしました。

rails generate migration changeColumnType

そのファイルの内容は次のとおりです。

class ChangeColumnType < ActiveRecord::Migration
  def up
    #change latitude columntype from string to integertype
    change_column :listings, :latitude, :integer
    change_column :listings, :longitude, :integer
    #change longitude columntype from string to integer type
  end

  def down  
  end
end

列タイプが変更されることを期待していましたが、レーキが中止され、次のエラーメッセージが表示されました。なぜこれが通らなかったのだろうか?私のアプリでpostgresqlを使用しています。

rake db:migrate
==  ChangeColumnType: migrating ===============================================
-- change_column(:listings, :latitude, :integer)
rake aborted!
An error has occurred, this and all later migrations canceled:

PG::Error: ERROR:  column "latitude" cannot be cast to type integer
: ALTER TABLE "listings" ALTER COLUMN "latitude" TYPE integer

Tasks: TOP => db:migrate
(See full trace by running task with --trace)

注:テーブルにはデータがありません。ありがとう

4

6 に答える 6

28

私はについてALTER TABLEのマニュアルを引用します:

古いタイプから新しいタイプへの暗黙的または割り当てキャストがない場合は、USING句を指定する必要があります。

必要なものは次のとおりです。

ALTERTABLEリストALTER経度TYPE整数USINGlongitude:: int ;
ALTERTABLEリストALTER緯度タイプ整数USING緯度::int ;

または、1つのコマンドでより短くより速く(大きなテーブルの場合):

ALTER TABLE listings ALTER longitude TYPE integer USING longitude::int
                    ,ALTER latitude  TYPE integer USING latitude::int;

これは、すべてのエントリがに変換可能である限り、データの有無にかかわらず機能integerします。列にを
定義した場合は、新しいタイプに対してそれを削除して再作成する必要がある場合があります。DEFAULT

これは、 ActiveRecordでこれを行う方法に関するブログ記事です。
または、コメントで@muのアドバイスを参考にしてください。彼は自分のRubyを知っています。私はここでPostgreSQLだけが得意です。

于 2012-04-27T01:03:41.037 に答える
24

以下のように、移行ファイルに生のSQLを含めて、schema.rbを更新します。

class ChangeColumnType < ActiveRecord::Migration
  def up
    execute 'ALTER TABLE listings ALTER COLUMN latitude TYPE integer USING (latitude::integer)'
    execute 'ALTER TABLE listings ALTER COLUMN longitude TYPE integer USING (longitude::integer)'
  end

  def down
    execute 'ALTER TABLE listings ALTER COLUMN latitude TYPE text USING (latitude::text)'
    execute 'ALTER TABLE listings ALTER COLUMN longitude TYPE text USING (longitude::text)'
  end
end
于 2013-09-25T19:20:42.683 に答える
24

私はこれが少し醜いことを知っていますが、列を削除して新しいタイプで再度追加することを好みます:

 def change
     remove_column :mytable, :mycolumn
     add_column :mytable, :mycolumn, :integer, default: 0
 end
于 2014-05-09T17:40:18.047 に答える
12

以下はrails way、問題に取り組むための詳細です。私の場合、購入テーブルに2つの列があり、文字列型から浮動小数点数に変換する必要がありました。

def change
    change_column :purchases, :mc_gross, 'float USING CAST(mc_gross AS float)'
    change_column :purchases, :mc_fee, 'float USING CAST(mc_fee AS float)'
end

それは私にとってトリックでした。

于 2016-04-27T19:37:27.333 に答える
2
  1. それらの列に既存のデータがありますか?
  2. 緯度と経度にintを使用しないでください。代わりに、フローティングポイントに配置する必要があります。
于 2012-04-27T03:34:34.037 に答える
0

緯度と経度は10進数です

rails g scaffold client name:string email:string 'latitude:decimal{12,3}' 'longitude:decimal{12,3}' 

class CreateClients < ActiveRecord::Migration[5.0]
  def change
    create_table :clients do |t|
      t.string :name
      t.string :email
      t.decimal :latitude, precision: 12, scale: 3
      t.decimal :longitude, precision: 12, scale: 3

      t.timestamps
    end
  end
end
于 2017-04-29T15:26:08.047 に答える