Fork me on GitHub
#duct
<
2021-01-07
>
roelof09:01:36

Good morning

roelof09:01:03

Im trying to follow the tutorial on duct

roelof09:01:19

and have to add something for migrations

roelof09:01:33

so I did change the file to this :

{:duct.profile/base
 {:duct.core/project-ns todo

  :duct.router/ataraxy
  {:routes {[:get "/"] [:todo.handler/index]}}
   [:duct.handler.static/ok :todo.handler/index]
 {:body {:entries "/entries"}}}
 
:duct.migrator/ragtime
{:migrations [#ig/ref :todo.migration/create-entries]}

[:duct.migrator.ragtime/sql :todo.migration/create-entries]
{:up ["CREATE TABLE entries (id INTEGER PRIMARY KEY, content TEXT)"]
 :down ["DROP TABLE entries"]}
 
 :duct.profile/dev   #duct/include "dev"
 :duct.profile/local #duct/include "local"
 :duct.profile/prod  {}

 :duct.module/logging {}
 :duct.module.web/api
 {}
 :duct.module/sql
 {}}

roelof09:01:13

but now I see this error message

Execution error (IllegalArgumentException) at clojure.java.jdbc/get-connection (jdbc.clj:292).
db-spec null is missing a required parameter

Kevin09:01:04

I think you at least need to move :duct.migrator/ragtime and [:duct.migrator.ragtime/sql :todo.migration/create-entries] into the :duct.profile/base map

Kevin09:01:26

(They are one level higher, in the module level)

Kevin09:01:23

I'm not sure if that'll solve everything though, but that needs to be fixed

roelof09:01:46

hmm, when I check the { it looks the code is inside the map

roelof09:01:20

all the code seems to be in the map

roelof09:01:28

or I misunderstood you

Kevin09:01:16

Here is a fixed version:

{:duct.profile/base
 {:duct.core/project-ns todo

  :duct.router/ataraxy
  {:routes {[:get "/"] [:todo.handler/index]}}

  [:duct.handler.static/ok :todo.handler/index]
  {:body {:entries "/entries"}}

  :duct.migrator/ragtime
  {:migrations [#ig/ref :todo.migration/create-entries]}

  [:duct.migrator.ragtime/sql :todo.migration/create-entries]
  {:up ["CREATE TABLE entries (id INTEGER PRIMARY KEY, content TEXT)"]
   :down ["DROP TABLE entries"]}}

 :duct.profile/dev   #duct/include "dev"
 
 :duct.profile/local #duct/include "local"
 
 :duct.profile/prod  {}
 
 :duct.module/logging {}
 
 :duct.module.web/api {}
 
 :duct.module/sql {}}

Kevin09:01:47

the two keys I mentioned are now inside of the map of :duct.profile/base , not in the top level map

Kevin09:01:21

(You can see the difference in indentation)

roelof09:01:27

thanks, but if I copy/paste your code the layout is messed up

Kevin09:01:56

Because of Slack you mean?

roelof09:01:48

it looks now this in vs code :

{:duct.profile/base
 {:duct.core/project-ns todo  :duct.router/ataraxy
  {:routes {[:get "/"] [:todo.handler/index]}}  [:duct.handler.static/ok :todo.handler/index]
  {:body {:entries "/entries"}}  :duct.migrator/ragtime
  {:migrations [#ig/ref :todo.migration/create-entries]}  [:duct.migrator.ragtime/sql :todo.migration/create-entries]
  {:up ["CREATE TABLE entries (id INTEGER PRIMARY KEY, content TEXT)"]
   :down ["DROP TABLE entries"]}} :duct.profile/dev   #duct/include "dev" :duct.profile/local #duct/include "local" :duct.profile/prod  {} :duct.module/logging {} :duct.module.web/api {} :duct.module/sql {}}

Kevin09:01:00

Yeah that's not good lol

roelof09:01:11

that is better

roelof09:01:15

thanks a lot

Kevin09:01:34

Do you see what's different now?

roelof09:01:06

yep, on my old code everything was intented the same

Kevin09:01:55

Hopefully it'll fix your error. Here's a small overview about the difference between base / profile / module configs https://github.com/duct-framework/duct/wiki/Configuration#duct-base-profiles-and-modules

Kevin09:01:02

Might be useful

roelof10:01:49

hmm maybe a error in the tutorial

First, add a new POST route:

:duct.router/ataraxy
{:routes
 {[:get "/"]        [:todo.handler/index]
  [:get "/entries"] [:todo.handler.entries/list]

  [:post "/entries" {{:keys [description]} :body-params}]
  [:todo.handler.entries/create description]}}

The new Ataraxy route not only matches the method and URI of the request, it also destructures the request body and places the description of the todo entry into the result.

When we come to write the associated handler, we need some way of getting the information from the result. Ataraxy places the result into the :ataraxy/result key on the request map, so we can destructure the request to find the description of the new entry:

[:duct.handler.sql/insert :todo.handler.entries/create]
{:request {[_ description] :ataraxy/result}
 :sql     ["INSERT INTO entries (description) VALUES (?)" description]}

roelof10:01:21

must the last line not be :duct.handler.sql/create ....

roelof10:01:44

because of this error message :

Missing definitions for refs: :todo.handlers.entries.create

Kevin10:01:00

Can you link the tutorial?

Kevin10:01:36

Do you have [duct/handler.sql "0.4.0"] as a dependency in project.clj?

Kevin10:01:33

Also I've never used sql handlers, I feel that it doesn't really give me enough control over my handlers

roelof10:01:49

yes, I have

roelof10:01:03

:dependencies [[org.clojure/clojure "1.10.0"]
                 [duct/core "0.7.0"]
                 [duct/handler.sql "0.4.0"]
                 [duct/module.logging "0.4.0"]
                 [duct/module.web "0.7.0"]
                 [duct/module.ataraxy "0.3.0"]
                 [duct/module.sql "0.5.0"]
                 [org.xerial/sqlite-jdbc "3.25.2"]]

Kevin10:01:32

Can you show me your config?

roelof10:01:38

you mean project.clj or config.edn ?

Kevin10:01:43

config.edn

Kevin10:01:10

Oh I see, you have :todo.handlers.entries.create but I think that should be :todo.handlers.entries/create

Kevin10:01:27

The error is saying it can't find a key for :todo.handlers.entries.create, which makes sense

roelof10:01:56

chips, that sort of errors do I overlooked very often

roelof10:01:16

now another problem not related to duct I think

http post :3000/entries description="Write Duct guide"

http: error: ConnectionError: HTTPConnectionPool(host='localhost', port=3000): Max retries exceeded with url: /entries (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f7c4f0ff4f0>: Failed to establish a new connection: [Errno 111] Connection refused')) while doing POST request to URL: 

Kevin10:01:44

I guess the server isn't started?

Kevin10:01:04

Or wrong port

roelof10:01:37

hmm, you mean the duct server or the sqlite server

Kevin10:01:02

Duct server

Kevin10:01:32

That HTTPie error sounds like it can't connect because it doesn't exist

roelof10:01:21

this is telling me that the duct server is working

roelof10:01:24

user=> (dev)
:loaded

Kevin10:01:59

(dev) switches you to the development namespace (`dev.clj`). Afterwards to start the server you have to use (go)

roelof10:01:31

and now the error re appears again

Execution error (ExceptionInfo) at integrant.core/missing-refs-exception (core.cljc:191).
Missing definitions for refs: :todo.handlers.entries/create

Kevin10:01:40

😕

Kevin10:01:03

Typo again

Kevin10:01:10

s/handlers/handler

roelof10:01:02

finally it worked

roelof10:01:51

maybe after this one look for a tutorial where duct is used to ask a external api

roelof12:01:36

hmmm, and another wierd error:

{:duct.profile/base
 {:duct.core/project-ns todo

  :duct.router/ataraxy
  {:routes {[:get "/"] [:todo.handler/index]
            [:get "/entries"] [:todo.handler.entries/list]

            [:post "/entries" {{:keys [description]} :body-params}]
            [:todo.handler.entries/create description]

            [:get "/entries/" id] [todo.handler.entries/find ^int id]
            [:delete "entries/" id] [todo.handler.entries/destroy ^int id]}}

  [:duct handler.sql/query-one :todo.handler.entries/find]
  {:request {[_ id] :ataraxy/result}
   :sql ["SELECT * FROM entries WHERE id = ?" id]
   :hrefs {:href "entries/{id}"}}

  [:duct.handler.sql/execute :todo.handler.entries/destroy]
  {:request {[_ id] :ataraxy/result}
   :sql ["DELETE FROM entries WHERE id =?" id]}

  [:duct.handler.static/ok :todo.handler/index]
  {:body {:entries "/entries"}}

  [:duct.handler.sql/query :todo.handler.entries/list]
  {:sql ["SELECT * FROM entries"]
   :hrefs {:href "/entries/{id}"}}

  [:duct.handler.sql/insert :todo.handler.entries/create]
  {:request {[_ description] :ataraxy/result}
   :sql     ["INSERT INTO entries (description) VALUES (?)" description]
   :location "entries/{last_insert_rowid}"}

  :duct.migrator/ragtime
  {:migrations [#ig/ref :todo.migration/create-entries]}

  [:duct.migrator.ragtime/sql :todo.migration/create-entries]
  {:up ["CREATE TABLE entries (id INTEGER PRIMARY KEY, description TEXT)"]
   :down ["DROP TABLE entries"]}}

 :duct.profile/dev   #duct/include "dev"
 :duct.profile/local #duct/include "local"
 :duct.profile/prod  {}
 :duct.module/logging {}
 :duct.module.web/api {}
 :duct.module/sql {}}

roelof12:01:56

reset)
:reloading ()
Execution error (AssertionError) at integrant.core/eval3789$fn (core.cljc:64).
Assert failed: (namespace parent)

Kevin12:01:13

The error is super cryptic (A bit of an Integrant issue). But I looks like you have a typo here: [:duct handler.sql/query-one :todo.handler.entries/find]

Kevin12:01:18

Missing a dot

roelof12:01:02

pff changed it

roelof12:01:11

but now see this :

Execution error (AssertionError) at ataraxy.core/parse (core.clj:105).
Assert failed: (valid? routes)

Kevin12:01:52

Apparently the syntax isn't correct for :routes

roelof12:01:46

oke, I copied the code from the tutorial and everything is working

roelof13:01:59

oke, done that one

roelof13:01:27

are there more tutorials I can follow to get more familiar with duct ?

Kevin13:01:58

There aren't many tutorials sadly. But be sure to understand how Integrant works https://github.com/weavejester/integrant/

âž• 3
Kevin13:01:10

Because that's about 90% of what Duct is

roelof13:01:33

Will read that well

roelof13:01:58

and maybe it is then better to write my own toy-project

roelof13:01:06

but no today

roelof13:01:12

maybe a piece of a galllery I wanted to build or a part of a crm I have in mind