duct

2019-01-30T01:12:38.057200Z

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

2019-01-30T01:13:39.057800Z

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

2019-01-30T01:14:35.057900Z

@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"}} }

2019-01-30T01:15:06.058400Z

You should place the handler inside the base profile.

2019-01-30T01:15:24.058900Z

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

2019-01-30T01:16:06.059600Z

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

2019-01-30T01:17:39.059700Z

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

2019-01-30T01:18:13.060200Z

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

2019-01-30T01:20:03.060300Z

I think I've learned the lesson at hand though

2019-01-30T01:20:10.060400Z

So thanks

2019-01-30T01:21:15.060500Z

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

2019-01-30T01:21:33.060800Z

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

2019-01-30T01:56:51.060900Z

@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.

2019-01-30T01:57:46.061300Z

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

2019-01-30T01:57:50.061500Z

So:

2019-01-30T01:58:37.062400Z

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

2019-01-30T01:58:42.062600Z

However, you can also write:

2019-01-30T01:59:11.063200Z

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

2019-01-30T01:59:37.063800Z

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

2019-01-30T02:00:04.064500Z

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

2019-01-30T02:00:31.065100Z

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

2019-01-30T02:00:56.065600Z

Ah I wasn't clear if that was still legal

2019-01-30T02:01:30.066200Z

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

2019-01-30T02:01:46.066600Z

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

2019-01-30T02:05:57.066700Z

I have limped on to the next step...

2019-01-30T02:21:20.067100Z

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

2019-01-30T02:22:36.067200Z

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 `

2019-01-30T02:22:48.067300Z

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

2019-01-30T02:24:13.068100Z

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

2019-01-30T02:24:41.068700Z

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

2019-01-30T02:25:20.068800Z

List entries key:

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

2019-01-30T02:26:38.068900Z

Which is placed inside the project-ns map

2019-01-30T02:27:03.069300Z

Do you have the right dependency?

2019-01-30T02:27:10.069600Z

duct/handler.sql I think.

2019-01-30T02:31:44.070Z

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

2019-01-30T02:32:33.070100Z

Right, i added it. Sorry.

2019-01-30T02:33:10.070800Z

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

2019-01-30T02:33:43.071500Z

So:

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

2019-01-30T02:34:18.071600Z

Yes, I got

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

2019-01-30T02:34:43.071900Z

It sounds like you don't have Integrant 0.7.0

2019-01-30T02:35:07.072400Z

Haha i just got what was in the template

2019-01-30T02:35:16.072600Z

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

2019-01-30T02:35:28.072900Z

If you add in Integrant 0.7.0 it should work.

2019-01-30T02:35:52.073500Z

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

2019-01-30T02:36:14.074100Z

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

2019-01-30T02:36:48.074500Z

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

2019-01-30T02:40:25.074600Z

Real life is intruding. Can we finish this tomorrw?

2019-01-30T02:40:35.074800Z

Sure.

2019-01-30T02:40:43.075Z

Thanks again

2019-01-30T02:40:49.075200Z

I might have the guide updated by then.

2019-01-30T02:41:30.075300Z

If you don't I promise to do it myself

2019-01-30T02:41:41.075500Z

Thanks 🙂

2019-01-30T10:21:25.079800Z

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

2019-01-30T10:23:17.080300Z

why is that?

2019-01-30T14:48:16.080800Z

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

2019-01-30T14:52:57.082Z

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

2019-01-30T14:54:30.082900Z

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

2019-01-30T14:58:24.084200Z

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.

2019-01-30T14:58:53.084900Z

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

2019-01-30T14:59:18.085400Z

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

2019-01-30T14:59:48.085700Z

So for example:

2019-01-30T15:01:06.086700Z

(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)))))

2019-01-30T15:01:57.087300Z

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

2019-01-30T15:02:29.087900Z

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.

2019-01-30T15:04:05.088100Z

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

2019-01-30T15:04:28.088500Z

It references a configuration key called ::devcards

2019-01-30T15:05:01.088800Z

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

2019-01-30T15:06:32.090500Z

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

2019-01-30T15:08:35.091600Z

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

2019-01-30T15:08:52.092Z

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

2019-01-30T15:09:24.092700Z

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

2019-01-30T15:09:40.093200Z

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

2019-01-30T15:09:49.093500Z

This produces a configuration of modules.

2019-01-30T15:10:06.094Z

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

2019-01-30T15:10:26.094500Z

This Integrant configuration is initiated to produce the system.

2019-01-30T15:10:53.095100Z

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

2019-01-30T15:11:08.095500Z

Duct config -> Integrant config -> running system

2019-01-30T15:13:38.096900Z

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))))

2019-01-30T15:15:23.098300Z

And then in your dev.edn:

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

2019-01-30T15:16:56.099100Z

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

2019-01-30T15:17:00.099400Z

Right

2019-01-30T15:17:44.100900Z

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

2019-01-30T15:17:56.101100Z

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.

2019-01-30T15:19:24.101800Z

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

2019-01-30T15:19:36.102Z

sure

2019-01-30T15:22:52.102600Z

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

2019-01-30T15:23:36.103400Z

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! 🙂

2019-01-30T15:42:12.103800Z

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

2019-01-30T15:42:55.104600Z

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

2019-01-30T15:43:22.104800Z

ok

scottlowe 2019-01-30T16:12:09.104900Z

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 🙂

2019-01-30T16:15:13.105200Z

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 🙂

1
2019-01-30T16:15:52.105700Z

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

👏 4
2019-01-30T21:00:30.111600Z

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?

2019-01-30T21:39:05.114Z

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