将新字段添加到预先存在的表中并修改先前在 Rails 中创建的数据

发布于 2024-08-19 05:37:37 字数 278 浏览 2 评论 0原文

所以我有一个用户模型和一个相应的表(用户),其中包含以下字段:User_id、用户名、密码等。

但后来我将invitation_limit 添加到用户表中。新创建的用户具有invitation_limit,但是在运行invitation_token 迁移之前创建的用户没有invitation_limit 字段。

如何更新之前创建的用户以包含invitation_token 字段?请注意,我不是在谈论向用户表添加invitation_limit 字段(即迁移),而是更新已创建的用户。

谢谢,

So I've a user model and a corresponding table (users) with fields: User_id, username, password etc.

But then I added invitation_limit to users table. Newly created users have invitation_limit, however the users created before the invitation_token migration was run don't have the invitation_limit field.

How do I update the previously created users to include invitation_token field? Mind you I'm not talking about adding invitation_limit field to users table (i.e. migration), but rather updating already created users.

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

却一份温柔 2024-08-26 05:37:37

不应将种子数据放入迁移中。迁移是为了创建结构,而不是添加数据,如果移动数据库,您就会遇到问题。

您可以编写一个 rake 任务。如果您创建一个名为“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

这是一种更简洁的方法。

更新

我在一篇名为“向现有模型添加列和默认数据"。

Seed data shouldn't be put in a migration. Migrations are for creating structure, not adding data, and you'll run into problems if you ever move the database.

You could write a rake task. If you create an instance method called something like "generate_invitation_token", you can then write a rake task like this:

# 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

You can then call the rake task from the commandline like this:

rake seed:user_tokens

This is a cleaner way to do it.

UPDATE

I've expanded this answer in a blog post called "Adding Columns and Default Data To Existing Models".

嗫嚅 2024-08-26 05:37:37

不幸的是,普遍接受的策略是添加另一个填充这些字段的迁移。当然,您不能使用活动记录(否则您的迁移可能会中断),因此最佳实践是在 纯 SQL

The generally accepted strategy for this, unfortunately, is to add another migration which populates those fields. Of course, you can't use active record (or your migrations might break), so best practice is to do this in pure SQL.

旧竹 2024-08-26 05:37:37

我的理解是,您想要更新用户记录,而不是创建种子(种子将数据添加到您的数据库中,例如角色等,这对您的应用程序很重要)。来自文档

class AddReceiveNewsletterToUsers <; ActiveRecord::迁移
  定义自我提升
    更改表:用户执行|t|
      t.boolean :receive_newsletter, :default =>;错误的
    结尾
    User.update_all ["receive_newsletter = ?", true]
  结尾

  绝对自我贬低
    删除列:用户,:接收新闻通讯
  结尾
结尾

您还可以在迁移中使用模型:

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

等等,请阅读 关于警告

编辑:
在您发表评论后,我认为您在迁移中应该这样做;

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

What I understand is that you want to update User records, not to create seed (seed adds data to your database, for example Roles ans so on, which are important to your application). From 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

You can also use your models inside migration:

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

and so on, read about caveats

Edit:
After your comment, this is how I think you should do it in migration;

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
撩人痒 2024-08-26 05:37:37

您想为此使用迁移。迁移只是 ruby​​ 代码,因此您可以访问应用程序有权访问的所有数据。更改数据、添加缺失数据、删除行等。

一些快速提示:

You want to use the migration for this. The migration is just ruby code, so you can access all the data that your application has access to. Alter data, add missing data, delete rows, etc.

Some quick tips:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文