Genie.jl icon indicating copy to clipboard operation
Genie.jl copied to clipboard

Code loading for Multi-file controller modules in Genie v5

Open angusmoore opened this issue 1 year ago • 4 comments

Changes to code loading for Genie v5 seem to have broken support for multi-file modules in app/resources.

To reproduce, a simple templated Genie app with the following controller and routes.jl

routes.jl

using Genie.Router
using WatchTonight.TestController
import Random

const rng = Random.MersenneTwister()

route("/") do
  serve_static_file("welcome.html")
end

route("/test") do
  TestController.test_function(rng)
end

app/resources/TestController/TestController.jl

module TestController
import UUIDs, Random

include("a.jl")

end

app/resources/TestController/a.jl

test_function(rng::Random.AbstractRNG) = UUIDs.uuid4(rng)

This will throw during the "Loading resources" step: ERROR: UndefVarError: Random not defined.

My guess is this is happening because code loading is trying to include (app/resources/TestController/a.jl) as a standalone file, rather than through TestController.jl, which means Random hasn't been imported.

Moving all the code into a single-file module works fine (eg moving the contents of a.jl into TestController.jl). That's obviously fine for small examples like this, but for large, complex controllers it's nice to be able to break up into files. If that's just not possible to support, probably worth documenting in the v4 => v5 migration docs, as multi-file modules worked fine in v4 (eg this example works as expected with v4).

angusmoore avatar Aug 08 '22 01:08 angusmoore

@angusmoore Currently working on a set of features to make auto-loading more powerful and flexible (configurable). It will allow setting the load order and ignoring files, among other things. What happens is that the Genie loader thinks that a.jl is a model and attempts to load it.

What you can do right now to fix it is to: a) create a folder inside app/resources/TestController/, for ex includes/ b) inside this folder put the files like a.jl c) also inside this folder create an empty .autoload_ignore file - this will tell Genie to ignore all the files in the folder from auto-loading.

(Let's leave this open, it will be a good test for the upcoming features).

essenciary avatar Aug 08 '22 09:08 essenciary

Alternatively you can host these files outside the app/resources/<resource>/ folder, for instance in app/includes and they won't be auto-loaded.

essenciary avatar Aug 08 '22 09:08 essenciary

Yet another optimisation we could do is to not autoload files that start with lowercase letters (as the Julia best practices recommend modules to start with uppercase letters). However, this would be a breaking change.

essenciary avatar Aug 08 '22 09:08 essenciary

Great, thanks @essenciary, that's really helpful. I'll use that workaround with .autoload_ignore. But, yes, happy to leave this open for discussion of upcoming features.

angusmoore avatar Aug 09 '22 05:08 angusmoore

Closing this as .autoload_ignore and the new .autoload allow controlling the loading order.

essenciary avatar Sep 07 '23 14:09 essenciary