Fork me on GitHub
#duct
<
2019-01-30
>
colliderwriter01:01:38

Once again trying to navigate the GUIDE.rst with 0.11 and when adding the Static Route, dev> (reset) :reloading (todo.main dev user) :duct.server.http.jetty/stopping-server Execution error (IllegalArgumentException) at integrant.core/resume$fn (core.cljc:450). No method in multimethod 'init-key' for dispatch value: :body

weavejester01:01:39

@colliderwriter Could you send me your configuration? My work on updating the guide has been a little sidetracked.

colliderwriter01:01:35

@weavejester Here's what I have: {:duct.profile/base {:duct.core/project-ns todo :duct.router/ataraxy {:routes {[:get "/"] [:index]} :handlers {:index :todo.handler/index} }} :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 {} [:duct.handler.static/ok :todo.handler/index] {:body {:entries "/entries"}} }

weavejester01:01:06

You should place the handler inside the base profile.

weavejester01:01:24

In 0.11, the configuration contains only modules or profiles (which are a type of module).

weavejester01:01:06

Mixing modules and normal keys generated too many issues, whereas separating them makes the setup process simpler.

colliderwriter01:01:39

Got it, edited, works. Sorry for my confusion.

weavejester01:01:13

No problem - it's my own fault. The guide really needs to be updated.

colliderwriter01:01:03

I think I've learned the lesson at hand though

colliderwriter01:01:15

If I can feel my way through the rest of the guide, I promise to submit a PR for an updated version

weavejester01:01:33

If you have any more questions, just send them my way.

colliderwriter01:01:51

@weavejester I'm afraid I do have another. WHen I add the route inside the base profile, I can (reset) without any errors, but i still get the 404 with the "not-found" body as if I had not edited it at all.

weavejester01:01:46

Oh, I think you're missing an #ig/ref.

weavejester01:01:37

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

weavejester01:01:42

However, you can also write:

weavejester01:01:11

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

weavejester01:01:37

The Ataraxy router has a ig/prep stage where it fills in the handlers if they're not specified.

weavejester02:01:04

The Ataraxy module still exists as well, so you could also write:

weavejester02:01:31

:duct.module/ataraxy
{[:get "/"] [:index]}

colliderwriter02:01:56

Ah I wasn't clear if that was still legal

weavejester02:01:30

Which is more concise, but lots of people thought it was too confusing

weavejester02:01:46

So when writing the router, I decided that it's better to be explicit.

colliderwriter02:01:57

I have limped on to the next step...

weavejester02:01:20

I'm going to try and find some time tomorrow to revise the guide.

colliderwriter02:01:36

I made it over a couple more hurdles but my best guess when adding the query route was

