在rails中将列类型更改为更长的字符串

问题描述 投票:86回答:2

在第一次迁移时,我在列content上声明为字符串Activerecord根据annotate gem将其设置为字符串(255)。

在我将应用程序推送到使用postgres的heroku后,如果我在内容中输入一个长度超过255的字符串,我会得到错误

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

问题是我需要内容包含一个非常长的字符串(自由文本,可能是数千个字符)

  1. 什么变量(字符串不适合这个)会接受?
  2. 如何创建迁移以替换该列的类型

谢谢

ruby-on-rails string postgresql ruby-on-rails-3.1 rails-activerecord
2个回答
207
投票

如果你想要一个没有长度限制的字符串,你应该使用带有Rails的text。像这样的迁移:

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。你必须在Rails中使用text来获得PostgreSQL中的text column。 PostgreSQL在text类型和varchar类型之间没有区别(但varchar(n)不同)。此外,如果你在PostgreSQL上部署,没有理由使用:string(AKA varchar),数据库内部对textvarchar(n)的处理方式相同,除了varchar(n)的额外长度限制;你应该只使用varchar(n)(AKA :string),如果你有一个外部约束(例如政府表格,表明897 / B表格上的字段432将是23个字符长)。

顺便说一句,如果你在任何地方使用string列,你应该总是指定:limit作为提醒你自己有一个限制,你应该在模型中进行验证,以确保不超过限制。如果超过限制,PostgreSQL会抱怨并引发异常,MySQL会悄悄截断字符串或​​抱怨(取决于服务器配置),SQLite会让它按原样传递,其他数据库会做其他事情(可能会抱怨) 。

此外,您还应该在同一个数据库(通常是Heroku上的PostgreSQL)之上进行开发,测试和部署,甚至应该使用相同版本的数据库服务器。数据库之间存在其他差异(例如GROUP BY的行为)ActiveRecord不会将您与之隔离。你可能已经这样做了,但我想我还是会提到它。


4
投票

虽然接受的答案非常好,但我想在这里添加一个答案,希望更好地处理原始海报问题第2部分,对于像我这样的非专家。

  1. 如何创建迁移以替换该列的类型

生成脚手架迁移

您可以通过在控制台中输入来生成迁移以保存更改(只需将table替换为您的表名,并为您的列名替换column

rails generate migration change_table_column

这将在您的Rails application / db / migrate /文件夹中生成框架迁移。此迁移是迁移代码的占位符。

例如,我想在名为TodoItems的表中创建一个迁移,以将列的类型从string更改为text

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 :)

© www.soinside.com 2019 - 2024. All rights reserved.