Skip to content

Commit

Permalink
Refactor Rails integration
Browse files Browse the repository at this point in the history
  • Loading branch information
bkeepers committed Jan 20, 2024
1 parent f052339 commit 6ed39f3
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 40 deletions.
35 changes: 17 additions & 18 deletions lib/dotenv/rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,33 @@
end

module Dotenv
# Dotenv Railtie for using Dotenv to load environment from a file into
# Rails applications
# Rails integration for using Dotenv to load ENV variables from a file
class Rails < ::Rails::Railtie
def self.deprecator # :nodoc:
@deprecator ||= ActiveSupport::Deprecation.new
end
attr_accessor :mode, :files

def initialize
config.dotenv = ActiveSupport::OrderedOptions.new.merge!(
mode: :load,
files: [
root.join(".env.#{env}.local"),
(root.join(".env.local") unless env.test?),
root.join(".env.#{env}"),
root.join(".env")
].compact
)
@mode = :load
@files = [
root.join(".env.#{env}.local"),
(root.join(".env.local") unless env.test?),
root.join(".env.#{env}"),
root.join(".env")
].compact
end

# Public: Load dotenv
#
# This will get called during the `before_configuration` callback, but you
# can manually call `Dotenv::Railtie.load` if you needed it sooner.
def load
Dotenv.load(*config.dotenv.files)
Dotenv.load(*files)
end

# Public: Reload dotenv
#
# Same as `load`, but will override existing values in `ENV`
def overload
Dotenv.overload(*config.dotenv.files)
Dotenv.overload(*files)
end

# Internal: `Rails.root` is nil in Rails 4.1 before the application is
Expand Down Expand Up @@ -72,19 +67,23 @@ def env
env
end

def deprecator # :nodoc:
@deprecator ||= ActiveSupport::Deprecation.new
end

# Rails uses `#method_missing` to delegate all class methods to the
# instance, which means `Kernel#load` gets called here. We don't want that.
def self.load
instance.load
end

initializer "dotenv.deprecator" do |app|
app.deprecators[:dotenv] = Dotenv::Railtie.deprecator
app.deprecators[:dotenv] = deprecator
end

config.before_configuration do
Dotenv.instrumenter = ActiveSupport::Notifications
config.dotenv.mode == :load ? load : overload
mode == :load ? load : overload
end
end

Expand Down
31 changes: 9 additions & 22 deletions spec/dotenv/rails_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,6 @@
require "rails"
require "dotenv/rails"

# Fake watcher for Spring
class SpecWatcher
attr_reader :items

def initialize
@items = []
end

def add(*items)
@items |= items
end
end

describe Dotenv::Rails do
before do
# Remove the singleton instance if it exists
Expand All @@ -23,7 +10,7 @@ def add(*items)
Rails.env = "test"
allow(Rails).to receive(:root).and_return Pathname.new(__dir__).join('../fixtures')
Rails.application = double(:application)
Spring.watcher = SpecWatcher.new
Spring.watcher = Set.new # Responds to #add
end

after do
Expand All @@ -32,11 +19,11 @@ def add(*items)
Rails.application = nil
end

describe "config.dotenv.files" do
describe "files" do
it "loads files for development environment" do
Rails.env = "development"

expect(Dotenv::Rails.config.dotenv.files).to eql(
expect(Dotenv::Rails.files).to eql(
[
Rails.root.join(".env.development.local"),
Rails.root.join(".env.local"),
Expand All @@ -48,7 +35,7 @@ def add(*items)

it "does not load .env.local in test rails environment" do
Rails.env = "test"
expect(Dotenv::Rails.config.dotenv.files).to eql(
expect(Dotenv::Rails.files).to eql(
[
Rails.root.join(".env.test.local"),
Rails.root.join(".env.test"),
Expand All @@ -67,7 +54,7 @@ def add(*items)
end

context "with mode = :overload" do
before { Dotenv::Rails.config.dotenv.mode = :overload }
before { Dotenv::Rails.mode = :overload }

it "calls #overload" do
expect(Dotenv::Rails.instance).to receive(:overload)
Expand All @@ -80,13 +67,13 @@ def add(*items)
before { Dotenv::Rails.load }

it "watches .env with Spring" do
expect(Spring.watcher.items).to include(Rails.root.join(".env").to_s)
expect(Spring.watcher).to include(Rails.root.join(".env").to_s)
end

it "watches other loaded files with Spring" do
path = fixture_path("plain.env")
Dotenv.load(path)
expect(Spring.watcher.items).to include(path)
expect(Spring.watcher).to include(path)
end

it "loads .env.test before .env" do
Expand All @@ -95,7 +82,7 @@ def add(*items)

it "loads configured files" do
expect(Dotenv).to receive(:load).with("custom.env")
Dotenv::Rails.config.dotenv.files = ["custom.env"]
Dotenv::Rails.files = ["custom.env"]
Dotenv::Rails.load
end

Expand All @@ -120,7 +107,7 @@ def add(*items)

it "loads configured files" do
expect(Dotenv).to receive(:overload).with("custom.env")
Dotenv::Rails.config.dotenv.files = ["custom.env"]
Dotenv::Rails.files = ["custom.env"]
Dotenv::Rails.overload
end

Expand Down

0 comments on commit 6ed39f3

Please sign in to comment.