Подтвердить что ты не робот

Перенос Rails: только для изменения схемы или для обновления данных?

Я разработчик Junior Rails и на работе мы столкнулись со следующей проблемой:

Необходимо обновить значение столбца только для одной записи. Мы создали миграцию следующим образом:

class DisableAccessForUser < ActiveRecord::Migration
  def change
    User.where(name: "User").first.update_column(:access, false)
  end
end

Являются ли миграции только для изменений схемы?

Какие другие решения вы предлагаете?

PS: Я могу изменить его только с помощью кода. Нет доступа к консоли.

4b9b3361

Ответ 1

Краткая версия, так как миграции предназначены только для изменений схемы, вы не захотите использовать их для изменения фактических данных в базе данных.

Основная проблема заключается в том, что ваши миграции, связанные с управлением данными, могут игнорироваться другими разработчиками, если они загружают структурирование БД, используя либо rake db:schema:load, либо rake db:reset. Оба из них просто загружают последнюю версию структуры с помощью файла schema.rb и не трогают миграции.

Как отметил в комментариях Никита Сингх, я также сказал бы, что лучший способ изменения данных строк - реализовать простую задачу рейка, которая может быть выполнена по мере необходимости, независимо от структуры миграции. Или, для установки в первый раз, файл seed.rb идеально подходит для загрузки исходных системных данных.

Надеюсь, что бессвязное помогает.

Обновление

Нашел некоторую документацию в некоторых "официальных" источниках:

  • Rails Guide for Migrations - использование моделей в ваших миграциях. В этом разделе описывается сценарий, в котором манипуляции с данными в файлах миграции могут создавать проблемы для других разработчиков.
  • Rails Guide для миграции - миграции и данные семян. Тот же документ, что и выше, на самом деле не объясняет, почему плохо переносить обработку семян или данных в перенос, просто говорит, что нужно положить все это в файл seed.rd.
  • Этот ответ SO. Этот человек в основном говорит то же самое, что я написал выше, за исключением того, что они приводят цитату из книги Agile Web Development с Rails (3-е издание), частично написанной David Heinemeier Hansson, создатель Rails. Я не буду копировать цитату, поскольку вы можете прочитать ее в этом сообщении, но я считаю, что это дает вам более полное представление о том, почему манипуляции семян или данных при миграции могут считаться плохой практикой.

Ответ 2

Миграции прекрасны для изменений схемы. Но когда вы работаете над многими совместными проектами, такими как вытягивание кода каждый день от множества разработчиков.

Скорее всего, вы можете пропустить некоторые миграции (переносить обновление значения. Нет проблемы с изменениями схемы). Поскольку миграции зависят от временных меток.

Итак, мы создаем задачу rake в одном пространстве имен, чтобы обновить некоторые значения таблиц (будьте осторожны, чтобы не перезаписывать)

И вызовите всю команду rake в этом NameSpace всякий раз, когда мы обновляем код из Git.

Ответ 3

Переходы - это просто структурированный способ внесения изменений в базу данных, как схемы, так и данных. На мой взгляд, существуют ситуации, когда использование миграций для изменений данных является законным.

Например:

  • Если вы держите данные, которые в вашей базе данных в основном постоянны, но меняются ежегодно, то каждый месяц обновлять их можно с легкостью. Например, если вы перечислите команды в футбольной лиге, миграция будет хорошим способом обновлять текущие команды за каждый год.
  • Если вы хотите массово изменить атрибут большой таблицы. Например, если у вас есть slug-столбец в вашем пользователе, а имя "some user" будет переведено в slug "some_user", и теперь вы хотите изменить его на "some.user". Это то, что я сделал бы с миграцией.

Сказав это, я не буду использовать миграцию для изменения одного пользовательского атрибута. Если это то, что иногда случается, вы должны сделать панель инструментов, которая позволит вам редактировать эти данные в будущем. В противном случае задача грабли может быть хорошим вариантом.

Ответ 4

Изменение данных с использованием классов при миграции является опасным, потому что это не ужасно будущее доказательство. Изменения в классе могут легко нарушить миграцию в будущем.

Например, представьте себе, что вы должны добавить новый столбец пользователю (sample_group) и получить доступ к этому столбцу в обратном вызове жизненного цикла Rails, который выполняется при загрузке объекта (например, after_initialize). Это нарушит эту миграцию. Если вы не пропустили обратные вызовы и проверки при сохранении (с помощью update_column), было бы еще больше способов прервать эту миграцию в будущем.

Когда я хочу делать изменения данных в миграциях, я обычно возвращаюсь к SQL. С помощью метода execute() можно выполнить любой оператор SQL при переносе. Точный SQL для использования зависит от используемой базы данных, но вы должны иметь возможность получить соответствующий запрос db. Например, в MySQL я считаю, что следующее должно работать:

 execute("UPDATE users SET access = 0 WHERE id IN (select id from users order by id limit 1);")

Это гораздо более перспективное доказательство.

Ответ 5

Если я правильно помню, изменение определенных записей может работать, но я не уверен в этом.

В любом случае, это не очень хорошая практика, миграция должна быть пользователем только для изменений схемы. Для обновления одной записи я бы использовал консоль. Просто введите "rails console" в терминале и код ввода для изменения атрибутов.

Ответ 6

Нет ничего плохого в использовании миграции для переноса данных в вашей базе данных, в правильной ситуации, если вы сделаете это правильно.

В ваших миграциях необходимо избегать двух связанных вещей (как многие упомянули), ни одна из которых не позволяет переносить данные:

  • Нельзя использовать ваши модели в своих миграциях. Код в модели User может измениться, и никто не собирается обновлять вашу миграцию, когда это произойдет, поэтому, если какой-то сотрудник отправляется на каникулы на 3 месяца, возвращается и пытается запустить все миграции, которые произошли, когда она ушел, но кто-то переименовал модель User в то же время, ваша миграция будет нарушена и не позволит ей догнать. Это просто означает, что вам нужно использовать SQL или (если вы настроены на то, чтобы сохранить даже вашу реализацию миграции - агностик), включить независимую копию модели ActiveRecord непосредственно в ваш файл миграции (вложенный в класс миграции).

  • Также не имеет смысла использовать миграции для данных семян, а именно данные, которые должны использоваться для заполнения новой базы данных, когда кто-то настраивает приложение в первый раз, поэтому приложение будет (или будут иметь данные, которые можно было бы ожидать в новом экземпляре приложения). Вы не можете использовать миграции для этого, потому что вы не запускаете миграцию при настройке своей базы данных в первый раз, вы запускаете db:schema:load. Следовательно, специальный файл для хранения исходных данных: seeds.rb. Это просто означает, что если вам нужно добавить данные в миграцию (чтобы получить производительность и все данные разработчика до скорости), и она квалифицируется как начальные данные (необходимые для запуска приложения), вам нужно добавить их в seeds.rb тоже!

Однако ни одно из них не означает, что вы не должны использовать миграция для миграции данных в существующих базах данных. Для этого они и есть. Вы должны использовать их!