Ruby on Rails:控制台/ .rb文件中的行为之间的差异

我想使用存储在credentials.yml.enc文件中的信息来获取Rails 5.2应用程序。 但是,我正在努力获得一个在控制台中完美运行的命令,以便在插入.rb文件时以相同的方式运行。

在Rails控制台(在我的本地开发计算机上) Rails.application.credentials.username返回"my_username"

如果我在一个非常简单的db_backup.rb文件中插入此行,如下所示,我收到错误:

 NameError: uninitialized constant #<Class:#>::Rails 

db_backup.rb

 Model.new(:db_backup, 'Description for db_backup') do ## # PostgreSQL [Database] # database PostgreSQL do |db| db.username = Rails.application.credentials.username end end 

请问你能解释为什么我在Rails控制台/ .rb文件中使用完全相同的代码行时会得到不同的行为吗?

执行代码的上下文不一样。 一个是rails控制台,另一个是备份命令

加载Rails控制台时会发生什么

启动rails控制台意味着在对其执行代码之前启动所有rails堆栈。 像Sinatra,Rails等机架应用程序使用config.ru文件作为应该运行文件以启动的约定。 (如果你想深入了解这个,你可以探索兔子洞)

这意味着您在控制台启动期间可能遇到的绝大多数错误都会阻止您在控制台中执行任何操作(因为启动失败)。 相反,它将打印堆栈跟踪错误,以便您找出问题所在,以便您可以更正并再次尝试。

TL; 控制台中的DR Rails.application.credentials.username在所有Rails堆栈(模型,依赖项,初始化程序)按特定顺序加载后执行的

运行备份命令时会发生什么

backup命令在备份存储库的bin repo中定义

它是这样的

 #!/usr/bin/env ruby # encoding: utf-8 require File.expand_path("../../lib/backup", __FILE__) Backup::CLI.start 

如果您打开所需的文件lib/backup.rb并在Gemfile中查看,那么您将无法使用依赖项或Rails常量定义。

因此,当您运行backup命令并执行db_backup.rb时,此处调用的常量Rails是……未定义的。 Ruby正在尝试在当前范围内找到这个常量的嵌套版本,这是Model.new do; end Model.new do; end块。

还没有定义哪个ruby告诉你NameError: uninitialized constant #>::Rails

@giglemad对执行上下文中的类解析问题给出了很好的解释(rails控制台与运行备份ruby文件)。

要修复错误,只需让代码知道使用顶级类查找( ::Rails ):

 Model.new(:db_backup, 'Description for db_backup') do ## # PostgreSQL [Database] # database PostgreSQL do |db| db.username = ::Rails.application.credentials.username end end 

如果你仍然看到丢失的Rails不变,你需要将你的脚本放在rake任务中,或者需要你的rails环境。

我最后通过将下面的行添加到db_backup.rb的顶部来解决这个问题:

 require './config/environment' # added to enable credentials to be read from Rails environment