1
0

rails.rb 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # Since rubygems doesn't support optional dependencies, we have to manually check
  2. unless Gem::Requirement.new(">= 6.1").satisfied_by?(Gem::Version.new(Rails.version))
  3. warn "dotenv 3.0 only supports Rails 6.1 or later. Use dotenv ~> 2.0."
  4. return
  5. end
  6. require "dotenv/replay_logger"
  7. require "dotenv/log_subscriber"
  8. Dotenv.instrumenter = ActiveSupport::Notifications
  9. # Watch all loaded env files with Spring
  10. begin
  11. require "spring/commands"
  12. ActiveSupport::Notifications.subscribe("load.dotenv") do |*args|
  13. event = ActiveSupport::Notifications::Event.new(*args)
  14. Spring.watch event.payload[:env].filename if Rails.application
  15. end
  16. rescue LoadError, ArgumentError
  17. # Spring is not available
  18. end
  19. module Dotenv
  20. # Rails integration for using Dotenv to load ENV variables from a file
  21. class Rails < ::Rails::Railtie
  22. delegate :files, :files=, :overwrite, :overwrite=, :autorestore, :autorestore=, :logger, to: "config.dotenv"
  23. def initialize
  24. super()
  25. config.dotenv = ActiveSupport::OrderedOptions.new.update(
  26. # Rails.logger is not available yet, so we'll save log messages and replay them when it is
  27. logger: Dotenv::ReplayLogger.new,
  28. overwrite: false,
  29. files: [
  30. ".env.#{env}.local",
  31. (".env.local" unless env.test?),
  32. ".env.#{env}",
  33. ".env"
  34. ].compact,
  35. autorestore: env.test? && !defined?(ClimateControl) && !defined?(IceAge)
  36. )
  37. end
  38. # Public: Load dotenv
  39. #
  40. # This will get called during the `before_configuration` callback, but you
  41. # can manually call `Dotenv::Rails.load` if you needed it sooner.
  42. def load
  43. Dotenv.load(*files.map { |file| root.join(file).to_s }, overwrite: overwrite)
  44. end
  45. def overload
  46. deprecator.warn("Dotenv::Rails.overload is deprecated. Set `Dotenv::Rails.overwrite = true` and call Dotenv::Rails.load instead.")
  47. Dotenv.load(*files.map { |file| root.join(file).to_s }, overwrite: true)
  48. end
  49. # Internal: `Rails.root` is nil in Rails 4.1 before the application is
  50. # initialized, so this falls back to the `RAILS_ROOT` environment variable,
  51. # or the current working directory.
  52. def root
  53. ::Rails.root || Pathname.new(ENV["RAILS_ROOT"] || Dir.pwd)
  54. end
  55. # Set a new logger and replay logs
  56. def logger=(new_logger)
  57. logger.replay new_logger if logger.is_a?(ReplayLogger)
  58. config.dotenv.logger = new_logger
  59. end
  60. # The current environment that the app is running in.
  61. #
  62. # When running `rake`, the Rails application is initialized in development, so we have to
  63. # check which rake tasks are being run to determine the environment.
  64. #
  65. # See https://github.com/bkeepers/dotenv/issues/219
  66. def env
  67. @env ||= if defined?(Rake.application) && Rake.application.top_level_tasks.grep(TEST_RAKE_TASKS).any?
  68. env = Rake.application.options.show_tasks ? "development" : "test"
  69. ActiveSupport::EnvironmentInquirer.new(env)
  70. else
  71. ::Rails.env
  72. end
  73. end
  74. TEST_RAKE_TASKS = /^(default$|test(:|$)|parallel:spec|spec(:|$))/
  75. def deprecator # :nodoc:
  76. @deprecator ||= ActiveSupport::Deprecation.new
  77. end
  78. # Rails uses `#method_missing` to delegate all class methods to the
  79. # instance, which means `Kernel#load` gets called here. We don't want that.
  80. def self.load
  81. instance.load
  82. end
  83. initializer "dotenv", after: :initialize_logger do |app|
  84. if logger.is_a?(ReplayLogger)
  85. self.logger = ActiveSupport::TaggedLogging.new(::Rails.logger).tagged("dotenv")
  86. end
  87. end
  88. initializer "dotenv.deprecator" do |app|
  89. app.deprecators[:dotenv] = deprecator if app.respond_to?(:deprecators)
  90. end
  91. initializer "dotenv.autorestore" do |app|
  92. require "dotenv/autorestore" if autorestore
  93. end
  94. config.before_configuration { load }
  95. end
  96. Railtie = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("Dotenv::Railtie", "Dotenv::Rails", Dotenv::Rails.deprecator)
  97. end