首页 文章

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

提问于
浏览
85

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

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

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

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

  • 什么变量(字符串不适合这个)会接受?

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

谢谢

2 回答

  • 1

    如果你想要一个没有长度限制的字符串,你应该使用带有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) 是不同的) . 此外,如果您根本没有理由使用 :string (AKA varchar ),则数据库会在内部对 textvarchar(n) 进行相同处理,但 varchar(n) 的额外长度限制除外;如果您有一个外部约束(例如表格897 / B上的字段432将长度为23个字符的政府表格),您应该只使用 varchar(n) (AKA :string ) .

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

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

  • 204

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

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

    generating scaffold migration

    您可以通过在控制台中键入来生成迁移以保存更改(只需为表名替换 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
    

    Running your migration

    输入代码后更改列只需运行:

    rake db:migrate
    

    要应用迁移 . 如果您出错,您可以随时恢复更改:

    rake db:rollack
    

    Up and Down methods

    接受的答案引用 UpDown 方法,而不是较新的 Change 方法 . 由于rails 3.2旧式Up和Down方法比新的Change方法有一些优势 . 'Up and Down'避免 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 :)

相关问题