Добавление нового поля в уже существующую таблицу и изменение ранее созданных данных в Rails - PullRequest
2 голосов
/ 25 января 2010

Итак, у меня есть модель пользователя и соответствующая таблица (пользователи) с полями: User_id, имя пользователя, пароль и т. Д.

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

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

Спасибо

Ответы [ 4 ]

4 голосов
/ 25 января 2010

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

Вы можете написать задание на грабли. Если вы создаете метод экземпляра, называемый чем-то вроде «generate_invitation_token», вы можете написать задачу rake, например:

# lib/tasks/invitation_tokens.rake
namespace :seed do
  desc "generate invitation tokens for users that don't have one already"
  task :user_tokens => :environment do
    User.all(:conditions => {:invitation_token => nil}).each do |user|
      user.generate_invitation_token
    end
  end
end

Затем вы можете вызвать задачу rake из командной строки следующим образом:

rake seed:user_tokens

Это более чистый способ сделать это.

UPDATE

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

1 голос
/ 25 января 2010

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

class AddReceiveNewsletterToUsers < ActiveRecord::Migration
  def self.up
    change_table :users do |t|
      t.boolean :receive_newsletter, :default => false
    end
    User.update_all ["receive_newsletter = ?", true]
  end

  def self.down
    remove_column :users, :receive_newsletter
  end
end

Вы также можете использовать свои модели внутри миграции:

User.all(:conditions => {}).each do |user|
  user.do_sth
  user.save
end

и т. Д., Прочитайте о предостережениях

Edit:
После вашего комментария я думаю, что вы должны сделать это при миграции;

class AddInvitationLimitToUser < ActiveRecord::Migration
  def selt.up
    change_table :users do |t|
      t.integer :invitation_limit # and add validation to model `validates_presence_of` and so on
    end
    # now update all records already in database, which didn't had value in invitation_limit column
    User.update_all ["invitation_limit = ?", 5]
  end

  def self.down
    remove_column, :users, :invitation_limit
  end
end
1 голос
/ 25 января 2010

Общепринятая стратегия для этого, к сожалению, заключается в добавлении еще одной миграции, которая заполняет эти поля. Конечно, вы не можете использовать активную запись (или ваши миграции могут прерваться), поэтому рекомендуется делать это в pure SQL .

0 голосов
/ 25 января 2010

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

Несколько быстрых советов:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...