Fork me on GitHub

How do you know if you have the appropriate amount of basic clojure knowledge before diving into this?


You don’t really need a lot of fancy stuff. I’d say you should understand the basics. get-in, assoc-in, update, etc.


you should understand React basics


There’s not a lot of syntax to Clojure. I think a lot of people would be better off if they understood the basics of compilation, since that bites ppl in weird ways. In particular, understanding that there are stages like read, macro expansion, and the actual compile


but a lot of people don’t really…it just costs them a bit more head-scratching on errors.


Clojurescript compile is also something to understand, because it happens in the JVM, and unless you’re bootstrapped (which you aren’t), then read and macro-expansion happen in the compiler (which is a Closure program running on the JVM that reads clojurescript and turns it into JS). This causes a bit of confusion sometimes.


I’d read “Joy of Clojure” or “Clojure for the Brave and True”, but you don’t need that much to get started


Ok great, thanks, I have a lot of JS/React experience and I can get by with Clojure


maybe just need to read up on static protocols


there’s no such thing 🙂


defui is a macro making up syntax, so you won’t find them in a book.


just in Om Next and Fulcro


@josh_horwitz The idea is that there is a class, and there are instances. What we’d like to do is add well-known methods to the class. In Javascript you can actually do that, but in JVM you cannot. So, there is no Clojure syntax for it. So, defui invents a notation for it.


If you use static then it plugs those methods onto the component class.


If you don’t then they end up on the component instance


This allows us to do proper startup behaviors…we need to know the Idents to normalize the database before there is anything on the screen. We need to know the initial query to get data to feed the UI as well.


same with InitialAppState


But render: only needed at instance level


So, I’ve got a good start on fulcro-sql:


It has a number of features worth using already if you’re using SQL: - A database management component that can be plugged into your web server - Migration support (integration of Flyway) - Connection pooling (integration with HikariCP) - Database data seeding with abstract ID support - Integration testing (setup/teardown of database in a test) So far I’ve only plugged in support for PostgreSQL, but I’ve written it to be extensible.


My intention, as you can see in the description, is to support running a Fulcro graph query against an SQL database.


Your voice is a little quiet on that one.


volume control sufficient to correct it? It played fine for me. I did go lower on the mic, to try to pick up less background noise.


I did as much volume as I could, and do regularly use this computer for Internet TV programs and other UTube stuff. My hardware will be of lower quality than yours. Maybe the Mac people won't complain...


I'll turn the aircon off - may that is part of my problem...


Does anyone also has this error with fulcro-spec in the browser?

[  1.191s] [] Mutation fulcro-spec.selectors/set-active-selectors failed with exception Error: Vector's key for assoc must be a number.
goog.debug.Console.logToConsole_ @ console.js:203
goog.debug.Console.addLogRecord @ console.js:110
goog.debug.Logger.callPublish_ @ logger.js:725
goog.debug.Logger.doLogRecord_ @ logger.js:706
goog.debug.Logger.log @ logger.js:543
goog.debug.Logger.severe @ logger.js:594
goog.log.error @ log.js:150
fulcro.client.logging.error.cljs$core$IFn$_invoke$arity$variadic @ logging.cljc?rel=1503470998782:54
fulcro$client$logging$error @ logging.cljc?rel=1503470998782:51
(anonymous) @ om_plumbing.cljc?rel=1503471000746:62
om$next$impl$parser$parser_$_self_$_step @ parser.cljc?rel=1503470978943:280
(anonymous) @ core.cljs:5329
(anonymous) @ core.cljs:5329
cljs.core.PersistentVector.cljs$core$IReduce$_reduce$arity$3 @ core.cljs:5333
cljs.core.reduce.cljs$core$IFn$_invoke$arity$3 @ core.cljs:2502
cljs$core$reduce @ core.cljs:2470
om$next$impl$parser$parser_$_self__3 @ parser.cljc?rel=1503470978943:296
om$next$impl$parser$parser_$_self @ parser.cljc?rel=1503470978943:247
om$next$impl$parser$parser_$_self__2 @ parser.cljc?rel=1503470978943:246
om$next$impl$parser$parser_$_self @ parser.cljc?rel=1503470978943:247
om$next$transact_STAR_ @ next.cljc?rel=1503470997381:1532$core$IFn$_invoke$arity$2 @ next.cljc?rel=1503470997381:1586
om$next$transact_BANG_ @ next.cljc?rel=1503470997381:1568
fulcro_spec$router$on_route_change @ router.cljs?rel=1503471010376:60
(anonymous) @ core.cljs?rel=1503471009686:102
pushy$core$start_BANG_ @ core.cljs?rel=1503471009686:49
$stuartsierra$component$Lifecycle$start$arity$1 @ router.cljs?rel=1503471010376:73
com$stuartsierra$component$start @ component.cljc?rel=1503471009446:6
cljs.core.Var.cljs$core$IFn$_invoke$arity$1 @ core.cljs:1122
cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$3 @ core.cljs:3846
cljs.core.apply.cljs$core$IFn$_invoke$arity$3 @ core.cljs:3886
cljs$core$apply @ core.cljs:3868
com$stuartsierra$component$try_action @ component.cljc?rel=1503471009446:117
(anonymous) @ component.cljc?rel=1503471009446:139
(anonymous) @ core.cljs:1495
cljs.core.array_reduce.cljs$core$IFn$_invoke$arity$4 @ core.cljs:1495
cljs.core.IndexedSeq.cljs$core$IReduce$_reduce$arity$3 @ core.cljs:1629
cljs.core.reduce.cljs$core$IFn$_invoke$arity$3 @ core.cljs:2502
cljs$core$reduce @ core.cljs:2470
com.stuartsierra.component.update_system.cljs$core$IFn$_invoke$arity$variadic @ component.cljc?rel=1503471009446:135
com$stuartsierra$component$update_system @ component.cljc?rel=1503471009446:129
com.stuartsierra.component.start_system.cljs$core$IFn$_invoke$arity$2 @ component.cljc?rel=1503471009446:163
com$stuartsierra$component$start_system @ component.cljc?rel=1503471009446:155
com.stuartsierra.component.start_system.cljs$core$IFn$_invoke$arity$1 @ component.cljc?rel=1503471009446:161
com$stuartsierra$component$start_system @ component.cljc?rel=1503471009446:155
$stuartsierra$component$Lifecycle$start$arity$1 @ component.cljc?rel=1503471009446:178
com$stuartsierra$component$start @ component.cljc?rel=1503471009446:6
fulcro_spec.suite.test_renderer.cljs$core$IFn$_invoke$arity$variadic @ suite.cljc?rel=1503471012412:26
fulcro_spec$suite$test_renderer @ suite.cljc?rel=1503471012412:18
(anonymous) @ client_test_main.cljs?rel=1503473287518:8


