Зміна типу стовпця на довші рядки в рейках


90

Під час першої міграції я оголосив для стовпця contentрядком Activerecord зробив його рядком (255) відповідно до анотації gem.

Після того, як я натискаю додаток на heroku, який використовує postgres, якщо я вводжу у форму у вмісті рядок довшим за 255, я отримую помилку

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

Проблема полягає в тому, що мені потрібно, щоб вміст містив рядок, який надзвичайно довгий, можливо (вільний текст може складати тисячі символів)

  1. Яку змінну (чи рядок не підходить для цього) приймає pg?
  2. Як створити міграцію для заміни типу цього стовпця

Дякую

Відповіді:


216

Вам слід використовувати 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(AKAvarchar ) взагалі, база даних обробляє textіvarchar(n)внутрішньо те саме, за винятком додаткових обмежень довжини для varchar(n); ви повинні використовувати varchar(n)(AKA :string) лише у випадку, якщо у вас є зовнішнє обмеження (наприклад, урядова форма, яка говорить, що поле 432 у формі 897 / B буде мати 23 символи) щодо розміру стовпця.

Окрім того, якщо ви stringде-небудь використовуєте стовпець, ви завжди повинні вказувати це :limitяк нагадування собі про те, що існує обмеження, і ви повинні мати перевірку в моделі, щоб переконатися, що обмеження не перевищено. Якщо ви перевищите ліміт, PostgreSQL скаржиться та викличе виняток, MySQL тихо скоротить рядок або поскаржиться (залежно від конфігурації сервера), SQLite дозволить йому пройти як є, а інші бази даних будуть робити щось інше (можливо, скаржиться) .

Крім того, вам слід також розробляти, тестувати та розгортати поверх тієї самої бази даних (яка зазвичай буде PostgreSQL на Heroku), ви навіть повинні використовувати ті самі версії сервера баз даних. Між базами даних існують інші відмінності (наприклад, поведінка GROUP BY), від яких ActiveRecord не захистить вас. Можливо, ви вже робите це, але я думав, що все одно згадаю про це.


13
Чудова відповідь. Одна примітка: Rails наразі не підтримує стовпець change_colum з методом зміни ( guides.rubyonrails.org/migrations.html#using-the-change-method ); якщо пам'ять служить, ви створите незворотну міграцію, якщо зробите це. Краще робити це по-старому за методами вгору / вниз.
поетична гора

@BourbonJockey: Має сенс, що changeне вдасться автоматично змінити зміну типу, і Керівництво з міграцій каже, що "[метод зміни] Цей метод є кращим для написання конструктивних міграцій (додавання стовпців або таблиць)" і не change_column' t у списку, на який ви вказуєте, тому я думаю, що ви маєте рацію. Я зафіксував його для використання up/ down(із застереженням down), дякую за підняті голови.
mu занадто короткий

4
Для подальших довідок інших читачів, перетворення з рядка в текст у Postgres на Heroku таким чином НЕ втратить дані.
Marina Martin

2
@Dennis: Можливо, "вам слід розробити, протестувати та розгорнути, використовуючи ту саму базу даних", було б точніше. Звичайна проблема полягає в тому, що люди використовують (смішну) Rails за замовчуванням налаштування SQLite, і все руйнується, коли вони розгортаються поверх чогось іншого. PostgreSQL все ще є найпоширенішим варіантом у Heroku, чи не так?
mu занадто короткий

3
Як примітка, припущення Rails про те, що поля невизначеної довжини повинні складати 255 символів, є дивним. Це НЕ потрібно в PostgreSQL використовувати textтільки для отримання необмеженої довжини; ви можете просто використовувати необмежений varchar. Rails встановлює цю непарну межу, а не PostgreSQL.
Крейг Рінгер,

8

Хоча прийнята відповідь є чудовою, я хотів додати тут відповідь, яка, сподіваюся, краще стосується оригінальних плакатів, частина 2, для таких не експертів, як я.

  1. Як створити міграцію для заміни типу цього стовпця

генерування міграції ешафотів

Ви можете згенерувати міграцію для утримання змін, набравши на консолі (просто замініть tableім’я таблиці та columnім’я стовпця)

rails generate migration change_table_column

Це призведе до міграції скелета всередині вашої програми Rails / db / migrate / folder. Ця міграція є заповнювачем для вашого коду міграції.

Наприклад, я хочу створити міграцію для зміни типу стовпця з stringна text, у таблиці під назвою TodoItems:

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методу. Оскільки рейки 3.2 старого стилю « Вгору та Вниз» Методи дають кілька переваг перед новим методом Зміни. "Вгору і вниз" уникайте 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

Насолоджуйтесь рейками :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.