railsのプロジェクトにおけるvueを使った開発手法
今回はrailsのプロジェクトにおいてフロントにvue.jsを導入してみたことを記事にしてみました。具体的には下記のやりたいことに書いてあります。
開発環境
やりたいこと
railsでjavascriptのフレームワークなどを使用せずに開発をする場合コントローラーで作ったインスタンス変数などをerb.html
ファイルに渡すことが多いと思います。
今回は冒頭にも書きましたがvueの単一ファイルコンポーネントを使用して開発することを前提としています。そこで.vue
ファイルにrails側で作成したデータを渡す必要があります。erb.html
ファイルなら直接rubyのコードを記述することができますが、.vue
ファイルはrubyのコードを書くことができません。
そこでどうしたら上記の問題を解決できるのか悩んでいました。
結論を言いますとwindowオブジェクトにviewmodelを追加すれば良いということです。
ここでは実際にユーザー情報が書かれたユーザ一詳細ページを例に解説していきます。(※ディレクトリ構成については説明していないのでご了承ください。)
ユーザー詳細ページの例
windowオブジェクトにviewmodelを追加している部分
import { Vue, Component } from 'vue-property-decorator'; import User from "../../component/users/User.vue"; @Component({ components: { "user-profile-component": User } }) class UserProfile extends Vue { } (<any>window).UserProfile = UserProfile;
前提としてtypescriptを使用して開発をしています。今回はそのことについてはあまり触れないので詳細を知りたい方は以下のリンクを参考にしてみてください。
はじめに、表示する用のUserコンポーネントを登録しています。 その後、windowオブジェクトのプロパティとしてUserProfileクラスを登録しています。
// typescriptを使用した記述方法 (<any>window).UserProfile = UserProfile; // typescriptを使用していない場合 window.UserProfile = UserProfile
viewModelをインスタンス化している部分
<div id="userProfile"> <user-profile-component :user="user"></user-profile-component> </div> <%= javascript_include_tag "/javascripts/viewmodel/users/show" %> <script> new UserProfile({ el: "#userProfile", data: { user: <%= raw @user.to_json %> } }) </script>
ここでviewファイルである.erb.html
ファイルとvueインスタンスをバインドしています。
その中にユーザー詳細ページを表示するコンポーネントを配置してprops
にrailsからのデータを渡しています。
<user-profile-component :user="user"></user-profile-component>
<script> new UserProfile({ el: "#userProfile", data: { user: <%= raw @user.to_json %> // railsのデータをインスタンス変数のuserに代入 } }) </script>
<%= raw @user.to_json %>
このto_json
メソッドは、rubyのHashやArrayをjson形式に変換してくれています。こうすることでフロント側で受け取りやすいデータ構造になります。
to_json
を使った簡単な例
to_json
を使用すると
json形式に変換してくれましたね。
またraw
メソッドも使う必要があります。
使った場合と使わない場合の出力結果を見てみましょう。
(ここではdebuggerを仕込んだ出力結果を見ています。)
- rawメソッドを使わない場合
- rawメソッドを使った場合
ダブルクォーテーション""
が"
と変換されているのがわかります。
つまりrawメソッドを使用しない場合は、自動的にエスケープされています。
エスケープされないためにraw
メソッドを使用する必要があるのです。
railsから受け取ったデータを受け取って描画している部分
<template> <div class='user'> <div class='user_name'>{{user.name}}</div> <div class='user_email'>{{user.email}}</div> </div> </template> <script lang="ts"> import { Vue, Prop } from "vue-property-decorator"; import UserData from "../../data/user"; export default class User extends Vue { @Prop() public user: UserData; } </script>
.vue
ファイルでは親から値を取得するためにpropsを定義してあげます。
あとは目的に合わせて表示するだけです。
まとめ
vueの単一ファイルコンポーネントを使用ってrailsからvueファイルにデータ渡すことができました。今回はvueを例に紹介しましたがreactなど他のフレームワークでも上記で説明した手法で開発できると思います。 簡単ではありますが、以上になります。