RailsでJavascriptをControllerから送る方法

jQueryとかRailsの基本的な部分の説明を割愛して書くので「???」な方はごめんなさい。

Railsでは「public/javascripts」の下にjavascriptを配置し、javascript_include_tagを使ってscriptタグを生成させて使うのが普通な使い方だと思う。この場合、「public」の下のファイルは静的なファイルとして、Railsとしては何も処理せず内容を配信してくれる。

さて、そこで。

たまーにjavascript内にURLを書きたい時がある。この「URL」が静的なファイル、つまり「public」の下にあるファイルが持つURLであれば特に問題はないのだが動的なファイル、つまり内容が変わるとすると、ちょっと面倒なことになる。

状況としてはこんな感じ。(以下の「静的」は「ファイルの中身が変更にならない」という意味。)

ケース1: HTML => JS1(静的)
ケース2: HTML => JS2(動的)

ケース1の場合は、JS1を「public/javascripts」の下に配置してあげれば問題ない。HTMLがクライアントに送られjavascript_include_tagを使って生成されたJS1用のScriptタグが送られるので無事Javascriptはロードされるだろう。

問題はケース2のとき。JS2のscriptの内容を動的に変化させたいとする。そうなると、JS2は「public/javascripts」の下には置けない。何らかのcontrollerのactionとして実装されることになるだろう。
こんな時どうすればいいのか。


これと似たようなケースは意外とあるのではないのだろうか。
以前、CSSでも同じ気分になったことがある。例えば、背景画像などのパスをCSSに書きたい場合。画像ファイルが「public/images」の下に置かれるのであれば問題はないが、動的に背景を変えたいなどの場合にも同じ悩みを持つことになる。

ということで、やり方。
今回はchat.jsというファイルをhome_controllerから送り返したいとする。

1,route.rbの調整

get 'home/chat'


2,application.html.erbの調整

<%= javascript_include_tag url_for({:controller => :home, :action => :chat}) %>


3,home_controller.rbの準備

class HomeController < ApplicationController
  def chat
    respond_to do |format|
      format.html {render :layout => false} # chat.html.erb
      format.js   {render :layout => false} # chat.js.erb
    end
  end
end

以上。

ポイントとしては
1,javascript_include_tagでは、指定されたパス+".js"というURLをsrc属性に設定してくれるのでurl_forを使う。
2,拡張子の違いでテンプレートを変えられるところを使う。scaffoldで生成した時に見られるもの。なお、例えばhtmlには見た目を、jsには動作部分とわけて書くという使い方もできる。そうすると、同じディレクトリに見た目とScriptが保存されるのでメンテナンスしやすそう。
3,chat.js.erbは普通にerbが使えるので、ご自由に。お好きに。
という感じ。

RJS使えばいいじゃんとか、可変部分はViewに入れておいて不変なところはjavascriptの静的なファイルとして実装すればいいじゃんとか、突っ込みどころ満載な方法。
でも、手を抜きたい時ってあるでしょ。とりあえず、貰ってきたソースをそのまま使ってしまって、ちょっとだけ変更すりゃいいやとか。
そういうときに使える小技ということで。こんな大したことないのを今まで思い付かなかったのが残念で仕方がない。今日はやけ酒ですね。