レールの列タイプを長い文字列に変更する


90

最初の移行で、列contentに文字列Activerecordであることを宣言し、注釈gemに従ってそれをstring(255)にした。

postgresを使用するherokuにアプリをプッシュした後、コンテンツに255より長い文字列をフォームに入力すると、エラーが発生します

PGError: ERROR: value too long for type character varying(255)

問題は、コンテンツにおそらく非常に長い文字列(フリーテキスト、数千文字になる可能性がある)を含める必要があることです

  1. pgはどの変数を受け入れますか(文字列はこれには適切ではありません)。
  2. その列のタイプを置き換えるマイグレーションを作成するにはどうすればよいですか

ありがとう

回答:


216

text長さに制限のない文字列が必要な場合は、Railsで使用する必要があります。このような移行:

def up
  change_column :your_table, :your_column, :text
end
def down
  # This might cause trouble if you have strings longer
  # than 255 characters.
  change_column :your_table, :your_column, :string
end

物事を整理する必要があります。あなた:null => falseもそれの終わりに他のいくつかのオプションが必要かもしれません。

string明示的な制限なしで列を使用すると、Railsは暗黙的なを追加し:limit => 255ます。ただし、を使用するtextと、データベースがサポートする任意の長さの文字列タイプが取得されます。PostgreSQLではvarchar、長さなしで列を使用できますが、ほとんどのデータベースはそのために別の型を使用し、Railsはvarchar長さなしでそれを認識しません。PostgreSQLでtextを取得するには、Railsで使用する必要があります。そこ型の列の間にはPostgreSQLには違いませんし、タイプの一つは(しかし、ある異なります)。さらに、PostgreSQLの上にデプロイする場合、(AKA )を使用する理由はまったくありません。データベースは、texttextvarcharvarchar(n) :stringvarchartextvarchar(n)の追加の長さ制約を除いて、内部的には同じですvarchar(n)。列のサイズに外部制約(フォーム897 / Bのフィールド432は23文字になると言う政府フォームなど)がある場合にのみvarchar(n)(AKA :string)を使用する必要があります。

余談ですが、string列をどこかで使用している場合は、常に:limit制限があることを思い出させるようにを指定し、制限を超えていないことを確認するためにモデルを検証する必要があります。制限を超えると、PostgreSQLは不平を言って例外を発生させ、MySQLは静かに文字列を切り捨てたり不平を言ったり(サーバーの設定に応じて)、SQLiteがそのまま渡したり、他のデータベースが何かをしたり(おそらく不平を言う) 。

また、同じデータベース(通常はHerokuのPostgreSQL)の上に開発、テスト、およびデプロイする必要もあります。同じバージョンのデータベースサーバーを使用する必要もあります。ActiveRecordがユーザーを隔離しないデータベース間の他の違い(GROUP BYの動作など)があります。あなたはすでにこれをしているかもしれませんが、とにかくそれを言及したいと思いました。


13
すばらしい答えです。注:Railsは現在、changeメソッドでのchange_columnをサポートしていません(guides.rubyonrails.org/migrations.html#using-the-change-method); メモリが機能する場合、それを行うと元に戻せない移行が作成されます。up / downメソッドを使用して、昔ながらの方法で行う方が良いでしょう。
poetmountain

@BourbonJockey:それはメイクセンスしchange、自動的にタイプの変更を逆にすることができないであろうと移行ガイドがいると言う「このメソッドは、建設的なマイグレーションを書くために好ましい[変更方法](列またはテーブルの追加)」んとchange_columnISN」をあなたが指し示しているリストの中で、私はあなたが正しいと思います。up/ を使用するように修正しましたdown(に警告がありますdown)。
muが短すぎる

4
他の読者の将来の参考のために、この方法でHerokuのPostgresで文字列からテキストに変換しても、データは失われません。
マリーナマーティン

2
@Dennis:おそらく「同じデータベースを使用して開発、テスト、デプロイするべきだ」という方がより正確でしょう。通常の問題は、人々が(ばかげた)RailsのデフォルトのSQLiteセットアップを使用していて、他のものの上にデプロイすると状況が崩れることです。PostgreSQLは依然としてデフォルトであり、Herokuで最も一般的なオプションです。
muが短すぎる

3
余談ですが、Railsで長さが指定されていないフィールドは255文字であるという仮定は奇妙です。PostgreSQLでは、長さを無制限にするためだけに使用する必要はありませんtext。unconstrainedを使用できますvarchar。RailsはPostgreSQLではなく、この奇妙な制限を課しています。
クレイグリンガー

8

受け入れられた答えは素晴らしいですが、私のような専門家ではない人のために、元のポスターの質問パート2をうまく処理できるような答えをここに追加したいと思います。

  1. その列のタイプを置き換えるマイグレーションを作成するにはどうすればよいですか

足場マイグレーションの生成

コンソールに入力することで、変更を保持するマイグレーションを生成できます(tableテーブル名とcolumn列名のを置き換えるだけです)。

rails generate migration change_table_column

これにより、Railsアプリケーションの/ db / migrate /フォルダー内にスケルトン移行が生成されます。この移行は、移行コードのプレースホルダーです。

たとえば、私はから列の種類を変更するには、移行を作成したいstringtextテーブルと呼ばTodoItemsで、:

class ChangeTodoItemsDescription < ActiveRecord::Migration
  def change
     # enter code here
     change_column :todo_items, :description, :text
  end
end

移行を実行する

列を変更するコードを入力したら、次を実行します。

rake db:migrate

移行を適用します。エラーが発生した場合は、いつでも変更を元に戻すことができます。

rake db:rollack

アップおよびダウンメソッド

新しいメソッドではなく、受け入れられた回答リファレンスUpDownメソッドChange。Rails 3.2 以降、古いスタイルの UpメソッドとDownメソッドには、新しいChangeメソッドに比べていくつかの利点があります。「上下」を避けActiveRecord::IrreversibleMigration exceptionます。Rails 4のリリース以降、reversibleこのエラーを回避するために使用できます。

class ChangeProductsPrice < ActiveRecord::Migration
  def change
    reversible do |dir|
      change_table :products do |t|
        dir.up   { t.change :price, :string }
        dir.down { t.change :price, :integer }
      end
    end
  end
end

Railsをお楽しみください:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.