Add lib/ to $LOAD_PATH before loading app file (#1251)
This makes it possible to require files from lib/ at conventional spot at the top of the file, rather than inside the body of the app class.
This commit is contained in:
parent
70d86d047e
commit
c963882a3c
|
@ -1,5 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "pathname"
|
||||||
require "zeitwerk"
|
require "zeitwerk"
|
||||||
require_relative "hanami/constants"
|
require_relative "hanami/constants"
|
||||||
|
|
||||||
|
@ -36,7 +37,8 @@ module Hanami
|
||||||
app_path = self.app_path
|
app_path = self.app_path
|
||||||
|
|
||||||
if app_path
|
if app_path
|
||||||
require(app_path)
|
prepare_load_path
|
||||||
|
require(app_path.to_s)
|
||||||
app
|
app
|
||||||
elsif raise_exception
|
elsif raise_exception
|
||||||
raise(
|
raise(
|
||||||
|
@ -47,6 +49,23 @@ module Hanami
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Prepare the load path as early as possible (based on the default root inferred from the location
|
||||||
|
# of `config/app.rb`), so `require` can work at the top of `config/app.rb`. This may be useful
|
||||||
|
# when external classes are needed for configuring certain aspects of the app.
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
# @since 2.0.0
|
||||||
|
private_class_method def self.prepare_load_path
|
||||||
|
lib_path = app_path&.join("..", "..", LIB_DIR)
|
||||||
|
|
||||||
|
if lib_path&.directory?
|
||||||
|
path = lib_path.realpath.to_s
|
||||||
|
$LOAD_PATH.prepend(path) unless $LOAD_PATH.include?(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
lib_path
|
||||||
|
end
|
||||||
|
|
||||||
# Returns the Hamami app class.
|
# Returns the Hamami app class.
|
||||||
#
|
#
|
||||||
# To ensure your Hanami app is loaded, run {.setup} (or `require "hanami/setup"`) first.
|
# To ensure your Hanami app is loaded, run {.setup} (or `require "hanami/setup"`) first.
|
||||||
|
@ -98,10 +117,10 @@ module Hanami
|
||||||
# Searches within the given directory, then searches upwards through parent directories until the
|
# Searches within the given directory, then searches upwards through parent directories until the
|
||||||
# app file can be found.
|
# app file can be found.
|
||||||
#
|
#
|
||||||
# @param dir [String] The directory from which to start searching. Defaults to the current
|
# @param dir [String, Pathname] The directory from which to start searching. Defaults to the
|
||||||
# directory.
|
# current directory.
|
||||||
#
|
#
|
||||||
# @return [String, nil] the app file path, or nil if not found.
|
# @return [Pathname, nil] the app file path, or nil if not found.
|
||||||
#
|
#
|
||||||
# @api public
|
# @api public
|
||||||
# @since 2.0.0
|
# @since 2.0.0
|
||||||
|
@ -110,7 +129,7 @@ module Hanami
|
||||||
path = dir.join(APP_PATH)
|
path = dir.join(APP_PATH)
|
||||||
|
|
||||||
if path.file?
|
if path.file?
|
||||||
path.to_s
|
path
|
||||||
elsif !dir.root?
|
elsif !dir.root?
|
||||||
app_path(dir.parent)
|
app_path(dir.parent)
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,11 +29,6 @@ module Hanami
|
||||||
subclass.class_eval do
|
subclass.class_eval do
|
||||||
@config = Hanami::Config.new(app_name: slice_name, env: Hanami.env)
|
@config = Hanami::Config.new(app_name: slice_name, env: Hanami.env)
|
||||||
|
|
||||||
# Prepare the load path (based on the default root of `Dir.pwd`) as early as possible, so
|
|
||||||
# you can make a `require` inside the body of an `App` subclass, which may be useful for
|
|
||||||
# certain kinds of app configuration.
|
|
||||||
prepare_load_path
|
|
||||||
|
|
||||||
load_dotenv
|
load_dotenv
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -82,6 +82,40 @@ RSpec.describe "Code loading / Loading from lib directory", :app_integration do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "default root with requires at top of app file" do
|
||||||
|
before :context do
|
||||||
|
with_directory(@dir = make_tmp_directory.realpath) do
|
||||||
|
write "config/app.rb", <<~'RUBY'
|
||||||
|
require "hanami"
|
||||||
|
require "external_class"
|
||||||
|
|
||||||
|
module TestApp
|
||||||
|
class App < Hanami::App
|
||||||
|
@class_from_lib = ExternalClass
|
||||||
|
|
||||||
|
def self.class_from_lib
|
||||||
|
@class_from_lib
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
write "lib/external_class.rb", <<~'RUBY'
|
||||||
|
class ExternalClass
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
with_directory(@dir) { require "hanami/setup" }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify "classes in lib/ can be required directly from the top of the app file" do
|
||||||
|
expect(Hanami.app.class_from_lib).to be ExternalClass
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "app root reconfigured" do
|
context "app root reconfigured" do
|
||||||
before :context do
|
before :context do
|
||||||
with_directory(@dir = make_tmp_directory.realpath) do
|
with_directory(@dir = make_tmp_directory.realpath) do
|
||||||
|
|
|
@ -126,7 +126,7 @@ RSpec.describe "Hanami setup", :app_integration do
|
||||||
with_tmp_directory(Dir.mktmpdir) do
|
with_tmp_directory(Dir.mktmpdir) do
|
||||||
write "config/app.rb"
|
write "config/app.rb"
|
||||||
|
|
||||||
expect(app_path).to match(%r{^/.*/config/app.rb$})
|
expect(app_path.to_s).to match(%r{^/.*/config/app.rb$})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -138,7 +138,7 @@ RSpec.describe "Hanami setup", :app_integration do
|
||||||
write "lib/foo/bar/.keep"
|
write "lib/foo/bar/.keep"
|
||||||
|
|
||||||
Dir.chdir("lib/foo/bar") do
|
Dir.chdir("lib/foo/bar") do
|
||||||
expect(app_path).to match(%r{^/.*/config/app.rb$})
|
expect(app_path.to_s).to match(%r{^/.*/config/app.rb$})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue