为什么 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 内置函数,看看它是否能满足您的需求?
我写了一个 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 内置函数,看看它是否能满足您的需求?