Fork me on GitHub
#beginners
<
2019-05-18
>
k.i.o04:05:31

whats the difference between map-indexed and keep-indexed?

seancorfield04:05:35

map-indexed keeps all the items and processes them, keep-indexed with drop items that produce nil from the predicate (updated to be accurate about nil vs false).

k.i.o04:05:14

right, thanks

seancorfield04:05:39

user=> (map-indexed (fn [i x] (when (< i x) x)) (repeat 10 5))
(5 5 5 5 5 nil nil nil nil nil)
user=> (keep-indexed (fn [i x] (when (< i x) x)) (repeat 10 5))
(5 5 5 5 5)
user=>    

sova04:05:42

i'm trying to parse a POST request on an app that i did not start as a lein new compojure myapp

sova04:05:00

i've gotten as far as (POST "/notify-by-email-please" {body :body} (slurp body))

sova04:05:26

which outputs a string like email=&zip=12345

sova04:05:49

not bad, but i don't know how to parse raw text. the normal compojure destructuring tells me it's a byteStream

sova04:05:06

doesn't really notice my param names... guessing i don't have the right middleware

sova04:05:24

i'm trying to use HTTP kit instead of ring ...

seancorfield04:05:50

@sova what is the body of the POST request? JSON? Encoded form parameters?

seancorfield04:05:30

There's probably a middleware out there that does what you want, turning that data into a hash map.

sova04:05:31

I'm using a simple HTML form with method=POST

sova04:05:52

it's just a landing page with a "submit your email for when this product launches"

sova04:05:18

and thanks sean, always most helpful to all.

seancorfield04:05:01

I always use the ring-defaults middleware stack for apps -- it takes care of so much basic stuff.

seancorfield04:05:18

For simple stuff, I generally disable the CSRF token stuff...

seancorfield04:05:52

Take a look at https://github.com/seancorfield/usermanager-example/blob/master/src/usermanager/main.clj as a basic setup. Pretty sure that would solve your problem: form POSTs become hash map elements in :params in the Ring request.

sova05:05:57

so theoretically i could pull them straight out of the params key

sova05:05:50

the middleware just makes that more palatable?

seancorfield05:05:54

That little app does POSTs of form data and deals with it as hash maps.

seancorfield05:05:28

Yup. Ring gets its power from middleware -- and you really need that "default" stack to make your like easier.

sova05:05:45

Ah, so even something like compojure destructuring depends on having the right middleware there

seancorfield05:05:46

Well, Compojure will do the destructuring -- but, as you've seen, that only gets you so far.

sova05:05:26

:body #object[org.httpkit.BytesInputStream 0x77a2b38d BytesInputStream[len=17]]

seancorfield05:05:27

Well... that is the body ๐Ÿ™‚

seancorfield05:05:50

It's not a very helpful body, but it is consumable ๐Ÿ™‚

seancorfield05:05:09

Middleware will turn that into a hash map for you.

sova05:05:17

I see. that's exactly what I want

seancorfield05:05:54

I think we use ring-defaults in all our web apps, even our simple REST APIs.

sova05:05:08

i'm using server/run-server (http-kit)

seancorfield05:05:39

Yeah, our apps all run on either Jetty or http-kit -- per that usermanager example: you can choose which server to start with at runtime.

seancorfield05:05:09

We generally use Jetty because New Relic is more compatible with it for monitoring/metric reporting purposes.

sova05:05:26

What's New Relic?

seancorfield05:05:35

But we initially used http-kit because we were having some threading issues with Jetty on an older version.

seancorfield05:05:43

New Relic is an application monitoring service.

sova05:05:58

okay, now i got the middleware in there correctly, invalid anti forgery

seancorfield05:05:36

https://newrelic.com/ we use it heavily to monitor performance in production.

sova05:05:46

you were saying it's probably fine to ignore the anti forgery / CSRF...

sova05:05:22

new relic looks neat

seancorfield05:05:26

Yeah, just disable that, like the example does.

seancorfield05:05:35

We've been using New Relic for years. Love it!

seancorfield05:05:50

Not cheap, but awesome if you have critical production services.

seancorfield05:05:39

It shows timings for all your app routes, it shows all your database activity in each request... it can provide alarms for pretty much any conditions, and send alerts to email and Slack etc.

sova05:05:01

woo the params show up in the request now

sova05:05:02

thanks man

seancorfield05:05:20

Also can do front end performance analysis -- browser stuff like network and rendering and DOM times.

seancorfield05:05:04

So, are you building a cool, secret, soon-to-be-launched product with Clojure/Script @sova?

sova05:05:08

it's just a "sign up to be notified" page for now ๐Ÿ˜ƒ

sova06:05:46

Can't say it will be "soon" launched, but the basic framework is coming along.

sova06:05:53

