Ruby on rails 如何知道rake任务已经在rails中运行?

Ruby on rails 如何知道rake任务已经在rails中运行?,ruby-on-rails,ruby,ruby-on-rails-4,rake,rake-task,Ruby On Rails,Ruby,Ruby On Rails 4,Rake,Rake Task,我在我的Rails应用程序中有一个迁移,我只想在特定的rake任务已经运行的情况下运行,否则我会丢失大量数据。以下是我想做的事情: if has_rake_task_been_run? remove_column :transactions, :paid_by end 目前,我无法找到,而不是手动保证这件事。有什么解决办法吗?使用rake任务进行数据迁移是一个非常危险的想法。不这样做的两个原因: 即使您设法找出您的rake任务是否已完成,您的迁移仍将标记为已完成,并且您将无法重播它。唯一的

我在我的Rails应用程序中有一个迁移,我只想在特定的rake任务已经运行的情况下运行,否则我会丢失大量数据。以下是我想做的事情:

if has_rake_task_been_run?
  remove_column :transactions, :paid_by
end

目前,我无法找到,而不是手动保证这件事。有什么解决办法吗?

使用rake任务进行数据迁移是一个非常危险的想法。不这样做的两个原因:

  • 即使您设法找出您的rake任务是否已完成,您的迁移仍将标记为已完成,并且您将无法重播它。唯一的解决办法是在迁移过程中引发异常

    不,您也无法回滚该迁移。如果rake任务在迁移运行后完成,回滚将尝试添加已经存在的列

  • 由新开发人员从头开始设置数据库将变得非常痛苦,因为他们需要知道何时运行哪些rake任务。更不用说,
    rakedb:migrate
    执行所有迁移

  • 您正在用不可重用的任务污染您的rake任务列表

  • 看起来您所做的只是一个常规的数据迁移,所以您的rake任务所做的所有事情实际上都应该是迁移的一部分。这甚至允许您进行可逆的数据迁移(在大多数情况下)

    但是,请注意,数据迁移并不像常规的纯模式迁移那么简单。因为您的迁移应该完全独立于您的代码(因为它们将在将来工作,即使迁移的模型已完全从您的代码库中删除),所以通常会重新定义您将在迁移中使用的模型(仅定义迁移所需的位)。不幸的是,这并不像听起来那么简单,老实说,我仍然在寻找一个完美的解决方案。到目前为止,我所看到的最好的例子很简单(我假设
    paid\u by
    过去是字符串,而您将其更改为
    paid\u by\u id
    ,它引用了用户):

    class YOURMIGRATIONNAME

    使用上述代码的唯一缺点是,如果这些模型中的任何一个使用STI,它都不会很好地工作(我犯过一次错误,花了一段时间才发现问题所在)。解决方法是在迁移类之外定义它,但是这些类在所有迁移中都是可用的,并且可能会受到实际模型代码的影响(特别是在所有模型都已预加载的生产环境中)。简而言之,使用STI进行数据迁移是我目前仍在研究的问题。

    使用rake任务进行数据迁移是一个非常危险的想法。不这样做的两个原因:

  • 即使您设法找出您的rake任务是否已完成,您的迁移仍将标记为已完成,并且您将无法重播它。唯一的解决办法是在迁移过程中引发异常

    不,您也无法回滚该迁移。如果rake任务在迁移运行后完成,回滚将尝试添加已经存在的列

  • 由新开发人员从头开始设置数据库将变得非常痛苦,因为他们需要知道何时运行哪些rake任务。更不用说,
    rakedb:migrate
    执行所有迁移

  • 您正在用不可重用的任务污染您的rake任务列表

  • 看起来您所做的只是一个常规的数据迁移,所以您的rake任务所做的所有事情实际上都应该是迁移的一部分。这甚至允许您进行可逆的数据迁移(在大多数情况下)

    但是,请注意,数据迁移并不像常规的纯模式迁移那么简单。因为您的迁移应该完全独立于您的代码(因为它们将在将来工作,即使迁移的模型已完全从您的代码库中删除),所以通常会重新定义您将在迁移中使用的模型(仅定义迁移所需的位)。不幸的是,这并不像听起来那么简单,老实说,我仍然在寻找一个完美的解决方案。到目前为止,我所看到的最好的例子很简单(我假设
    paid\u by
    过去是字符串,而您将其更改为
    paid\u by\u id
    ,它引用了用户):

    class YOURMIGRATIONNAME
    使用上述代码的唯一缺点是,如果这些模型中有任何一个使用STI(我疯了),它将无法正常工作
    class YOURMIGRATIONNAME < ActiveRecord::Migration
      class Transaction < ActiveRecord::Base
        belongs_to :paid_by, class_name: "User"
      end
    
      class User < ActiveRecord::Base
      end
    
      def up
        add_column :transaction, :paid_by_id, :integer
    
        Transaction.transaction do # for speed
          Transaction.find_each do |t|
            t.paid_by_id = User.find_by(username: t[:paid_by])
            t.save!         # Always banged save in migration!
          end
        end
    
        remove_column :paid_by
      end
    
      def down
        add_column :transaction, :paid_by, :string
    
        Transactions.transaction do 
          Transaction.find_each do |t|
            t[:paid_by] = t.paid_by && t.paid_by.username
            t.save!
          end
        end
    
        remove_column :transactions, :paid_by_id
       
    end