2014jQuery,Ajax,CoffeeScript覚えること多過ぎ先物・オプションのシミュレーションサイトのポジション編集画面で、チェックボックスをクリックすることでグラフのタイプを切り替える処理(データ更新後リダイレクトしている)をしているのですが、これをAjaxで実現しようとしたところ思わぬエラーに遭遇したので、新規サンプルプロジェクトを作って改めて動作を確認することにしました。sあと、turbolinksを有効にしているとAjaxの動作状況が分かりにくいのでこのサイトを参考にしてturbolinksを無効にしました。trueを追加してcontrollerをすこし弄ってupdate.js.erbを新規作成しただけですが、フォームのボタンをクリックするとAjax通信でデータの更新処理が完了し、コントローラから渡された文字列をビューに表示出来ます。フレームワークが用意してくれた仕組みを素直に使えば非常に簡単にAjax更新処理が実現できました。%>と書き換えて、チェックボックスをクリックするとInvalidAuthenticityTokenエラーが出ました。javascriptでsubmitしてしまうとcsrf-tokenが送られないということでしょう。missingエラー。%>書き換えて、再度チェックボックスをクリックすると、ブラウザにupdate.js.erbファイルの中身が文字として表示されました。ここまで来てもすぐには自分の間違いに気が付きませんでした。上でも自分で書いているけど、javascriptで普通にsubmitしているのだからAjax通信出来ていないようです。書くことでフォームがAjax用になっているからform.submit()でAjax通信が出来るような錯覚をしていました。Railsがどういう仕組みでAjaxを実現しているのかよくわかってませんが、Railsで予定していない使い方であることは確かなようです。form.submit()ではダメだとわかったので次のようにcheckboxのonchange=のイベントを削除して、jQueryでイベントを登録してそのイベント内でAjax通信するようにしました。Ajax送信後のCallback処理もそこに記述したのでjs.erbは使いません。@statusとすれば.doneイベント(コールバック関数)のdata引数に@statusの内容が入って来るので。$('#status').html(data);として画面に表示します。これで一応UnobtrusiveなJavascriptというかHTMLとスクリプトの分離が出来たのは目出度いことです。それと、先ほどエラー回避のためにフォーム内のPATHを変更しましたが、_form.html.erbはupdateのときだけでなくcreateのときも使用しているので元に戻しておきます。すればチェックボックスでの更新処理はあくまで追加の機能として作成できます。@statusこれで一応checkboxのクリック時は動くのですが、render部分を変更したために更新ボタンをクリックした場合に何も表示されません。はじめはcheckboxイベント用の別メソッドをコントローラに追加したのですが、更新処理自体は同じものなので既存のupdateメソッドをそのまま使って表示の際に分岐するようにします。それからテンプレートとjavascriptは分けておこうと思ってjavascript部分をapp/asset/javascript/ディレクトリに別ファイル(chkbox.js)として移動したのですが、ajax呼び出し時のurl:パラメータが上手く展開されませんでした。拡張子に「erb」を追加すればRailsがちゃんと展開してくれるとどこかに書かれていたので.jsからerb.jsに拡張子を変えてみましたが上手くいきませんでした。それとRails4から新規プロジェクトを作成すると勝手にコントローラ毎のjs.coffeeファイルが作られるので、どうせならそちらに移動しようと思いcoffeescriptに書き換えて1最終的には以下のようにしました。endurlパラメータはRailsの_PATH表記から文字列に変更memo.idをview内のhiddenフィールドに保存して、jQueryでその値を取得するように変更Railsのフォームから呼ばれた場合とjQueryから呼ばれた場合でrenderするものを変更するこれで一応checkboxでの更新&表示処理が完成しましたが、Railsで生成したフォームからupdateメソッドを呼び出す場合とjQueryからupdateメソッドを呼び出す場合で、画面出力処理が2種類(js.erbと.doneイベント)に分かれています。このサンプルの場合@status変数に格納した文字列を画面に表示するだけの処理ですが、それでも同じ処理をするコードが2ヶ所に存在しているのはよくないでしょう。Javascript側からAjax通信を開始(request.send、$.ajax)するときにコールバック関数としてjs.erbを指定することが出来たり(もしかして出来る?)、RailsのフォームからAjax通信するときにcoffeescript(Javascript、jQuery)のコールバック関数を指定出来たりしたら出力関数を統一出来そうですがそれはそれでややこしそうです。あと、request.methodで分岐していますが、これでいいのかどうか分かりませんしこういうコードは見かけたことが無いような気がします。いうことで結局実際に使用するアプリではformから更新ボタンを無くしてjs.erbは使わないやり方に統一することにしました。こんなことになるなら最初からjs.erbは使わずにjQueryとCoffeeScriptで作ることに決めておけばよかったような気がします。それと実際に使用するサイトでやりたかったことはlazy_high_chartsを使ったグラフ表示なのでdataTypeはtextでなくjsonでやりとりしています。とてつもなく汚いソースですが興味のある方はそちらで確認出来ます。修正前(左)と修正後(右)注意点としてこのアプリの場合、編集画面と新規登録画面が別々なのでよかったのですが、説明に使用したサンプルプロジェクトでは編集画面と新規登録画面で同じフォームを利用しているので新規登録画面でcheckboxをクリックしたときはjQueryイベントが発動しないようにするかフォームを分ける必要があると思います。そもそもcheckboxクリックで更新処理というのが特殊なUIなのかもしれませんが...。