:duct.router/ataraxy
  {:routes {[:get "/"] [:index]
            [:get "/entries"] [:entries/list]}
   :handlers {:index #ig/ref :todo.handler/index
              :entries/list #ig/ref :todo.handler.entries/list}}
which fails at (reset) with `

colliderwriter02:01:48

No method in multimethod 'init-key' for dispatch value: :integrant.composite/duct.handler.sql.query+todo.handler.entries.list_29426

weavejester02:01:13

That's essentially saying "I can't find any multimethod for any of the keys in the composite key"

weavejester02:01:41

What does your list entries key look like, and do you have the required dependencies?

colliderwriter02:01:20

List entries key:

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

colliderwriter02:01:38

Which is placed inside the project-ns map

weavejester02:01:03

Do you have the right dependency?

weavejester02:01:10

duct/handler.sql I think.

weavejester02:01:44

So in your dependencies, @colliderwriter, you should have [duct/handler.sql "0.3.1"]

colliderwriter02:01:33

Right, i added it. Sorry.

weavejester02:01:10

You might also need to add in the :db key manually, because I haven't updated the duct/handler.sql library yet either.

weavejester02:01:43

So:

[:duct.handler.sql/query :todo.handler.entries/list]
{:db #ig/ref :duct.database/sql
 :sql ["SELECT * FROM entries"]}

colliderwriter02:01:18

Yes, I got

user> (dev)
Syntax error compiling at (merge.clj:102:11).
No such var: ig/reflike?

weavejester02:01:43

It sounds like you don't have Integrant 0.7.0

colliderwriter02:01:07

Haha i just got what was in the template

weavejester02:01:16

So a dependency (maybe handler.sql because it's old) might be overriding it.

weavejester02:01:28

If you add in Integrant 0.7.0 it should work.

weavejester02:01:52

But if you run lein deps :tree it should tell you what dependency is overriding Integrant and replacing it with an older version.

weavejester02:01:14

Leiningen always chooses the "nearest" dependency to your project file, but that's not always the most up to date.

weavejester02:01:48

[integrant "0.7.0"] I think is the dependency you want to add.

colliderwriter02:01:25

Real life is intruding. Can we finish this tomorrw?

weavejester02:01:49

I might have the guide updated by then.

colliderwriter02:01:30

If you don't I promise to do it myself

myguidingstar10:01:25

I've just update my fullstack app to latest duct from v0.10. The only problem I have is this custom module no longer works. It tries to tweak figwheel config a little bit

weavejester14:01:16

@myguidingstar That looks okay... Could you show me an example of use?

weavejester14:01:57

Ah, I see. You're putting it in the dev profile.

weavejester14:01:30

Give me a minute or two to think about the best way forward for this.

weavejester14:01:24

Okay, so in Duct 0.11 I separated out Duct modules from Integrant's normal component keys. Mixing the two caused too many issues, even if it was convenient.

weavejester14:01:53

This does mean that you can't place modules inside profiles, since profiles are a type of module.

weavejester14:01:18

However, what you can do is make the module more generic, and add in keys that the module uses.

weavejester14:01:48

So for example:

weavejester15:01:06

(defmethod ig/init-key :fulcro.module/devcards [_ {build-id :build-id :or {build-id 0}}]
  (fn [config]
    (-> config
      (update-in [:duct.server/figwheel :builds build-id :build-options :preloads] 
        conj (ig/ref ::preloads)
      (assoc-in [:duct.server/figwheel :builds build-id :build-options :devcards]
(ig/ref ::devcards)))))

weavejester15:01:57

There's probably a more elegant way of arranging that, but hopefully you get the idea?

weavejester15:01:29

I'm also going to try and make the cljs stuff more easily configurable in future as well, so this should be less of an issue.

myguidingstar15:01:05

what is that (ig/ref ::devcards) for?

weavejester15:01:28

It references a configuration key called ::devcards

weavejester15:01:01

Let me check the module.cljs to see if there's a more elegant way of doing this.

myguidingstar15:01:32

so the separation of Duct modules from Integrant's normal components means only modules can "modify" other modules?

weavejester15:01:35

Not quite; modules can modify the configuration, but they can't modify other modules.

weavejester15:01:52

Profiles are just a type of module that merges its value into the configuration.

weavejester15:01:24

Duct now separates out each stage, whereas before they were all mixed together.

weavejester15:01:40

So first of all there's a read stage, which also handles reading included files.

weavejester15:01:49

This produces a configuration of modules.

weavejester15:01:06

The modules are initiated, composed, and then this produces an Integrant configuration.

weavejester15:01:26

This Integrant configuration is initiated to produce the system.

weavejester15:01:53

You can think of the Duct module configuration as a "higher level" configuration. It's a configuration that produces a configuration.

weavejester15:01:08

Duct config -> Integrant config -> running system

weavejester15:01:38

So back to your problem. A better solution might be to write:

(require '[duct.core :as duct])

(defmethod ig/init-key :fulcro.module/cljs-build-options [_ _]
  (fn [config]
    (update-in config
               [:duct.server/figwheel :builds build-id :build-options]
               duct/merge-configs
               (:fulcro/cljs-build-options config))))

weavejester15:01:23

And then in your dev.edn:

{:fulcro/cljs-build-options
 {:preloads [fulcro.inspect.preload]
  :devcards false}}

myguidingstar15:01:56

and I'll need {:fulcro.module/cljs-build-options {}} to initiate it config.edn?

myguidingstar15:01:44

is there a better verb to use in place the above "initiate it"?

weavejester15:01:56

This should be a lot easier. I'm looking at the code for module.cljs and I think I can modify it so that changes like these won't need a module to alter the code.

scottlowe16:01:09

I’m excited to hear that you are thinking about this friction with module.cljs. I’ve been meaning to write to you about this issue. There’s hundreds of options that can be passed to the ClojureScript compiler and passing them through to module.cljs has been somewhat awkward of late. Especially once one starts adding foreign JS libs and externs to the system. Somewhat related: You mentioned here recently that you were looking at shadow-cljs with reference to recent figwheel compatibility issues. I got frustrated with the figwheel situation and also had problems integrating third party JS libs which used different JS module systems, so switched to shadow-cljs. It was a painless experience and everything worked first time! shadow-cljs is really that good. Nice and fast too 🙂

weavejester16:01:13

I should be doing some work with Duct and cljs within the next month or so, so it's in my best interests to take another look 🙂

5
weavejester15:01:24

Could you possibly open a issue on module.cljs for something like "It should be easier to modify the build options"?

myguidingstar15:01:52

thank you so much for Duct and everything. It's a smooth dev experience 🙂

weavejester15:01:36

No problem. The 0.11 changes could be a lot smoother, though! All I can say about that is that I'll get through the backlog of stuff to do eventually! 🙂

myguidingstar15:01:12

is (derive ::something :duct/module) required anymore?

weavejester15:01:55

No, I don't believe so, although it's not a bad idea to put that in your duct_hierarchy.edn for clarity.

weavejester16:01:52

The guide (https://github.com/duct-framework/docs/blob/master/GUIDE.rst) has now been updated for Duct 0.11.

👏 20
ticean21:01:30

I’d like to extend duct.core.env/coerce to add a 'Keyword coercion. I’ve defined a new`defmethod` but the method doesn’t seem to be registered when config is read. I get No method in multimethod 'coerce' for dispatch value: 'Keyword. I’ve registered the new method in my main.clj where the config is loaded. Do I need to override the #duct/env reader with a version that has the registered dispatch?

ticean21:01:05

Facepalm. I updated main.clj but then tested in the REPL. I helps to modify the right runtime! Requiring the defmethod works just fine.