2010-01-25 1 views
2

Так я модель пользователя и соответствующую таблицу (пользователей) с полями: user_id, имя пользователя, пароль и т.д.Добавление нового поля предварительно существующей таблицы и модификации ранее созданных данных в Rails

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

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

Спасибо,

ответ

4

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

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

# 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 seed:user_tokens 

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

UPDATE

Я расширил этот ответ в своем блоге под названием "Adding Columns and Default Data To Existing Models".

+0

Это именно то, что я искал, спасибо! –

1

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

+0

Я вижу. Это работает? User.find (: all) .each do | p | p.update_attribute: invite_limit, 5 end –

+0

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

+0

Спасибо, я буду использовать вышеупомянутую задачу рейка. –

0

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

Некоторые быстрые подсказки:

  • Написать свой вверх и вниз по миграции, если это возможно, если нет, то поднять IrreversibleMigration
  • проверить. :)
  • См: Can Rails Migrations be used to convert data?
1

Я понимаю, что вы хотите обновить записи пользователя, а не создавать семя (семя добавляет данные в вашу базу данных, например, Roles ans и т. Д., Которые важны для вашего приложения).От documentaion:

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 

и так далее, читайте about caveats

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 
+0

Ну, я хочу добавить новое поле в свою таблицу User после того, как пользователь был создан. Я создал пользовательскую модель, а затем добавил поле приглашения_limit в таблицу users, поэтому у пользователей, созданных до миграции нового поля, не будет нового поля. Я хочу обновить этих пользователей и добавить приглашение_лимит и установить их на 5. –

+0

@Senthil Пользователи создают, прежде чем перенос нового поля будет иметь новое поле, они не имеют в нем значения (по умолчанию это будет NULL). Они находятся в одной таблице, которую вы уже изменили, поэтому они не могут пропустить новое поле (столбец) только потому, что они были созданы ранее. – MBO

+0

Вы правы, он создается. Я предполагаю, что ошибка, которую я получал раньше, заключалась в том, что она была NULL, но не была создана. Благодаря! –