@mitchelkuijpers Try the latest version


beta8 I think…don’t remember what that issue was, but it is familiar


oh, I think it was the network upgrade…yeah, that was it.


I forgot to install the push handlers, so there is a broken version of spec


So, you’re using the browser rendering for server-side tests? I was using that today working on fulcro-sql. I really like it much better than the console. The selectors in particular are super-handy.


I was using it for client-side tests but I use it for both really loving it


well, let me know if your problem persists. I think that was just on that one broken beta


otherwise your config might be wrong…but if you’ve been using it, I doubt it


I’m headed to bed, but I can wait a min for your confirmation that it is fixed if you like @mitchelkuijpers


No I'll manage, don't worry about it


Just make sure you’re using the latest versions of things, and it should work.


beta8 breaks it more, it now tries to connect to the websocket even when we try to run only the client tests


@tony.kay I was reading the docs on fulcro-sql, I wonder if the ::core/om->sql wouldn't be better as a function instead of a map, this way you can still use the map, but would also enable for custom converters


looking through the video "core concepts part 2". Is require-macros needed in that case ? thinking about


@mitchelkuijpers Did you figure it out? The fulcro project itself uses both client and server and all are passing.


@wilkerlucio what functionality would a function add? There should be a 1-to-1 correspondence between an om property name and an sql table/column.


Oh, perhaps you misunderstood…this is not a type conversion (though I should support that as well).


it is something like I want to say :person/name in the UI code, but my database calls it :member/first_name


@mitchelkuijpers You’re right that the client tries to connect to a websocket when it shouldn’t (I hadn’t noticed that), but that does not break the client tests for me.


Depending on how many versions you just skipped, you may either want to use the built-in client test html file, or update yours to match. Also, other versions of things could possibly cause a problem. The final possibility is a failing test is somehow crashing it, but it’s been a while since I’ve seen that happen (there were a number of bug fixes around that).


@mitchelkuijpers I pushed a fulcro-spec-1.0.0-beta9-SNAPSHOT that fixes the networking error message on client. It tests out as well.


@tony.kay yes, that's what I'm talking about, the name conversion, maps are a static way to handle that, but I can image dynamic ways to handle this too, for example, I might wanna say that my query field is person/created-at and on DB it might be just createdAt, or other types of conversion, functions would allow to set conventions around it


@wilkerlucio Oh, I see. so instead of having to type out the mapping, have a convention. Hm. I’m supporting sqlprop as a multimethod which is meant to sanitize keywords that you don’t map. That would be a place to put that. Right now it just converts - to _, and is dispatched on db driver. Having the schema be pure data has some advantages I’m hesitant to drop. But perhaps the dispatch for sanitation could be changed to use something else.


Awesome will try it out tomorrow


@wilkerlucio I’ll think it over. I like the idea, I’ll just have to think about how I’d best like to support it.


@claudiu Yes, the require-macros is needed. The patch you’re referring to eliminates the need to refer-macros from other namespaces, making it nice for library users.


Cool. Haven't gotten to the point of writing my own macros yet. Was really happy with that patch for .cljc files 🙂