今までは
request
オブジェクトで何かをする、と言う事を避けてきました。しかし、request
オブジェクトは避けるべきものではありません!ユーザがwebフォームに何か入力して投稿すると、ユーザのブラウザはフォームの値を保持した新しいrequest
を生成します。ここでは、ユーザが入力した値を受け取るrequest-bindings
機能を使います。request-bindings
の型は:
request-bindings : (request? . -> . bindings?)
です。
request-bindings
に加えて、名前を受け取り、その名前に関連した値を返すextract-binding/single
機能と言うものもあります。
extract-binding/single : (symbol? bindings? . -> . string?)
最後に、
exists-binging?
で束縛に名前があるかどうかチェックします。
exists-binding? : (symbol? bindings? . -> . boolean?)
これらの機能を使って、
request
を受け取り、何か役立つ事を行う機能を実装しましょう。Exercise.
bingings?
を受け取るcan-parse-post?
と言う機能を書いてみましょう。'title
と'body
と二つのシンボルに束縛されたものがあれば#t
を返し、そうじゃなければ#f
を返します。
can-parse-post? : (bindings? . -> . boolean?)
Exercise.束縛を受け取る
can-parse-post?
と言う機能を書いてみましょう。ここではでは'title
と'body
と言うシンボルに値が束縛されている構造とします。parse-post
はこれらの値を含む投稿を生成します。
parse-post : (bindings? . -> . post?)
さて、これらの補助機能を用いて、入力フォームを操れるようにwebアプリを拡張します。ページの最後に小さな入力フォームを付け加えて、新規投稿を加えられるようにプログラムを変更してみましょう。そして、startメソッドは、最初にリクエストがパース可能であるかどうか調べ、そうであるならば、投稿セットを拡大し、最終的にこれらのブログ投稿を表示するようにします。
#lang web-server/insta
; ブログは (listof post) で
; 投稿は (make-post title body)
(define-struct post (title body))
; BLOG: blog
; 静的ブログ
(define BLOG
(list (make-post "First Post" "This is my first post")
(make-post "Second Post" "This is another post")))
; start: request -> html-response
; リクエストを受け取り全てのwebコンテンツを
; 表示するページを生成する
(define (start request)
(local [(define a-blog
(cond [(can-parse-post? (request-bindings request))
(cons (parse-post (request-bindings request))
BLOG)]
[else
BLOG]))]
(render-blog-page a-blog request)))
; can-parse-post?: bindings -> boolean
; 束縛が 'title と 'body を含む値がある場合、真を返す
(define (can-parse-post? bindings)
(and (exists-binding? 'title bindings)
(exists-binding? 'body bindings)))
; parse-post: bindings -> post
; 束縛を受け取り、取り出した投稿を返す
(define (parse-post bindings)
(make-post (extract-binding/single 'title bindings)
(extract-binding/single 'body bindings)))
; render-blog-page: blog request -> html-response
; ブログをリクエストを受け取り、ブログコンテンツである
; html-response ページを生成する
(define (render-blog-page a-blog request)
`(html (head (title "My Blog"))
(body
(h1 "My Blog")
,(render-posts a-blog)
(form
(input ((name "title")))
(input ((name "body")))
(input ((type "submit")))))))
; render-post: post -> html-response
; 投稿を受け取り、html-response 要素を生成する
(define (render-post a-post)
`(div ((class "post"))
,(post-title a-post)
(p ,(post-body a-post))))
; render-posts: blog -> html-response
; ブログを受け取り、全投稿の html-response
; 要素を生成する
(define (render-posts a-blog)
`(div ((class "posts"))
,@(map render-post a-blog)))
これは動くように見えますが・・・一つ問題があります!二つの新規投稿をしてみてください。一体、何が起きるでしょうか?
0 件のコメント:
コメントを投稿