LoginSignup
0
1

More than 5 years have passed since last update.

Railsのビューで、マスター供給用のJavaScriptを生成する

Posted at

Webシステムを作っていると、データベースにマスターを入れることもありますが、それをJavaScript側にどのように引き渡すかも、悩ましいものです。

なお、ここでは「管理画面からならマスターは更新できる」というものではなく、「デプロイ時にシードするだけで、Railsから変更することはない」ようなマスターについて考えます。

いくつかの手法

このようなことをしたい場合にも、いくつか方法が考えられます。

JSON APIを用意する

いちばん素直に考えれば、APIを叩いてJSONを返すようにすることでも値の受け渡しは可能です。

  • メリット…サーバサイドはシンプルに実装できる
  • デメリット…同期的な取得ができない、使うJavaScriptのコードが煩雑になる

JavaScriptに書き出す

Sprocketsやrails-erb-loaderなどはRails環境で.js.erbを実行できますので、事前に必要な値を書き出したJavaScriptを生成しておく、という手段もあります。

  • メリット…事前にJavaScriptにまでしておくため、実行時の負担は少ない(Turbolinksにも載せられる)
  • デメリット…デプロイ環境にもDBの準備が必要になる、rails-erb-loaderが別プロセスの呼び出しになるなどデプロイ処理が複雑化する

ビューに書き出す

ビューに適当な方法で値を埋め込んで、それを読み取って使う、という方法もあります。

  • メリット…ふつうのビューとJavaScriptだけで、別に処理を用意する必要がない、値は動的に生成するけど同期的な取得も可能
  • デメリット…使うページごとに値を書き出していくと、ビューが肥大化する

JavaScriptを返すビューを用意する

今回は、この方法について取り上げます。

  • メリット…Railsで制御するので自由度が高い
  • デメリット…自由度が高い分、正しく作るのが難しい

JavaScriptのビュー

Railsのビューはフォーマットごとに用意できるので、適切なコントローラーのshowアクションに対応するようにshow.js.erbを作ればいい…とも思えるのですが、そのままではActionController::InvalidCrossOriginRequestとなってしまいます。

CSRF対策→止める

JSONPなどにも使われている技ですが、<script>に書かれたsrcのURLは、クロスオリジンであっても読み込み、実行が可能となっています。そのため、<script>として実行されうる、GETリクエストに対してJavaScriptを返すアクションは、protrect_from_forgeryが有効な場合、ActionController::InvalidCrossOriginRequestを起こすようになっています。

とはいえ、今回のようなマスター系を前提とした場合、CSRFは問題となりません。protrect_from_forgery except: :showのように上書きして、CSRF対策自体を止めましょう。

キャッシュの活用

そのままやっていては、毎回毎回データベースを読んでJavaScriptとして吐き出すことになって、効率が悪すぎます。

  • ビューレベルのキャッシュ→<%= cache do %>...<% end %>を活用して、出来上がったビューをキャッシュしておきましょう。
  • ブラウザキャッシュ→コントローラーでexpires_inをかけると、キャッシュヘッダの調節ができます。マスター更新時のキャッシュ無効化のために、適当なキーを指定しておいてもいいかも知れません。
  • Turbolinks→ビューとして生成したJavaScriptにも、Turbolinksは問題なく適用できます。data-turbolinks-track="reload"(Turbolinks 5の場合)を設定しておきましょう。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1