【问题标题】:Run Rake task programmatically with specified environment使用指定环境以编程方式运行 Rake 任务
【发布时间】:2022-01-23 17:51:45
【问题描述】:

我正在使用我的 Ruby on Rails (3) 应用程序设置第二个数据库,因此我想创建一个 rake 任务来创建第二个开发数据库。我正在尝试覆盖 rake db:create 任务,以便它完成我需要的所有数据库创建。但是,似乎我找不到合适的方法来执行此任务。我尝试了几种方法 - 从 URL 建立到数据库的连接:

# remove db:create from the list of rake tasks in order to override it
db_create = Rake.application.instance_variable_get('@tasks').delete('db:create')

namespace :db do
  task :create do
    if Rails.env == "development"
      # database.yml contains an entry for secondary_development, this works, as confirmed from rails console
      ActiveRecord::Base.establish_connection "postgresql://localhost/secondary_development"       
      Rake::Task["db:create"].invoke # this does nothing
    end

    # invoke original db_create task - this works
    db_create.invoke
  end
end

另一种方法是:

# remove db:create from the list of rake tasks in order to override it
db_create = Rake.application.instance_variable_get('@tasks').delete('db:create')

namespace :db do
  task :create do
    if Rails.env == "development"
      Rails.env = "secondary_development"
      Rake::Task["db:create"].invoke
    end

    # invoke original db_create task - this doesn't work like this
    db_create.invoke
  end
end

这一次只有secondary_developmentdb:create 可以正常工作,并且可以根据需要创建数据库,但不再使用这种方法创建development 数据库。

根据我在其他地方找到的一个答案,我认为重新启用该任务是必要的,但这并没有改变这里的任何东西,而且似乎不是问题。

最后,一种行之有效的方法是:

# remove db:create from the list of rake tasks in order to override it
db_create = Rake.application.instance_variable_get('@tasks').delete('db:create')

namespace :db do
  task :create do
    if Rails.env == "development"
      system("rake db:create RAILS_ENV=secondary_development")
    end

    db_create.invoke
  end
end

这里唯一的问题是,因为 rake 任务是通过 system 运行的,Rails 应用程序必须在执行之前加载,所以我实际上是为了运行任务而完全加载应用程序两次 - 这将是当我将测试数据库添加到组合中时 3 次。

所以,实际的问题:

是否可以在指定环境下以编程方式运行Rake::Task["..."]

为什么ActiveRecord::Base.establish_connection 在创建数据库时不能这样工作?从 Rails 控制台运行它时我取得了成功。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 rake


    【解决方案1】:

    我设法找到了解决方案。我相信原因是.invoke 不会总是调用任务,而是会先判断是否有必要。鉴于rake db:create 在同一任务中多次运行,.invoke 认为后续调用是不必要的,因此不会运行它们。对于所需的行为,应使用.execute

    # remove db:create from the list of rake tasks in order to override it
    db_create = Rake.application.instance_variable_get('@tasks').delete('db:create')
    
    namespace :db do
      task :create do
        if Rails.env == "development"
          Rails.env = "secondary_development"
          Rake::Task["db:create"].execute # execute rather than invoke
        end
    
        # Reset the Rails env to 'development', otherwise it remains as 'secondary_development', which is not what we want (or move this above the if)
        Rails.env = "development"
        db_create.execute
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 2015-03-10
      • 2011-07-26
      • 1970-01-01
      • 2016-02-13
      • 2014-02-28
      • 1970-01-01
      相关资源
      最近更新 更多