这是与您的代码的一个小偏差:
# config/boot.rb
require 'rails/commands/server'
module DefaultOptions
PORT = 3001
def default_options
super.merge!(Port: PORT)
end
end
# This line was part of the Stack Overflow answer you quoted, and is important
# With newer Ruby versions, you can call `prepend` directly
Rails::Server.prepend(DefaultOptions)
这遵循您引用的堆栈溢出答案,除了将端口提取到常量之外DefaultOptions::PORT
。现在请注意,模块的名称没有什么神奇之处DefaultOptions
,它只是定义了一个普通模块,然后添加到Rails::Server
。您可以随意命名它。当开发服务器启动时,一个新的Rails::Server
对象被实例化,并且在某个时刻default_options
对该对象调用方法。由于使用prepend
,方法查找将首先到达您定义的方法DefaultOptions
. The super
在该方法中只需调用原始的未前置的default_options
定义于Rails::Server
.
为什么“很难”获取这些值default_options
是因为它是一个实例方法,这意味着您只能在实例上访问它Rails::Server
类,并且我们通常不拥有服务器对象。你可以这样访问它:
# config/development.config
require 'rails/commands/server'
Rails::Server.new.default_options[:Port]
但我认为这是不必要的依赖和对象创建。名字Rails::Server
也意味着我们可能只想拥有此类的一个对象,并且我不会实例化服务器对象只是为了获取它们的配置哈希。因此,将端口提取为一个可以保存的常量,无论您是否有对服务器对象的引用 -DefaultOptions::PORT
- 在我看来更干净。
所以,现在我们已经掌握了DefaultOptions::PORT
常量,您可以在邮件程序中使用它:
# config/development.rb
config.action_mailer.smtp_settings = {
:port => DefaultOptions::PORT,
:address => '...',
:user_name => '...',
:password => '...',
:domain => '...',
:authentication => :plain
}
您还可以考虑将邮件程序和端口定义放在yaml
文件,这样您就不需要将配置的各个部分“散布”在不同的位置 - 这可能会节省您以后的麻烦。
如果您想这样做,您可以自己创建一个包装类,使用YAML.load_file
加载新的yaml
配置文件转换成哈希值。或者,查看Figaro
gem,它提供了一种将所有 Rails 配置放置在单个文件中的便捷方法 -application.yml
- 并使用以下方式从任何地方访问它们ENV
.
如果你要使用Figaro
,例如,并且有PORT
key in application.yml
,那么您的代码可能如下所示:
# config/boot.rb
require 'rails/commands/server'
module DefaultOptions
def default_options
super.merge!(Port: ENV['PORT'])
end
end
Rails::Server.prepend(DefaultOptions)
# config/development.rb
config.action_mailer.smtp_settings = {
:port => ENV['PORT'],
:address => ENV['SMTP_SERVER'],
:user_name => ENV['SMTP_LOGIN'],
:password => ENV['SMTP_PASSWORD'],
:domain => ENV['MAILER_DOMAIN'],
:authentication => :plain
}