thanks very much sean

seancorfield20:05:57

@sova Signed up. Looks interesting. Good luck!

kari.marttila20:05:01

I downloaded the example code in https://pragprog.com/book/shcloj3/programming-clojure-third-edition . There was a very minimal deps.edn:

{
 :deps
          {org.clojure/clojure    {:mvn/version "1.9.0"}
           org.clojure/test.check {:mvn/version "0.9.0"}
           }
}
I added path for src and alias for test runner:
:test-runner {:extra-paths ["test"]
                         :extra-deps  {com.cognitect/test-runner {:git/url ""
                                                                  :sha     "209b64504cb3bd3b99ecfec7937b358a879f55c1"}}
                         :main-opts   ["-m" "cognitect.test-runner"]}
But when trying to run the tests nothing is found:
clj -Atest-runner
Running tests in #{"test"}
Testing user
Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
What am I missing here?

seancorfield20:05:45

Where are your tests?

kari.marttila20:05:08

The tests are in directory "test".

seancorfield20:05:22

I'm trying to remember whether the test runner expects your test files to have test in the namespace name...

seancorfield20:05:49

Let me just try to repro...

kari.marttila20:05:28

Maybe I'm just too tired, it's already midnight here in Finland. ๐Ÿ™‚

seancorfield20:05:26

Oh, you don't have the -d option

alexmiller20:05:30

I would help but I actually don't have a copy of the original repo or creds to get it on this machine

seancorfield20:05:44

:main-opts need to include "-d" "test"

alexmiller20:05:05

iirc we had a script to run all the tests (the book vastly pre-dated deps.edn)

kari.marttila20:05:31

Ok. I was just wondering since the same alias I used above worked with my personal project.

kari.marttila20:05:53

I try to add the ยด-dยด option...

alexmiller20:05:27

-d default is test

kari.marttila20:05:30

Nope. didn't work. Well, I think I try to continue tomorrow.

alexmiller20:05:32

but -r prob needs to be set

alexmiller20:05:37

Regex for namespaces to test. Defaults to #".*-test$" (i.e, only namespaces ending in '-test' are evaluated)

alexmiller20:05:56

so -r ".*" maybe?

seancorfield20:05:29

Ah, so it is the namespace suffix... that was going to be my next suggestion ๐Ÿ™‚

seancorfield20:05:55

I didn't realize -d defaulted to "test" -- good to know.

kari.marttila21:05:34

That might be the reason since in my personal project all test namespaces are ending with "test", e.g. domain_test.clj.

seancorfield21:05:07

Yup, that's the standard convention.

seancorfield21:05:22

foo.bar for the source code, foo.bar-test for the test code.

kari.marttila21:05:46

But -r "*" didn't work either.

alexmiller21:05:58

it's a regex

kari.marttila21:05:06

I'll try to change one test namespace ending with "test"...

seancorfield21:05:38

clj -A:test-runner -r ".*" should work (as a test from the command-line)

seancorfield21:05:47

(I just tried that locally)

kari.marttila21:05:36

Yep. That's the reason. Now it ran tests for the file I renamed from "chat.clj" to "chat-test.clj".

kari.marttila21:05:20

Yep. Now test-runner is running the tests. Thanks!

seancorfield21:05:49

If you use clj-new to create a new project, it creates an appropriately named test file.

seancorfield21:05:34

And the default deps.edn file in a new clj-new-created project is

{:paths ["resources" "src"]
 :deps {org.clojure/clojure {:mvn/version "RELEASE"}}
 :aliases
 {:test {:extra-paths ["test"]
         :extra-deps {org.clojure/test.check {:mvn/version "RELEASE"}}}
  :runner
  {:extra-deps {com.cognitect/test-runner
                {:git/url ""
                 :sha "76568540e7f40268ad2b646110f237a60295fa3c"}}
   :main-opts ["-m" "cognitect.test-runner"
               "-d" "test"]}}}

seancorfield21:05:54

Saves quite a bit of typing.

kari.marttila21:05:58

In those examples I had to comment the tasklist example - there were some genclass stuff that broke the tests. After commenting that ns the test runner ran all tests. Got to go to sleep now. Kari continues Clojure studies again tomorrow. BTW - Programming Clojure, 3rd ed is excellent. I started to read it again maybe, 3rd or 4th time now. I have noticed that some books need to be read several times before they are assimilated into the existing clojure knowledge in my head.

seancorfield21:05:19

Ah, right, you're working from a book whose code predates deps.edn... sounds like you're making good progress tho'! Good work!

alexmiller21:05:30

nope, 3rd ed has deps.edn in it

alexmiller21:05:08

last minute switch before publication - just barely made it

kari.marttila21:05:58

This time I thought that I also experiment with the book code examples. I really want to be more fluent with Clojure. And more idiomatic.