rails+vueの開発環境でフォームのpost通信を行う方法

今回もvue+railsのプロジェクトにおいて自分が実際にハマった?体験を記事にしていきます。

開発環境

  • vue:2.3.4
  • typescript:2.2.2
  • ruby2.4.2
  • rails5.2.0

やりたいこと

railsで新規投稿ページや編集ページを作成する場合、よく利用される方法として標準で用意されれいるform_forform_tagなどがあります。 タイトルにもあるように今回実現したいこととしては、.vueの単一ファイルコンポーネントを使用してformの送信をしたいです。

.erbファイルの中ではform_tagを使用できますが、.vueファイルでは使用することができません。

rails4から標準でCSRFへの対応をしてくれています。 そのためform_tagなどのヘルパーメソッドが実行された時に下記のようにauthenticity_tokenが埋め込まれます。

<input name="authenticity_token" type="hidden" value="4aEXK2Ztfe+8fUEz5QrRYw6oETI1OWL0Lkg+EQyz81TixmxF1x7niphP2ROHngj0AY2iu3lZwTfbd4y2Tf93oA==">

今回はrailsが用意てくれているformのヘルパーメソッドは使用しないのでvue側で用意してあげなければいけません。

vueとrailsの連携についての記事はこちらを参考にしてみてください。

top-men.hatenablog.com

解決方法

railsではトークンを作成してくれるform_authenticity_tokenというメソッドがあるみたいです。それを今回は利用します。

新規作成ページを例にします。

rails側のファイル

<div class="postNew">
  <new-component :post="post" :token="authenticationToken"></new-component>
</div>

<script>
new PostNew({
  el: '.postNew',
  data:{
    post: <%= raw @post.to_json %>,
    authenticationToken: '<%= form_authenticity_token %>'
  }
})
</script>

上のコードではvueモデルのdataに投稿データとトークンを渡しています。

vuemodelを定義しているファイル

下記はvue-class-componentを使用しています。

github.com

import { Vue, Component } from 'vue-property-decorator';
import New from "../../component/post/new.vue";

@Component({
  components: {
    "new-component": New
  }
})
export default class PostNew extends Vue {

}

(<any>window).PostNew = PostNew;

新規登録ページ用の単一ファイルコンポーネントを登録し、windowのプロパティにクラスを追加しています。

vueファイル

<template>
  <div class='wrapper'>
    <form action='/posts' method="post">
      <input
        name="authenticity_token"
        type="hidden"
        :value="token">
      <!--省略-->
    </form>
   </div>
</template>

<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator";
import Post from "../data/post";

export default class New extends Vue {
  @Prop() public post: Post;

  @Prop() public token: string;
}
</script>

<style>

</style>

ここで大切なのはpropで受け取った値をinputタグのvalueにいれている箇所です。 こうすることでformにトークンを埋め込むことができました。 ブラウザで表示した結果です。

f:id:top_men:20180701214310p:plain

この処理を記述する前は、postした時にInvalidAuthenticityTokenと下記のエラーが表示されていました。

f:id:top_men:20180701215231p:plain

ですが、上記の処理をすることで埋め込まれたトークンが正しく認証されました!!

まとめ

rails側からvue側へどのようなものを渡してあげるべきかを上手にやってあげればなんとかうまくできるといった感じです。(ざっくりですみません) 今後もvueとrailsで詰まったことやこれは便利だと思ったことを記事にいていきます。