Fork me on GitHub
#beginners
<
2017-03-19
>
lepistane08:03:30

@pcbalodi tnx!! i still need to learn a lot them i have no idea how you came up with destructuring thing although i saw it in use.

jennifer16:03:18

anyone available to rubber duck a POST request problem? the problem is more with the request itself than anything clojure-specific, i think. any clues are much appreciated! i’m using the reagant-template with cljs-ajax, ring/compojure. this is the request on the front end:

(POST "/list"
          {:params text
           :handler (fn [data]
                        (reset! state-atom (cljs.reader/read-string data)))
           :error-handler error-handler})))
what’s happening is that i’m making a post request, sending the params (which is a string or an object or whatever data) and then the handler gets the response back or the error handler fires. the handler works! i get a “successful” response with the updated data. the backend functions are working properly in the repl with test data, but the params don’t ever seem to get over to the backend the right way, they never get added to the new data. GET requests are working as expected. expected response: {0 {:text "first response" :complete true :id 0} 1 {:text "another response" :complete true :id 1}} but what i get back is {0 { :complete true :id 0} 1 {:complete true :id 1}} the :text part is what is sent through the params, but doesn’t seem to get to the backend.

noisesmith17:03:15

what are you doing to access the post data?

jennifer17:03:29

i made some progress since that post. was able to log out the request on the backend (which is just the handler functions and an atom as a “database”).

jennifer17:03:58

so, i think the first thing is figuring out what the content type is supposed to be. the params are definitely empty as well.

noisesmith17:03:55

for a post request, it should be in :form-params, though the wrap-params middleware will also merge it into the :params

noisesmith17:03:26

for most ring setups, you can default to form-encoded (and be sure to form encode your params) or you can set it to application/json and send a json string

jennifer17:03:04

i’m wondering if i have the middleware set up in correctly.

noisesmith18:03:21

are you sure cljs-axaj doesn't want the params under :body ?

noisesmith18:03:37

usually for post requests the payload would be in the body

noisesmith18:03:01

n/m - I found it in the docs, it accepts either

noisesmith18:03:47

@jennifer one thing that I've found helps when getting things set up, is to start with a known quantity on one side of the request - so either use the clj backend plus a curl request that is known to work on another server, or the cljs frontend, sending the request to a different server (one where you can see the data it gets, of course).

jennifer18:03:19

i did try using body as well, which seems to log out a Java object. i can post my current request if that might help.

noisesmith18:03:38

what happens if you try to do (slurp (:body request))

jennifer18:03:10

total n00b question: where would i do that?

noisesmith18:03:22

somewhere where you can access the request

noisesmith18:03:36

for example the handler

noisesmith18:03:12

the thing that gets me about that request, is it has a :content-length 21 but I don't see the decoded request body anywhere, which makes me think that if you slurped the body you might see a raw request that was 21 bytes long

jennifer18:03:39

so i should be trying to do the slurp on the backend in the POST router? or the clojurescript/frontend handler? i apologize for the super newbie questions. i’ve mostly been a front end js dev and am new to clojure/backend.

jennifer18:03:28

my usual resources are offline today. 🙂

noisesmith18:03:28

how did you print that request?

noisesmith18:03:53

that's a back end ring request object, anywhere in the clojure back end code where you can access that object you should be able to access the :body key and attempt to slurp it. For example, it looks like that request was sent to /list so you could add a line to the code of /list that slurps the body and prints it

noisesmith18:03:43

OK I find it really weird on line 3 that (request) is in parens

noisesmith18:03:15

but anyway, you could add (println (slurp (:body params)))

jennifer18:03:16

oh. i had to undo a couple times. might have missed that.

noisesmith18:03:08

list-add is written as if it was getting the params of the request as sent by the client, but it's being given the full request

noisesmith18:03:25

(but after we figure out how to get the actual params we can sort that out too)

jennifer18:03:58

yup. the original route was (list-add (:params request)) sorry. i’ve had to backtrack a couple times to post snippets. 🙂

noisesmith18:03:01

I assume you started passing in the full request for debugging purposes

noisesmith18:03:32

so yeah, that println / slurp / body might be informative

jennifer18:03:20

huh. it seems to just print an empty string.

jennifer18:03:09

i stuck a (println “yo”) before it, just to make sure something was working. that logs properly, but i get nothing from the body.

noisesmith18:03:36

OK - so something is consuming the body but you aren't seeing the data in the request

jennifer18:03:28

that sounds about right and matches what i’m seeing returned to the front end handler function.

noisesmith18:03:58

well, the front end handler function gets whatever /list returns

noisesmith18:03:30

you just happen to be returning a hash map with none of the keys that ring likes at the moment, which translates to an empty reply

noisesmith18:03:43

(swap! returns the new state of the object you swapped on)

jennifer18:03:27

am i correct in thinking that this is centered on how i’m sending data from the front end?

noisesmith18:03:32

are you explicitly using the wrap-params middleware?

noisesmith18:03:57

@jennifer - no, the first problem is that the back end isn't seeing any of the data the front end is actually sending

noisesmith18:03:09

it can't return a meaningful result until it knows the content of hte request

jennifer18:03:17

got it. okay.

noisesmith18:03:31

try commenting out line 12

noisesmith18:03:03

I think wrap-defaults already wants to get your params, if you do it twice you could end up with nothing

noisesmith18:03:32

