我经常有许多Rails应用程序并行运行,因此我将它们配置为使用不同的端口:
# Change default port of development server, see http://stackoverflow.com/questions/18103316
require 'rails/commands/server'
module DefaultOptions
def default_options
super.merge!(Port: 3001)
end
end
现在,这对于在开发环境中的ActionMailer也起作用很重要:
config.action_mailer.default_url_options = {host: 'localhost:3001'}
但是,我不想直接对此进行硬编码,而是直接从
DefaultOptions
进行设置。这怎么可能? 最佳答案
这与您的代码略有不同:
# 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
中定义的方法。该方法中的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
中使用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
}