A website built in Common Lisp using Caveman2 as its framework. It is based on a collection of tutorials written by hyotang666. Those tutorials are based on chapters from the book 'Basic Ruby on Rails'. hyotang666 ported the Ruby code to Common Lisp.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

103 lines
3.2 KiB

(in-package :cl-user)
(defpackage rails-to-caveman.web
(:use :cl
:caveman2
:rails-to-caveman.config
:rails-to-caveman.view
:rails-to-caveman.db
:datafly
:sxql)
(:export :*web*))
(in-package :rails-to-caveman.web)
;; for @route annotation
(syntax:use-syntax :annot)
;;
;; Application
(defclass <web> (<app>) ())
(defvar *web* (make-instance '<web>))
(clear-routing-rules *web*)
;;
;; Routing rules
(defroute "/" ()
(render #P"index.html"))
(defroute "/about" ()
(render #P"about.html" '(:page-title "About")))
(defroute "/hello/:name" (&key name)
;; Substitutes `:name' with `name'.
(format nil "Hello, ~A" name))
(defroute "/say/*/to/*" (&key splat)
;; If route is /say/hello/to/world (in the browser). It will match
;; to /say/hello/to/world. 'hello' and 'world' are the wildcard
;; values in this example.
(format nil "~A" splat))
(defroute ("/hello/([\\w]+)" :regexp t) (&key captures)
;; Parse the second part of the URL via a regular expression
;; (regexp). The result of the parsed regexp text is stored in
;; `captures', hence the use of 'first' in the format string.
(format nil "Hello, ~A!" (first captures)))
(defroute "/hello/?:name?" (&key name)
;; Generates two types of routes:
;; 1. /hello/earth
;; 2. /hello?NAME=earth
;; The query string must be in UPPERCASE. Otherwise, the `name' will
;; be bound to `nil'.
(format nil "Hello, ~A" name))
(defroute "/hello/?:name?" (&key |name|)
;; If you want the query string in lowercase, enclose `name' (in
;; this case) with vertical bars '|'. This will force you to have
;; only one route (unlike the route above). `NAME' will now bind to
;; `nil'.
;; 1. /hello?name=earth
;; 2. /hello?NAME=earth <--- no longer works ('earth' binds to nil).
;; 3. /hello/earth <--- no longer works
(format nil "Hello, ~A" |name|))
(defroute "/lesson/step*/:name" (&key splat name)
;; Directory style: Working with Parameters.
;; Example URL: /lesson/step1/Sato
(case (parse-integer (car splat) :junk-allowed t)
(1 (format nil "Hello, ~A" name))))
(defroute "/lesson/step*" (&key splat (|name| "Anonymous"))
;; 'Anonymous' is the default value for `|name|'.
;; Query style: Working with Parameters.
;; Example URL: lesson/step1?name=Sato
(case (parse-integer (car splat) :junk-allowed t)
(1 (format nil "Hello, ~A" |name|))))
(defroute "/lesson/step*" (&key splat name)
;; If /lesson/step1 is used, it will be redirected to /lesson/step2,
;; then /lesson/step3 and finally /lesson/step4. No matter where you
;; start (along as it is below 4), the redirects will always take
;; you wot /lesson/step4.
;; The example includes `name' but it is never used. I am keeping it
;; here for consistency between the reference material and this code
;; base.
(case (parse-integer (car splat) :junk-allowed t)
(1 '(302 (:location "/lesson/step2")))
(2 '(302 (:location "/lesson/step3")))
(3 '(302 (:location "/lesson/step4")))
(4 "Moved to step4")))
;;
;; Error pages
(defmethod on-exception ((app <web>) (code (eql 404)))
(declare (ignore app))
(merge-pathnames #P"_errors/404.html"
*template-directory*))