Rails5でコントローラー別に実行するJavaScriptを分ける

Railsでコントローラー毎に実行するJavaScriptを分けたいときの対応方法です。

対応方法としては、

  1. コントローラー毎にファイルを作り読み込む
  2. ファイルは1つにしてコントローラー毎に実行するJavascriptを分ける

という方法があるかと思います。

1の方法でも良いのですが、Turbolinksを使うのであればファイルを分けるのは望ましくないので2の方法で実装します。

1. HTMLにコントローラー名を設定

JavaScriptからコントローラーを取得するために、HTMLのカスタムデータ属性を使いコントローラー名を設定します。 bodyタグでカスタムデータ属性を使っていますが、ほかの方法でも問題ありません。

Slimでカスタムデータ属性を設定する場合。

body data-controller="#{params[:controller]}"

2. コントローラー名を取得する

HTMLからコントローラー名を取得します。

var controller = $('body').data('controller');

JavaScriptの量が少なく、とにかくシンプルにコントローラー毎に処理を分けたいという場合は、以下のように単純な分岐でも良いかもしれません。

if ( controller == "コントローラー名") {
  //コントローラー別の処理
}

3. 初期化処理をする

しかし、これでは分岐が増えると大変なことになるので、以下のような初期化処理をつくります。 コントローラー名と同じコンストラクタをインスタンス化して実行するという非常にシンプルなものです。

$(document).on('turbolinks:load', function(){
  var controller = $('body').data('controller');
  if (window[controller]) {
    new window[controller];
  }
});

JavaScriptの場合は、以下のようにコントローラー別にコンストラクタをつくります。

var user = function() {
  console.log("userコントローラーで実行されます");
}

CoffeeScriptを使う場合は、以下のようにコンストラクタの名前に@を付けて外部から参照できるようにしてください。

@user = ->
    console.log("userコントローラーで実行されます")

コントローラー名と同じコンストラクタを作ればインスタンス化して実行するようになります。これで完了です。

[おまけ] RailsScriptを使う

RailsScriptというGemを使うことでも可能です。

RailsScriptも内部の実装は、上記の方法とほぼ同じようなものです。

しかし、使い方が悪かったのか、Turbolinksとあわせると画面遷移したときにJavaScriptが実行されなかったので採用していません。

Gemfileにgem 'rails_script', '~> 2.0'を追加をしてインストール。

bundle install
bundle exec rails g rails_script:install
Running via Spring preloader in process 3112
      create  app/assets/javascripts/base.coffee
      create  app/assets/javascripts/global.coffee
      append  app/assets/javascripts/application.js

layout/application.html.slimnclude_rails_scriptを追加

application.jsに設定を追加。

//= require rails_script
//= require_tree .

こんな感じで使えます。

class App.Users extends App.Base

   show: =>
      console.log 'users#show'

参考