I want to have routes defined over multiple files, not just web.lisp. What is the correct way of doing this?
I tried writing another file with this code and it works:
(in-package :mywebapp.web)
;; for @route annotation
(syntax:use-syntax :annot)
(defroute "/hello" ()
(format nil "Hello World!"))
However, what I thought was the correct approach was to have another package definition and then either import :mywebapp.web
into my new package, or import my new package :mywebapp.controllers.hello
into :mywebapp.web
.
Can you please explain to me the correct approach?
When I created my own package and imported :mywebapp.web
I got the following error:
There is no applicable method for the generic function #<STANDARD-GENERIC-FUNCTION (COMMON-LISP:SETF NINGLE/APP:ROUTE) (1)> when called with arguments (#<FUNCTION (LAMBDA (#:PARAMS1141) :IN "/project/src/controllers/hello.lisp") {53CE5F6B}> NIL "/hello"). See also: The ANSI Standard, Section 7.6.6
However I had imported into the new packages all the same imports as in the .web
package...
Note that I redacted the path...
Thanks!
So, in package CL-USER (in the REPL) I wrote the following form and asked Emacs/Slime for its macroexpansion:
(caveman2:defroute "/hello" ())
The result is:
(SETF (APPLY #'NINGLE/APP:ROUTE
(CONS
(CAVEMAN2.APP:FIND-PACKAGE-APP #<PACKAGE "COMMON-LISP-USER">)
(LIST "/hello")))
(LAMBDA (#:PARAMS1721) (DECLARE (IGNORABLE #:PARAMS1721))))
This corresponds to your error, because ultimately when combining apply
with the (cons ...)
forms, the code will be calling route
with the result of find-package-app
and "/hello"
.
But in your case, the result of find-package-app
is NIL, meaning no such app was found. I probably would have expected a better error message here, but anyway the solution is to explicitly specify the application:
(caveman2:defroute (other-package:*app* "/hello") ())
This macroexpands as:
(SETF (APPLY #'NINGLE/APP:ROUTE (LIST OTHER-PACKAGE:*APP* "/hello"))
(LAMBDA (#:PARAMS1723) (DECLARE (IGNORABLE #:PARAMS1723))))
There is however little documentation about that, I had to look at the source code.
Basically when an application is instantiated, the current value of *package*
is captured and associated in a hash-table to the application instance.