1. ホーム
  2. ruby-on-rails

[解決済み] railsでカラムタイプを長い文字列に変更する

2023-02-20 10:05:27

質問

最初のマイグレーションで、カラムに content を文字列にすると宣言しました。 Activerecordでは、annotate gemに従ってstring(255)になっていました。

postgresを使用しているherokuにアプリをpushした後、contentのフォームに255より長い文字列を入力すると、エラーが発生します。

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

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

  1. どのような変数 (文字列はこれに適していません) を pg は受け入れるでしょうか?
  2. そのカラムの型を置き換えるためにマイグレーションを作成するにはどうすればよいでしょうか。

感謝

どのように解決するのですか?

この場合 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 を知らないのです。そのため text をRailsで取得する必要があります。 text をPostgreSQLで使用することができます。PostgreSQLでは、カラムの型が text 型のカラムと varchar (ただし varchar(n) が異なる)。さらに、PostgreSQLの上にデプロイする場合は :string (AKA varchar ) が全くない場合、データベースは textvarchar(n) の長さの制約を除けば、内部的には同じです。 varchar(n) のみを使用する必要があります。 varchar(n) (別名 :string ) がある場合、列のサイズに外部制約 (例えば、フォーム 897/B のフィールド 432 は 23 文字になるという政府フォームなど) があります。

余談ですが、もしあなたが string カラムを使う場合は、常に :limit を指定する必要があります。これは、制限があることを自分自身に思い出させ、制限を超えないことを確認するために、モデル内で検証を行う必要があるためです。もし制限を超えたら、PostgreSQLは文句を言って例外を出し、MySQLは静かに文字列を切り詰めるか文句を言い(サーバの設定によります)、SQLiteはそのまま通し、他のデータベースは他のことをします(おそらく文句を言うでしょう)。

また、開発、テスト、デプロイは同じデータベース (Heroku では通常 PostgreSQL) の上で行うべきで、データベースサーバーのバージョンも同じものを使用すべきです。データベース間の違い(例えばGROUP BYの動作など)は、ActiveRecordでは解決できないことがあります。すでにやっていることかもしれませんが、一応書いておこうと思います。


更新 : 新しいバージョンのActiveRecordでは、以下のように理解することができます。 varchar を無制限に理解しますので、少なくともPostgreSQLではそう言えるでしょう。

change_column :your_table, :your_column, :string, limit: nil

を変更するために varchar(n) カラムを varchar . text そして varchar はPostgreSQLに関する限り同じものですが、いくつかのフォームビルダーはこれらを異なるものとして扱います。 varchar<input type="text"> 一方 text は複数行の <textarea> .