ユーザーと投稿の紐付け

前回でユーザー登録できるようになりましたので、今回はユーザーと投稿の紐付けを行っていきます。
流れとしてはこんな感じで作っていきます。

・投稿画面の作成(post.scala.htmlファイルの作成)
・routesの設定
・controllersで投稿ページのpostアクションとデータの送信先としてのaddPostを作成
・ログインユーザーの自身の投稿のみを閲覧できるページ作成

ちなみに現在の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] {
    }

schema設定は前回のentity定義の際に行いましたので、変更点はありません。

val postTable = table[Post]("post")

・投稿画面の作成(post.scala.htmlファイルの作成)

では最初に投稿画面の作成(post.scala.html)をしていきたいと思います。
ユーザーIDはユーザーが直接変更するものではないため、type="hidden"で渡しています。

@(form: play.api.data.Form[db.Post], userData: UserData)

@helper.form(action = routes.AdminController.addPost) {
//hiddenに対応したhelperはないためHTML形式で
<input type="hidden" name="user_id" value="@userData.id" />
@helper.inputText(form("title"))
@helper.inputText(form("content"))
<input type="submit"/>
}

・routesの設定

次にroutesファイルの設定ですが、今回は投稿画面とユーザーが入力したデータの送信先が必要です。なので下記のように記述します。

//投稿画面用
GET     /admin/post                      @controllers.AdminController.post

入力データの送信先
POST    /admin/addPost                   @controllers.AdminController.addPost

・controllersの設定(投稿ページのpostとデータの送信先としてaddPostを作成)

controllersではpostとaddPostの作成を行っていきます。

  //postページでは、user_idを参照できるようにユーザー情報を渡します
  def post = SecuredAction { implicit request =>
    Ok(views.html.post(postForm, request.user))
  }
  //投稿はログインユーザーのみ可能なためSecuredActionつける
  def addPost = SecuredAction { implicit request =>
    postForm.bindFromRequest.fold(
      errors => {
          BadRequest
      },
      //postページで受け取った情報をDBに反映する
      post => {
        inTransaction(if(request.user.id == post.userId) AppDB.postTable.insert(post))
        Redirect(routes.AdminController.index())
      }
    )
  }

これで投稿時にuser_idとpost_idが紐付けられるので、特定のユーザーの投稿のみの表示ができるようになりました。

・ログインユーザーの自身の投稿のみを閲覧できるページ作成

仕上げにログインユーザーが自分の投稿のみ閲覧できるページを作成します。

controllersの設定

  def index = SecuredAction { implicit request =>
    transaction {
      //ページを閲覧しているユーザーのidをwhereで指定
      val posts = from(AppDB.postTable)(p => where(p.userId === request.user.id) select (p)).toList
      Ok(views.html.index(posts, request.user))
    }
  }

ユーザー自身の投稿を閲覧するためのページ
ここはあまり変更点ないため説明は飛ばします。

@(posts: List[db.Post], userData: UserData)

<p>@userData.userName</p>
■<a href="@routes.AdminController.post">Post</a>
<ul>
    @for( post <- posts ){
    <li>@post.title, @post.content
        <p>
            ■<a href="@routes.AdminController.deletePost(post.id)">Delete</a>
            ■<a href="@routes.AdminController.update(post.id)">Update</a>
        </p>
    </li>
    }
</ul>

routesファイルでも変更点はありません。
これでユーザーと投稿の紐付け、特定のユーザーと紐付けられた投稿の表示までできました。
今回作ったものはよくあるwebサービスのマイページのユーザー自身の投稿ページと思ってもらえたらイメージしやすいかと。
次回は一般のユーザーが投稿を閲覧できて、かつコメントできるページを作成していきます。