在第一次迁移时,我在列content
上声明为字符串Activerecord根据annotate gem将其设置为字符串(255)。
在我将应用程序推送到使用postgres的heroku后,如果我在内容中输入一个长度超过255的字符串,我会得到错误
PGError: ERROR: value too long for type character varying(255)
问题是我需要内容包含一个非常长的字符串(自由文本,可能是数千个字符)
谢谢
如果你想要一个没有长度限制的字符串,你应该使用带有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
),数据库内部对text
和varchar(n)
的处理方式相同,除了varchar(n)
的额外长度限制;你应该只使用varchar(n)
(AKA :string
),如果你有一个外部约束(例如政府表格,表明897 / B表格上的字段432将是23个字符长)。
顺便说一句,如果你在任何地方使用string
列,你应该总是指定:limit
作为提醒你自己有一个限制,你应该在模型中进行验证,以确保不超过限制。如果超过限制,PostgreSQL会抱怨并引发异常,MySQL会悄悄截断字符串或抱怨(取决于服务器配置),SQLite会让它按原样传递,其他数据库会做其他事情(可能会抱怨) 。
此外,您还应该在同一个数据库(通常是Heroku上的PostgreSQL)之上进行开发,测试和部署,甚至应该使用相同版本的数据库服务器。数据库之间存在其他差异(例如GROUP BY的行为)ActiveRecord不会将您与之隔离。你可能已经这样做了,但我想我还是会提到它。
虽然接受的答案非常好,但我想在这里添加一个答案,希望更好地处理原始海报问题第2部分,对于像我这样的非专家。
- 如何创建迁移以替换该列的类型
生成脚手架迁移
您可以通过在控制台中输入来生成迁移以保存更改(只需将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
上下方法
接受的答案引用Up
和Down
方法,而不是较新的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 :)