ActionMailer的default_url_options:如何从DefaultOptions自动检索端口?
我经常有许多并行运行的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)
这是在您引用的Stack Overflow答案之后,但将端口提取到常量DefaultOptions::PORT
。 现在请注意,模块DefaultOptions
的名称并不神奇,它只是定义了一个普通的模块,然后将其添加到Rails::Server
。 你可以根据需要命名它。 当开发服务器启动时,会实例化一个新的Rails::Server
对象,并且在某些时候会在该对象上调用default_options
方法。 由于使用了prepend
,方法查找将首先到达您在DefaultOptions
定义的方法。 该方法中的super
只调用Rails::Server
定义的原始un-prepended default_options
。
在default_options
获取值“难”的原因是因为它是一个实例方法,这意味着你只能在Rails::Server
类的实例上访问它,而我们通常不会拥有服务器宾语。 您可以像这样访问它:
# config/development.config require 'rails/commands/server' Rails::Server.new.default_options[:Port]
但我认为这是一种不必要的依赖和对象创建。 Rails::Server
这个名字也暗示我们可能只想拥有这个类的一个对象,而且我不会实例化服务器对象只是为了获得它们的配置哈希。 因此,无论您是否具有对服务器对象的引用( DefaultOptions::PORT
,都可以将端口提取到常量,您可以更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
,并在application.yml
使用PORT
键,那么您的代码可能如下所示:
# 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 }
您可以使用Rails :: Server :: Options获取所需的信息,然后相应地配置ActionMailer:
config.action_mailer.default_url_options = { host: Rails::Server.new.options[:Host], port: Rails::Server.new.options[:Port] }