为什么 Rake 任务中的这个 Ruby 脚本不能选择 Rails 环境?

Why won't this Ruby script in a Rake task pick up the Rails environment?

我写了一个 Ruby 脚本,我想 运行 作为 Rake 任务。以下是我的 data.rake 文件:

namespace :data do
  namespace :fixtures do
    desc "Save fixtures to JSON file"
    task :file do
      bundle exec ruby "#{Rails.root}/lib/tasks/get_fixtures.rb"
    end

    desc "Save fixtures to DB"
    task db: :environment do
      # puts League.all.inspect
      bundle exec ruby "#{Rails.root}/lib/tasks/save_fixtures_to_db.rb"
    end
  end
end

data:fixutres:db 任务中,注释行工作正常并将联赛数据显示为 ActiveRecord 查询,而 Ruby 脚本在使用 League.new 时抛出以下错误它:

`save_to_db': uninitialized constant League (NameError)
    from /home/fred/workspace/plprediction/lib/tasks/save_fixtures_to_db.rb:134:in `<main>'
rake aborted!
Command failed with status (1): [/home/fred/.rvm/rubies/ruby-2.2.1/bin/ruby...]
/home/fred/workspace/plprediction/lib/tasks/data.rake:11:in `block (3 levels) in <top (required)>'
/home/fred/.rvm/gems/ruby-2.2.1@havenprediction/bin/ruby_executable_hooks:15:in `eval'
/home/fred/.rvm/gems/ruby-2.2.1@havenprediction/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => data:fixtures:db
(See full trace by running task with --trace)

我在这里迷路了。我不知道为什么环境只在rake任务中可用,而不是rake任务中的Ruby脚本。

而不是,例如,bundle exec ruby "#{Rails.root}/lib/tasks/get_fixtures.rb"尝试bundle exec rails runner "#{Rails.root}/lib/tasks/get_fixtures.rb"

环境仅在 rake 任务中可用,而不是在 rake 任务中的 Ruby 脚本,因为您构建了 Rake 调用的方式。您正在启动一个额外的进程(这需要将环境本身加载到 "get back" 到您的 Rake 进程已经存在的位置)。

您的 lib/tasks/get_fixtures.rb 任务可能会成功,因为它只使用 Ruby 代码,而不是 Rails。 (这是推测,因为该代码不可用。)

在这种情况下,我通常将 save_fixtures_to_db.rb 之类的内容放入 Class 方法中,然后从 rake 调用该方法。这是一个例子:

class League
  def self.save_fixtures_to_db
    # Your ruby code here.
  end
end

rake 任务然后调用此方法。这避免了重新加载环境(正如您在任务中成功引用 League 所见)。

另一种选择是在您编写的脚本中加载 Rails。如果无法将代码移动到 Rails 方法中,您可以将 binstub 的前几行(bin/rails 和 bin/rake)复制到您自己的文件中。

此外,您是否查看了 db:fixtures:load Rails 内置函数,看看它是否能满足您的需求?