Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include Rails integration in dotenv gem and refactor #468

Merged
merged 8 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor Rails integration
  • Loading branch information
bkeepers committed Jan 20, 2024
commit 6ed39f396991a55b38a65fea089651b2665a7e17
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