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

Nic*_*nto 88 string postgresql ruby-on-rails ruby-on-rails-3.1 rails-activerecord

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

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

PGError: ERROR: value too long for type character varying(255)
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢

mu *_*ort 212

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
Run Code Online (Sandbox Code Playgroud)

应该解决问题.您可能还想要:null => false或其他一些选项.

当您使用string没有显式限制的列时,Rails将添加隐式:limit => 255.但是如果你使用text,你将获得数据库支持的任意长度字符串类型.PostgreSQL允许您使用varchar没有长度的列,但大多数数据库使用单独的类型,Rails不知道varchar没有长度.您必须text在Rails中使用PostgreSQL中的text.有类型的列之间PostgreSQL中没有区别text类型的一个和varchar(但是varchar(n) 不同的).此外,如果你对PostgreSQL的顶部部署,没有理由使用:string(AKA varchar在所有),数据库对待text,并varchar(n)同国内除了用于额外的长度的限制varchar(n); 如果你有一个外部约束(例如政府表格,表格897/B上的字段432长度为23个字符),你应该只使用varchar(n)(AKA :string).

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

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

  • 很好的答案.一个注意事项:Rails目前不支持使用change方法的change_column(http://guides.rubyonrails.org/migrations.html#using-the-change-method); 如果内存服务,如果你这样做,你将创建一个不可逆转的迁移.用上/下方法更好地做老派的方式. (13认同)
  • 对于其他读者的未来参考,以这种方式在Heroku上Postgres中从字符串转换为文本不会丢失数据. (4认同)
  • 另外,Rails假设未指定长度的字段应为255个字符是很奇怪的.PostgreSQL中不需要使用`text`来获得无限长度; 你可以使用不受约束的`varchar`.Rails强加了这个奇怪的限制,而不是PostgreSQL. (3认同)
  • @Dennis:也许"你应该使用相同的数据库开发,测试和部署"会更准确.通常的问题是人们使用(荒谬的)Rails默认的SQLite设置,当他们部署在其他东西之上时,事情就会崩溃.PostgreSQL仍然是Heroku的默认和最常见选项,不是吗? (2认同)

Ton*_*nin 6

尽管接受的答案非常好,但我想在此处添加一个答案,希望能够更好地处理像我这样的非专家问题的原始海报问题2。

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

产生支架迁移

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

rails generate migration change_table_column
Run Code Online (Sandbox Code Playgroud)

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

例如,我想创建一个迁移从改变一个列的类型stringtext,在表中称为TodoItems:

class ChangeTodoItemsDescription < ActiveRecord::Migration
  def change
     # enter code here
     change_column :todo_items, :description, :text
  end
end
Run Code Online (Sandbox Code Playgroud)

运行迁移

输入更改列的代码后,请运行:

rake db:migrate
Run Code Online (Sandbox Code Playgroud)

应用您的迁移。如果发生错误,可以随时使用以下方法还原更改:

rake db:rollack
Run Code Online (Sandbox Code Playgroud)

上下方法

可接受的答案参考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
Run Code Online (Sandbox Code Playgroud)

享受Rails :)