コメント機能
前回は投稿とユーザーの紐付けを行ったので、今回は投稿に対して一般のユーザーがコメントをできる機能を作っていきます。
流れとしてはこんな感じです。
・commentテーブルの作成&外部キーの追加
・entityとschemaの作成
・全ての投稿一覧が見れるページを作成
・各投稿が閲覧でき、かつコメントするページ
・routesファイルの設定
・controllersファイルの設定
では早速作っていきましょう。
Post Entity
case class Post( @Column("post_id") id: Long, @Column("title") title: String, @Column("content") content: String, @Column("user_id") userId: Int ) extends KeyedEntity[Long] { }
User Entity
case class User( @Column("user_id") id: Long, @Column("user_name") userName: Option[String], @Column("mail_address") mailAddress: Option[String] ) extends KeyedEntity[Long] { }
・commentテーブルの作成&外部キーの追加
ここではuser_idはuserテーブルのuser_idに、post_idはpostテーブルのpost_idにリレーションさせています。
create table comment ( comment_id integer primary key, comment text, post_id integer REFERENCES post(post_id) );
・entityとschemaの作成
//entityの作成 case class Comment( @Column("comment_id") id: Int, @Column("comment") comment: Option[String], @Column("post_id") postId: Int ) extends KeyedEntity[Int] { } object AppDB extends Schema { ...省略... //schemaの作成 val commentTable = table[Comment]("comment") }
・全ての投稿一覧が見れるページを作成
まずはviewから
//allposts.scala.html @(posts: List[(db.Post, db.User)]) <ul> @for( (post, user) <- posts ){ <li>title: @post.title <br/>content: @post.content <br/>author: @user.userName <p> <a href="@routes.Application.entry(post.id)">view comments</a> </p> </li> } </ul>
・各投稿が閲覧でき、かつコメントするページ
今回コメントは各投稿閲覧時のページからできるようにします。
@(post: db.Post, comments: List[db.Comment], form: play.api.data.Form[db.Comment]) <h2>@post.title</h2> <p>@post.content</p> <ul> <li> @for( comment <- comments){ <p>Viewer's Comment: @comment.comment</p> </li> } </ul> @helper.form(action = routes.Application.addComment) { <input type="hidden" name="post_id" value="@post.id"/> @helper.inputText(form("comment")) <input type="submit"/> }
・routesファイルの設定
今度はroutesの設定を行っていきます。
ここでも今までと比べてあまり変わったことはしていないので、細かい説明は省きます。
//全ての投稿を表示 GET / @controllers.Application.index //各投稿を表示 GET /entry/:id @controllers.Application.entry(id: Long) //commentフォームのデータの送信先として POST /addComment @controllers.Application.addComment
・controllersファイルの設定
前回は投稿とユーザーの紐付けを行ったので、今回は投稿に対して一般のユーザーがコメントをできる機能を作っていきます。 流れとしてはこんな感じです。 ・commentテーブルの作成&外部キーの追加 ・entityとschemaの作成 ・全ての投稿一覧が見れるページを作成 ・各投稿が閲覧でき、かつコメントするページ ・routesファイルの設定 ・controllersファイルの設定 では早速作っていきましょう。 Post Entity >|scala| case class Post( @Column("post_id") id: Long, @Column("title") title: String, @Column("content") content: String, @Column("user_id") userId: Int ) extends KeyedEntity[Long] { }
User Entity
case class User( @Column("user_id") id: Long, @Column("user_name") userName: Option[String], @Column("mail_address") mailAddress: Option[String] ) extends KeyedEntity[Long] { }
・commentテーブルの作成&外部キーの追加
ここではuser_idはuserテーブルのuser_idに、post_idはpostテーブルのpost_idにリレーションさせています。
create table comment ( comment_id integer primary key, comment text, post_id integer REFERENCES post(post_id) );
・entityとschemaの作成
//entityの作成 case class Comment( @Column("comment_id") id: Int, @Column("comment") comment: Option[String], @Column("post_id") postId: Int ) extends KeyedEntity[Int] { } object AppDB extends Schema { ...省略... //schemaの作成 val commentTable = table[Comment]("comment") }
・全ての投稿一覧が見れるページを作成
まずはviewから
//allposts.scala.html @(posts: List[(db.Post, db.User)]) <ul> @for( (post, user) <- posts ){ <li>title: @post.title <br/>content: @post.content <br/>author: @user.userName <p> <a href="@routes.Application.entry(post.id)">view comments</a> </p> </li> } </ul>
・各投稿が閲覧でき、かつコメントするページ
今回コメントは各投稿閲覧時のページからできるようにします。
@(post: db.Post, comments: List[db.Comment], form: play.api.data.Form[db.Comment]) <h2>@post.title</h2> <p>@post.content</p> <ul> <li> @for( comment <- comments){ <p>Viewer's Comment: @comment.comment</p> </li> } </ul> @helper.form(action = routes.Application.addComment) { <input type="hidden" name="post_id" value="@post.id"/> @helper.inputText(form("comment")) <input type="submit"/> }
・routesファイルの設定
今度はroutesの設定を行っていきます。
ここでも今までと比べてあまり変わったことはしていないので、細かい説明は省きます。
//全ての投稿を表示 GET / @controllers.Application.index //各投稿を表示 GET /entry/:id @controllers.Application.entry(id: Long) //commentフォームのデータの送信先として POST /addComment @controllers.Application.addComment
・controllersファイルの設定
package controllers import models.UserData import play.api.mvc._ import play.api.data._ import org.squeryl.PrimitiveTypeMode._ import db._ import play.api.data.Forms._ import securesocial.core._ class Application(override implicit val env: RuntimeEnvironment[UserData]) extends Controller with securesocial.core.SecureSocial[UserData] { //コメントのフォームの定義 val commentForm = Form( mapping( "comment_id" -> ignored(0), "comment" -> optional(text), "post_id" -> number )(Comment.apply)(Comment.unapply) ) def index = Action { implicit request => transaction { val posts = from(AppDB.postTable, AppDB.userTable)((p, u) => select(p, u)).toList Ok(views.html.allpost(posts)) } } def entry(id: Long) = Action { implicit request => transaction { val comments = from(AppDB.commentTable)((c) => where(c.postId === id) select(c)).toList from(AppDB.postTable)((p) => where(p.id === id) select(p)).headOption.map { postContent => Ok(views.html.entry(postContent, comments, commentForm)) }.getOrElse { NotFound("404 Page not found") } } } def addComment = Action { implicit request => transaction { commentForm.bindFromRequest.fold( errors => { BadRequest }, comment => { inTransaction(AppDB.commentTable.insert(comment)) Redirect(routes.Application.entry(comment.postId)) } ) } } }
簡単に各Actionでどのようなことをしているかを説明していきます。
indexでは、ユーザー関わらず全ての投稿を表示させています。
entryでは該当のpost_idがない場合、404ページを表示するしています。
今回は簡易的に「404 Page not found」の文字のみ表示させています。
addCommentではフォームの内容が正しく受け取れた場合、DBにその内容を反映させた後該当の投稿ページにリダイレクトさせています。
これでcompileしてerrorが表示されなければ、runコマンドのあとページが正しく表示されることを確認しましょう。
viewで正しい表示が確認できたら、次はコメントフォームからコメントしてcommentテーブルに入力したデータが正しく反映されていることを確認しましょう。
これでコメント機能の完成です。
次回は全投稿閲覧ページにページング機能を作成していきたいと思います。