in the future you might want to keep line 12, and replace wrap-defaults, but that's trickier since wrap-defaults does a few things

jennifer18:03:38

yeah. that was a result of me flailing around trying stuff.

noisesmith18:03:22

I think if you comment the wrap-restful-format and restart your http server, you might see something useful in the request body in the list handler (or even the form-params key in the request)

jennifer18:03:56

huh. now i’m getting a 404 error from the request.

noisesmith18:03:51

after a full restart?

jennifer18:03:50

ah! the restart. let me do that.

jennifer18:03:35

confirmed. still 404ing. it wasn’t doing that before i put line 12 in, so maybe i’m missing something else.

noisesmith18:03:07

are you using version control?

jennifer18:03:55

yup. using git. i haven’t committed in a bit because i was trying to get this working first.

noisesmith18:03:55

looking at your diff might be helpful at this point - and if you get to another stable point, that might be a good starting point for a debugging branch

jennifer18:03:19

yeah, my last stable point doesn’t have this working either. i have GET requests working fine (yay!) i’m just hung up on POST. is it possible i’m missing something with middleware or dependencies or something? i had started with reagent-template which did most of the setup for me.

noisesmith18:03:44

right, but your last stable build point doesn't 404

jennifer18:03:17

correct. so i got back there easily enough. there’s only a couple functions i’m dealing with, so i hadn’t mucked things up too badly. 🙂

jennifer19:03:22

so my build is stable again and the POST doesn’t 404.

jennifer19:03:49

one of my usual resources came on line. she might be able to give me some more insights. fingers crossed

danp20:03:17

Hi all, I'm working on 4clojure and trying to do the Fibonacci sequence task. I've got the following code...

danp20:03:09

When I run it, I get

IllegalArgumentException Don't know how to create ISeq from: cbat.core$eval1588$fn__1589  clojure.lang.RT.seqFrom (RT.java:542)

noisesmith20:03:53

@danp you can't take from a function

noisesmith20:03:03

perhaps you meant to wrap an extra set of parens so the function would be called?

noisesmith20:03:15

or you could remove the fn part altogether, the loop can stand alone

noisesmith20:03:55

the next issue is the loop is not lazy, so the take can't prevent it from being infinite

noisesmith20:03:49

it can't return its collection, because there's no codepath that can ever return the collection

danp20:03:31

yep - i see what you mean with the take

danp20:03:57

And now get an integer overflow exception

noisesmith20:03:06

because it is looping infinitely

danp20:03:13

Yep, gotcha

noisesmith20:03:14

there's no codepath that ever returns the sequence

noisesmith20:03:34

you can use lazy-seq, then take will help

noisesmith20:03:49

otherwise you can check the count of 10 in your loop, with a conditional to return the coll

danp20:03:07

This was something I couldn't quite get my head around - do i just put fib before the recur?

danp20:03:12

to return?

noisesmith20:03:34

you have two options - make a proper lazy-seq, or have a conditional to return fib

noisesmith20:03:54

the first is a more useful thing genarally in clojure, the latter is easier right now

noisesmith20:03:56

it's up to you

danp20:03:26

I was just going to say the latter sounds like I could do it, the former I can't quite think how to do right now 🙂

noisesmith20:03:58

in that case, have an if, check the size, one branch of the if calls recur, the other returns fib

danp20:03:58

That makes sense for sure - I'll look into the lazy-seq solution later

noisesmith20:03:35

if you want a more efficient version of the function, you would want to keep track of the last two items instead of reversing the list or taking the last item out, which is half of the work needed to do the lazy-seq solution properly

danp20:03:11

I did wonder how well the reverse would perform with larger sequences - I'll keep that in mind, thanks very much.

noisesmith20:03:20

last on lists is O(n), as is reverse, and you can avoid both if you keep the last two items in an extra loop binding

noisesmith20:03:40

which makes your fib O(n!) or something

danp20:03:31

I'll definitely give it a go, expect more messages of confusion later 😛

danp20:03:58

The loop counter version worked fairly easily, cheers @noisesmith !

noisesmith20:03:29

yeah, the other stuff is extra credit - you should see it in other people's solutions

jennifer21:03:02

@noisesmith thanks so much for your help before! there were some configuration things set up incorrectly and i’ve got things working now. 😄

danp21:03:26

Hey @noisesmith, I've got the lazy version working now. Admittedly, I stumbled on a Fibonacci-specific example when I was looking at: https://clojuredocs.org/clojure.core/lazy-seq

noisesmith21:03:25

heh, it is the classic after all

danp21:03:29

But I managed to do it without referencing back to the example. Just wondering though, how comes this works?

danp21:03:55

But this doesn't:

noisesmith21:03:12

a lazy-seq acts like a sequence, but the rest of the sequence is actually a function

danp21:03:23

Mainly I ask because concat's doc says it returns a lazy sequence

noisesmith21:03:48

concat only accepts collections

noisesmith21:03:01

l1 is not a collection

noisesmith21:03:34

and once you have to create the collection, lazy-seq is a more natural answer in comparison (but [l1] as the first arg to concat should work too)

danp21:03:08

ah ok - makes sense. I get an integer overflow if I add [l1]

noisesmith21:03:53

odd, somehow not lazy enough I guess

danp21:03:30

I definitely understand the solution with cons though, which is progress 🙂

danp21:03:14

Think I'll call it a night now anyway and pick up 4clojure in the morning. Thanks again for your help