【问题标题】:Rails Migration Update existing records while creating entries in another tableRails 迁移更新现有记录,同时在另一个表中创建条目
【发布时间】:2011-10-03 20:32:47
【问题描述】:

我正在尝试为我的 Rails 应用程序设置 Beta 邀请。我有一个 Invitation 模型和一个 User 模型。

用户有一个invitation_id。我正在验证该用户必须有一个邀请 ID,并且它应该是唯一的。我想编写一个迁移,以便我可以更新我现有的用户以拥有一个邀请 ID。

这是我的邀请模型:

# Table name: invitations
#
#  id              :integer         not null, primary key
#  sender_id       :integer
#  recipient_email :string(255)
#  token           :string(255)
#  sent_at         :datetime
#  created_at      :datetime
#  updated_at      :datetime

为了保证唯一性,我必须在邀请表中创建记录,并将相应的 id 分配给用户记录。

有人可以建议迁移吗?

提前致谢!

【问题讨论】:

    标签: sql ruby-on-rails migration sql-update insert-update


    【解决方案1】:

    如果您已经为您的邀请和用户进行了迁移,那么您真的应该将邀请填充到自定义 rake 任务中。保持迁移严格用于表操作始终是一个好习惯。

    /lib/tasks/distribute_invitations.rake

    namespace :db do
      desc "Run all custom tasks"
      task :import_all => [:distribute_invitations, :some_other_data_import]
    
      desc: "Some other data import"
      task :some_other_data_import => :environment do
        puts "insert task code here"
      end
    
      desc: "Give existing user's invitations"
      task :distribute_invitations => :environment do
        for user in User.all
          if user.invitation_id.nil?
            invite = Invitation.create(:sender_id => <some id>, :recipient_email => <some email>, :token => <some token>, :sent_at => Time.now)
            user.update_attribute(:invitation_id, invite.id)
            puts "Updated user #{user.id} with invitation_id #{invite.id}"
          else
            puts "User already has an invitation_id"
          end
        end
      end
    end
    

    在您进行迁移以向您的用户表提供一个邀请 ID 后,您可以运行:

    rake db:distribute_invitations
    

    您的现有用户将通过invitation_id 创建并关联到他们的邀请。

    或者运行你能做的所有任务:

    rake db:import_all
    

    在这种情况下,很可能只需将其与您的用户迁移一起进行迁移:

    class AddInvitationID < ActiveRecord::Migration
      def self.up
        add_column :users, :invitation_id, :integer
        for user in User.all
          if user.invitation_id.nil?
            invite = Invitation.create(:sender_id => <some id>, :recipient_email => <some email>, :token => <some token>, :sent_at => Time.now)
            user.update_attribute(:invitation_id, invite.id)
            puts "Updated user #{user.id} with invitation_id #{invite.id}"
          else
            puts "User already has an invitation_id"
          end
        end
      end
    
      def self.down
        remove_colum :users, :invitation_id
      end
    end
    

    【讨论】:

    • 感谢克里斯。这是一个很好的解决方案。出于好奇,为什么我们不应该使用迁移来做呢?我所有正在开发此应用程序的同事(以及潜在的合作者)也必须单独运行 rake db:distribute_invitations 才能使其在他们的系统中运行。
    • 刚刚通过噩梦般的经历了解到,每当迁移中存在种子数据依赖关系时,我总是在以后后悔。使其更难追踪,并且在必要时无法重新运行任务。我在团队环境中工作过,每当我们有需要在现有表中运行填充数据的自定义任务时,我们总是关注 /lib/tasks。如果您或其他任何人需要做同样的事情,他们可以附加到文件中,这样您的所有数据操作都是集中的
    • 添加了迁移解决方案和更强大的 rake 任务
    • 感谢克里斯!我能够使用您提供的详细信息制定解决方案。
    • 您忘记在您的 rake 任务中添加 :environment 依赖项。在这种情况下,您无法定义模型。请更新它以避免人们复制您的代码时出现一些错误。
    猜你喜欢
    • 2023-03-25
    • 2013-09-25
    • 2013-12-21
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    相关资源
    最近更新 更多