[{"data":1,"prerenderedAt":323},["ShallowReactive",2],{"$ft6jtkd6xhw3c":3,"$f2g9griukwkyt4":263},{"featured":4,"latest":129,"categories":227},[5,14,27,37,48,56,66,76,86,96,106,114,122],{"slug":6,"title":7,"date":8,"excerpt":9,"image":10,"categories":11},"custom-database-tables","Custom DataBase Tables","2015-11-24T02:29:34","You can create the new own table freely in the your WordPress database via this plugin. Then, you can make the management of table or (as view or entry or edit) data in a simple user interface.\\nAlso,","\u002Fassets\u002Fuploads\u002F2016\u002F02\u002Fcdbt-overview.png",[12],{"slug":13,"name":7},"cdbt",{"slug":15,"title":16,"date":17,"excerpt":18,"image":19,"categories":20},"10_php_tips_for_developers","PHP開発者が心得ておくべき10の鉄則","2016-01-11T18:38:09","PHPだけに限った話ではないが、プログラミングを行うに当たって、心得て、準備しておくと失敗が劇的に減る事柄をまとめてある良い記事を見つけたので、私なりの解釈で意訳しつつ、経験則を踏まえてあらためてまとめてみた。 オリジナ…","\u002Fassets\u002Fuploads\u002F2016\u002F01\u002Feyecatch-php-10-tips.jpg",[21,24],{"slug":22,"name":23},"column","コラム",{"slug":25,"name":26},"development","開発関連",{"slug":28,"title":29,"date":30,"excerpt":31,"image":32,"categories":33},"jquery-timeline-v1","2種類の横型タイムラインを簡単に作成できる「jQuery.Timeline」をリリース","2017-05-29T14:55:46","現在開発しているサービスで利用するべく、横型タイムラインを生成できるjQueryプラグインを自作したので、そこだけ単独でリリースしてみた。 ソースコード等はGitHubの方にリリースしてあるので、興味のある方は、そち…","\u002Fassets\u002Fuploads\u002F2017\u002F05\u002Fjquery_timeline_image.png",[34],{"slug":35,"name":36},"jqtl","jQuery.Timeline",{"slug":38,"title":39,"date":40,"excerpt":41,"image":42,"categories":43},"optimize-browser-cache-of-static-resources","更新されたJS、CSS、画像のみブラウザキャッシュを破棄して読み込ませる","2018-01-31T15:47:47","WEBサービスの保守や開発をやっていると、JavaScriptやスタイルシート、画像などの静的リソースを更新した際、しばしば「確認したけど、更新されてないよ」とか云われて、「ブラウザのキャッシュを消してからもう一度見て…",null,[44,47],{"slug":45,"name":46},"codes","コード集",{"slug":25,"name":26},{"slug":49,"title":50,"date":51,"excerpt":52,"image":53,"categories":54},"jquery-timeline","jQuery.Timeline version2 – full documentation","2019-03-04T20:40:48","Plugin Overview The jQuery.Timeline plugin provides you two types of the horizontal timeline. You can create a…","\u002Fassets\u002Fuploads\u002F2019\u002F03\u002Fjquery.timeline_v2.jpg",[55],{"slug":35,"name":36},{"slug":57,"title":58,"date":59,"excerpt":60,"image":61,"categories":62},"released-the-sloth","Released the Sloth of mobile-first CSS micro framework!","2019-04-16T18:04:25","I released the “Sloth” that is mobile-first CSS micro framework. I have long used frontend framewo…","\u002Fassets\u002Fuploads\u002F2019\u002F04\u002Fsloth_doc_head.png",[63],{"slug":64,"name":65},"sloth","Sloth",{"slug":67,"title":68,"date":69,"excerpt":70,"image":71,"categories":72},"challenge-to-conceal-the-wordpress-site","WordPressサイトを徹底的に秘匿化する","2020-02-02T23:59:58","私は自分の個人サイトをはじめ、仕事でもWordPressサイトを運用している。WordPressは気軽にサイトを立ち上げられてカスタマイズも簡単な、素晴らしいオープンソースなのだが、世界中で使われまくっているその知名度…","\u002Fassets\u002Fuploads\u002F2020\u002F02\u002Fshutterstock_1878005929.jpg",[73],{"slug":74,"name":75},"wordpress","WordPress関連",{"slug":77,"title":78,"date":79,"excerpt":80,"image":81,"categories":82},"what-is-forkor","Made a shortened URL app called Forkor","2020-07-07T22:27:01","What’s Forkor? Forkor is a service that provides a shortened URL feature that allows you to redirect any…","\u002Fassets\u002Fuploads\u002F2020\u002F07\u002Fforkor.png",[83],{"slug":84,"name":85},"forkor","Forkor",{"slug":87,"title":88,"date":89,"excerpt":90,"image":91,"categories":92},"manual-about-svg-japan","インタラクティブな日本地図を生成するJSプラグイン「SVG Japan」","2020-11-16T21:19:58","各都道府県をそれぞれ選択・クリック可能なインタラクティブな日本地図を生成するネイティブJavaScript建てのプラグイン「SVG Japan」を作ったので、その紹介と使い方をまとめておく。ちなみにソースコードはgit…","\u002Fassets\u002Fuploads\u002F2020\u002F11\u002Fsvg-japan.png",[93],{"slug":94,"name":95},"svg-japan","SVG Japan",{"slug":97,"title":98,"date":99,"excerpt":100,"image":101,"categories":102},"wp-ignitor-plugin-to-conceal-wordpress-site","WordPressサイトを秘匿化するプラグイン「WP Ignitor」","2021-01-19T15:28:21","以前「WordPressサイトを徹底的に秘匿化する」という記事で、WordPress建てのサイトを秘匿化する方法を取り上げたのだが、あれをサイト構築時に毎度実施するとなるととても労力が必要であった。そこで、もっとお手軽…","\u002Fassets\u002Fuploads\u002F2021\u002F01\u002Fbanner-1554x500-1.png",[103],{"slug":104,"name":105},"wp-ignitor","WPイグナイタ",{"slug":107,"title":108,"date":109,"excerpt":110,"image":111,"categories":112},"tastewp","無料でWordPressサイトを複数作成できるWEBサービス「TasteWP」","2021-03-25T20:21:59","私が日本語翻訳に協力しているWEBサービス「TasteWP」について紹介しようと思う。 https:\u002F\u002Ftastewp.com このサービス、サインアップすることなく無料で自分用のWordPressサイトを作れるとい…","\u002Fassets\u002Fuploads\u002F2021\u002F03\u002FTasteWP_screenshot.png",[113],{"slug":74,"name":75},{"slug":115,"title":116,"date":117,"excerpt":118,"image":119,"categories":120},"monster-hunter-rise-skill-simulator","モンハンライズのスキルシミュレータを作ってみた！","2021-06-28T20:24:52","コラムで連載していたNintendo Switch版『モンスターハンターライズ』のスキルシミュレータ開発がやっと一段落して一通り完了した。いやぁ、記事書きながら同時並行で開発すると思っていた以上に時間がかかるもんだなぁ…","\u002Fassets\u002Fuploads\u002F2021\u002F06\u002Fmhrss_v100.png",[121],{"slug":25,"name":26},{"slug":123,"title":124,"date":125,"excerpt":126,"image":42,"categories":127},"comparison-of-javascript-date-libraries","JavaScriptの日時ライブラリを比較してみた","2021-07-28T22:39:19","ネイティブJavaScriptで日時を取り扱う場合、ビルトインされているDateオブジェクトを使うことになるのだが、このDateオブジェクトは取り扱いにクセが多く、直感的に日時を操作できない点でも有名である。そこで、専…",[128],{"slug":25,"name":26},[130,141,153,165,175,184,192,195,198,206,213,220],{"slug":131,"title":132,"date":133,"excerpt":134,"image":135,"categories":136},"pulllog_launched","ガチャ履歴を記録・分析できるWebサービス「PullLog」","2025-08-22T13:05:30","このたび、新しい個人開発サービスとして 「PullLog（プルログ）」 をリリースした。 URLはこちら https:\u002F\u002Fpulllog.net PullLogとは？ PullLogは、ソーシャルゲームのガチャ履歴を記録…","\u002Fassets\u002Fuploads\u002F2025\u002F08\u002Fpulllog_stats_jp.png",[137,140],{"slug":138,"name":139},"industries","プロダクト",{"slug":25,"name":26},{"slug":142,"title":143,"date":144,"excerpt":145,"image":146,"categories":147},"mockapi-php-openapi-schema-generation","モックAPIのレスポンスから OpenAPI 3.0 スキーマを自動生成するPHPツール","2025-04-17T09:31:52","私自身がそうなのですが、OpenAPI仕様書を毎回手作業で書いていて「面倒だな」と思ったことはありませんか？ そんな（私と）あなたにぴったりのツールがあります。 レスポンスの例さえ用意すれば、OpenAPI 3.0 スキ…","\u002Fassets\u002Fuploads\u002F2025\u002F04\u002Fswaggerui-preview.png",[148,151,152],{"slug":149,"name":150},"mockapi-php","MockAPI-PHP",{"slug":138,"name":139},{"slug":25,"name":26},{"slug":154,"title":155,"date":156,"excerpt":157,"image":158,"categories":159},"ambient_playlist_customize","Ambientでメメントモリのラメントプレイヤーを作る","2023-11-30T17:32:39","「Ambient」の最新バージョン 1.2.0で実装した「疑似フェーダー」機能を使って、ソーシャルゲーム「メメントモリ」のYouTube公式チャンネルで公開されているMVを集約したラメント専用プレイヤーを作ってみた。 ラ…","\u002Fassets\u002Fuploads\u002F2023\u002F11\u002Fambient_mememori_1.png",[160,163,164],{"slug":161,"name":162},"ambient","Ambient",{"slug":138,"name":139},{"slug":25,"name":26},{"slug":166,"title":167,"date":168,"excerpt":169,"image":170,"categories":171},"released_ambient_demo_version","Ambientメディアプレイヤーのクラウド版デモを公開","2023-11-22T13:47:36","つい先日「Ambient」の最新バージョン 1.1.0をリリースして、それに合わせてクラウド版デモサイトも公開してみた。 なお、クラウド版デモでローカルのホストコンピュータのメディアを再生するには、そのメディアファイルも…","\u002Fassets\u002Fuploads\u002F2023\u002F10\u002FAmbientMediaPlayer-typologo.png",[172,173,174],{"slug":161,"name":162},{"slug":138,"name":139},{"slug":25,"name":26},{"slug":176,"title":177,"date":178,"excerpt":179,"image":170,"categories":180},"ambient-media-player","YouTubeと自分のPC内メディアを同時に再生できるメディアプレイヤーを作ってみた","2023-10-20T00:00:25","私はよくPCで何か作業をするときには音楽を垂れ流していることが多い。 そういう時にかける曲は、手持ちのアルバムCD等からPCに取り込んだ音源だったり、さらにはYouTubeの動画だったりとメディアや再生環境がバラバラだ。…",[181,182,183],{"slug":161,"name":162},{"slug":138,"name":139},{"slug":25,"name":26},{"slug":185,"title":186,"date":187,"excerpt":188,"image":189,"categories":190},"what-is-the-sunorhc","Sunorhc is a date-time library for JavaScript","2021-08-25T22:55:55","Sunorhc is a lightweight library for handling dates and times for JavaScript. The library wraps a native JavaS…","\u002Fassets\u002Fuploads\u002F2021\u002F08\u002Fshutterstock_1091212919_resized.jpg",[191],{"slug":25,"name":26},{"slug":123,"title":124,"date":125,"excerpt":126,"image":42,"categories":193},[194],{"slug":25,"name":26},{"slug":115,"title":116,"date":117,"excerpt":118,"image":119,"categories":196},[197],{"slug":25,"name":26},{"slug":199,"title":200,"date":201,"excerpt":202,"image":203,"categories":204},"mhrise-skill-simulator-creation-chapter-12","モンスターハンターライズのスキルシミュレータを作ってみる！ 第12回","2021-06-21T13:11:46","今回は「マイセット登録」と護石データの「エクスポート／インポート」機能の追加をしていく。折り良く（悪く？）「FF7リメイク・インターグレード」や「FORTNITEシーズン7」が出たこともあって、そっちをプレイしてたらこ…","\u002Fassets\u002Fuploads\u002F2021\u002F04\u002Fb6ca09e9a7f6faf27641f62dabe64c6ff97b4f326aa478379e3c112aa28eb9ab.jpg",[205],{"slug":22,"name":23},{"slug":207,"title":208,"date":209,"excerpt":210,"image":203,"categories":211},"mhrise-skill-simulator-creation-chapter-11","モンスターハンターライズのスキルシミュレータを作ってみる！ 第11回","2021-06-07T14:52:31","さて、今回はユーザー個別データの管理部分を開発していく予定だが、まずその前にやっておくことがある。 新スキル「風雷合一」に対応する Ver.3.0の大型無料アップデートで追加された新スキルに「風雷合一」というのがある…",[212],{"slug":22,"name":23},{"slug":214,"title":215,"date":216,"excerpt":217,"image":203,"categories":218},"mhrise-skill-simulator-creation-chapter-10","モンスターハンターライズのスキルシミュレータを作ってみる！ 第10回","2021-06-02T00:29:10","今回は、護石管理画面の作成だ。この護石管理では、ユーザーごとに護石の登録を行う機能と、登録した護石を削除する機能を持つ仕様になる。この画面から登録した護石データはデータベースに格納するので、フロントエンド側からのリクエス…",[219],{"slug":22,"name":23},{"slug":221,"title":222,"date":223,"excerpt":224,"image":203,"categories":225},"mhrise-skill-simulator-creation-chapter-9","モンスターハンターライズのスキルシミュレータを作ってみる！ 第9回","2021-05-22T23:56:27","さて、今回はVuexによるデータ・キャッシュの実装だ。一度データベースから読み込んだデータをフロントエンド側で再利用可能なストアに格納することで、データベースへの接続回数を減らしてシステム負荷を下げるとともに、UX的な…",[226],{"slug":22,"name":23},[228,230,232,236,238,239,240,241,242,244,247,248,250,252,254,258,261],{"slug":161,"name":162,"count":229},3,{"slug":13,"name":7,"count":231},7,{"slug":233,"name":234,"count":235},"csnp","Custom Sticky Notes",2,{"slug":84,"name":85,"count":237},1,{"slug":35,"name":36,"count":229},{"slug":149,"name":150,"count":237},{"slug":64,"name":65,"count":237},{"slug":94,"name":95,"count":237},{"slug":74,"name":75,"count":243},37,{"slug":245,"name":246,"count":237},"wpqt","WP Qiita",{"slug":104,"name":105,"count":237},{"slug":22,"name":23,"count":249},29,{"slug":45,"name":46,"count":251},16,{"slug":138,"name":139,"count":253},5,{"slug":255,"name":256,"count":257},"lifelog","ライフログ",64,{"slug":259,"name":260,"count":235},"uncategorized","未分類",{"slug":25,"name":26,"count":262},45,{"type":264,"post":265},"post",{"slug":266,"title":267,"date":268,"excerpt":269,"image":42,"categories":270,"modified":272,"html":273,"tags":274,"related":287,"prev":308,"next":315},"for-ajax-in-ruby-on-rails-part1","Ruby on RailsのAjax処理のおさらい","2015-01-20T19:41:34","何気に、アプリケーションで取り扱うデータ量が増えた場合や、大容量データをデータベースとやり取りする時なんかは、Ajaxを使ってデータ通信をバックエンド側に押しやることで、WEBフロント側のUXからパフォーマンスの悪さを改…",[271],{"slug":25,"name":26},"2021-02-03T20:45:35","\u003Cp>何気に、アプリケーションで取り扱うデータ量が増えた場合や、大容量データをデータベースとやり取りする時なんかは、Ajaxを使ってデータ通信をバックエンド側に押しやることで、WEBフロント側のUXからパフォーマンスの悪さを改善できたりする。また、ネットワーク経路的にproxyサーバとかを中継するような環境間でデータのやり取りをする場合などに、proxy側で接続時間にリミットがかけてあったりすると、通常アクセスではデータ通信時間がリミットに達して503エラーとかになってしまうような処理でもAjaxで通信をバックエンド化することで、回避できたりもするのだ。\u003Cbr \u002F>\n通信帯域が小さいスマートデバイスが主力である今のご時勢、Ajaxによる非同期処理は、言語やフレームワークを問わずに必須な技術になっている。\u003Cbr \u002F>\nオレはPHPerなので、PHP＋JavaScript（jQuery）やWordPressでのAjax処理なら特に造作もなく作れていたんだが、今回Rubyでのアプリケーション開発をして、Ruby on Rails（バージョン 4.2.0）でのAjax処理の開発にかなり手を焼いた次第。確かに、広く云われているようにRailsでのAjax処理はお手軽で生産性が高いのだけれど、オレの知見的にはかなり癖がある作り方が必要だった。応用を利かそうとすると毎度シビれる状況に陥ったりしてなかなかに大変だった──という経験から、一度ここらでRails＋Ajaxについての情報を整理しておこうと思ったのだ。\u003C\u002Fp>\n\u003Ch2>環境情報\u003C\u002Fh2>\n\u003Chr \u002F>\n\u003Cp>まずは本記事におけるオレのRails環境情報をまとめておく。RubyやRailsではバージョンによって結構コーディング条件や使える関数が異なったりするので、これは重要。\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Ruby 1.9.3\u003C\u002Fli>\n\u003Cli>Ruby on Rails 4.2.0\u003C\u002Fli>\n\u003Cli>jquery-rails 4.0.3 （※ Railsに依存するgemなのでインストール時に自動で入るハズ？）\u003C\u002Fli>\n\u003Cli>jQuery 1.11.2（※ 2015\u002F1\u002F19時点。Rails の Turbolinkに よって自動で最新版が読み込まれる）\u003C\u002Fli>\n\u003Cli>coffee-script 2.3.0 (※ Railsに依存するgemの coffee-rails は 4.1.0)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>一般的なAjax処理のおさらい\u003C\u002Fh2>\n\u003Chr \u002F>\n\u003Cp>Railsに限らず、世間一般のAjax処理の全体な流れを図にすると下記のようになるのかな──と。\u003C\u002Fp>\n\u003Cp>\u003Cimg decoding=\"async\" src=\"\u002Fassets\u002F2015\u002F01\u002Fajax-general.png\" alt=\"Ruby on RailsでのAjax処理の概要\" title=\"Ruby on RailsでのAjax処理の概要\" \u002F>\u003C\u002Fp>\n\u003Cp>古典的なWEBアプリケーションだと、ボタンアクションや画面遷移などのユーザー側からの明確なイベント後に、おもにWEBページの読込処理を伴ってサーバーサイドとやり取りをするんだが、Ajaxだとユーザーからの明示的なアクションがなくても、およそJavaScript側で取得できるすべてのイベントから発火させることができ、さらにページ遷移などを伴わずにリアルタイムにフロントエンドに結果を反映できるのが大きな特徴だ。非同期で実行すれば、ブラウザ側の機能がロックされることもないので、データがすべて読み込まれるまでユーザーに待ちを強いるようなこともないし、都度最小限のデータアクセスでアプリケーションを動かすことができるようになるので、ユーザビリティやアクセシビリティを最大化させられる。\u003C\u002Fp>\n\u003Cp>あと重要なのが、Ajaxの非同期処理はイベント発火順のシーケンシャルには処理されないということだ（下図参照）。\u003C\u002Fp>\n\u003Cp>\u003Cimg decoding=\"async\" src=\"\u002Fassets\u002F2015\u002F01\u002Fajax-general_2.png\" alt=\"非同期なAjaxチェーンのレスポンス\" title=\"非同期なAjaxチェーンのレスポンス\" \u002F>\u003C\u002Fp>\n\u003Cp>JavaScript側で、1つのイベントに対して非同期設定のAjaxで複数のリクエスト送信を行うような場合、そのレスポンスがリクエスト順には戻ってこないのだ。これは、Ajax処理を連結してAjaxチェーンを作る時などに注意しておかないと、意図しない結果になったりする。\u003C\u002Fp>\n\u003Ch2>RailsでのAjax処理のおさらい\u003C\u002Fh2>\n\u003Chr \u002F>\n\u003Cp>Ruby on Railsでは View 側のヘルパータグ（\u003Ccode>form_tag\u003C\u002Fcode>）等で \u003Ccode>:remote =&gt; true\u003C\u002Fcode> を指定するだけで該当フォームでのsubmitアクションをAjax化してくれる。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Viewの例: index.html.erb\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;%= form_tag({:controller =&gt; '&lt;コントローラ名&gt;', :action =&gt; 'index'}, :remote =&gt; true, :class =&gt; 'form-ajax') do -%&gt;\n&lt;%= hidden_field_tag :ajax_handler, 'handle_name1' -%&gt;\n&lt;%= submit_tag('Start Ajax', :class =&gt; 'btn btn-primary btn-sm') -%&gt;\n&lt;% end %&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Controller側ではその アクションに対応する処理を行い、\u003Ccode>render\u003C\u002Fcode> でレスポンスを指定する。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Controllerの例: XXXXs_controller.rb\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>class XXXXsController &lt; ApplicationController\n  def index\n    ajax_action unless params[:ajax_handler].blank?\n\n    # Ajaxリクエストではない時の処理\n\n  end\n\n  def ajax_action\n    if params[:ajax_handler] == 'handle_name1'\n      # Ajaxの処理\n      @data = Datum.all\n      if @data.size &gt; 0\n        render\n      else\n        render json: 'no data'\n      end\n    end\n  end\nend\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>デフォルトではレスポンスとしてフロントエンド側にJavaScriptの処理が戻ってくる。そのレスポンス用JavaScriptは View 側にJavaScriptテンプレートを用意する。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>JavaScriptテンプレートの例: index.js.erb\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>if ($('#ajax-response-wrapper').size() === 0) {\n  $('body').append('&lt;div id=\"ajax-response-wrapper\"&gt;&lt;\u002Fdiv&gt;');\n} else {\n  $('#ajax-response-wrapper').html('');\n}\n$('#ajax-response-wrapper').html('&lt;%=j render partial: \"ajax_container\", collections: @data %&gt;');\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>この例では、レンダリングされたインスタンス変数\u003Ccode>@data\u003C\u002Fcode>を整形したHTMLとして表示するため、さらにJavaScriptから partial を使ってhtmlテンプレートを呼んでいる。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>partialテンプレートの例: _ajax_container.html.erb\u003C\u002Fstrong> （※ \u003Ccode>_&lt;partial名&gt;.html.erb\u003C\u002Fcode> ）\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;ul&gt;\n&lt;% @data.each do |datum| %&gt;\n&lt;li&gt;&lt;%= datum.slug %&gt;&lt;\u002Fli&gt;\n&lt;% end %&gt;\n&lt;\u002Ful&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>これだけで（…といっても結構手間だが）Ajax処理（正常系のみ）は完結してしまうのだ（この辺の詳しい解説は色々なサイトに紹介されているので本記事では割愛する）。一番凄いと思ったのが、Ajax関連のJavaScriptなんぞ一切コーディングせずともAjax処理ができてしまうという点だ。このあたりがRailsでのAjax処理の生産性が高い理由でもある。\u003Cbr \u002F>\nただ、実用的なアプリケーション開発を行う場合、このような単純な処理だけでは機能不足なことが多くて、エラー処理やAjax中のview制御などもう少し突っ込んだハンドリングが最低限必要になってくる。\u003Cbr \u002F>\n例えば、前述の例だと、controllerでDatumモデルにレコードがない場合エラーにしているが、フロントエンド側でエラー用のJSONをキャッチする処理がないため、ユーザーがエラーを認識できないのだ。ではAjaxのエラー処理のサンプルを書いてみる。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Ajaxエラーキャッチ用JavaScriptの例: XXXXs.coffee\u003C\u002Fstrong> （※ app\u002Fassets\u002Fjavascript\u002F 内）\u003C\u002Fp>\n\u003Cpre>\u003Ccode>XXXXs = -&gt;\n  $('.form-ajax').on 'ajax:error', (e, xhr, status, error) -&gt;\n    alert xhr.responseText\n\n$(document).ready(XXXXs)\n$(document).on('page:load', XXXXs)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>RailsのJavaScript側でのAjax制御の実装は、上記のようにAjax通信の発火フォームのイベントハンドラとして定義する。しかしまぁ、ここまで書いてきて改めて思ったが、単純な1つのAjax処理に対してあまりにも手を入れなければならないファイルが多い。これだと管理が大変だ。前出のJavaScriptテンプレートやpartialテンプレートを使わず、controllerからは処理結果を一律JSONでレンダリングして、コントローラ用のCoffeeScriptにAjaxの後続処理を一元化してしまった方が全体の処理として見通しが良くなる気がする。\u003Cbr \u002F>\n──ということで、この記事では前出のようなRailsの独自実装型仕様に極力依存せずに、フロントエンドのAjax関連処理はJavaScript（jQuery）に集約するような建付けでやってみる。\u003C\u002Fp>\n\u003Ch3>jQueryでのAjaxイベント\u003C\u002Fh3>\n\u003Cp>そもそもJavaScriptでAjaxを取り扱う際は、素のJavaScriptよりjQueryでやった方が圧倒的に簡単だ。コードの見通しが良いのはもちろん、コード量も抑えられるためコーディングコストが低いというメリットもある。幸いにもRailsはデフォルトでjQueryが使える環境になっているし、さらにCoffeeScriptで書けるので、スクリプト部分のコーディングがとても楽だ（CoffeeScriptの作法に馴れるまではちょっと違和感があったが…）。──というわけで、本記事でのJavaScriptコードはCoffeeScript+jQueryで書いてあるのでご注意を。\u003C\u002Fp>\n\u003Cp>さて、まずは一般的なjQueryでのAjaxイベントをまとめてみた。\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth align=\"center\">イベント名\u003C\u002Fth>\n\u003Cth align=\"center\">Railsでのイベント名\u003C\u002Fth>\n\u003Cth align=\"left\">呼び出しタイミング\u003C\u002Fth>\n\u003Cth align=\"center\">第1引数\u003C\u002Fth>\n\u003Cth align=\"center\">第2引数\u003C\u002Fth>\n\u003Cth align=\"center\">第3引数\u003C\u002Fth>\n\u003Cth align=\"left\">備考\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd align=\"center\">Before\u003C\u002Ftd>\n\u003Ctd align=\"center\">ajax:before\u003C\u002Ftd>\n\u003Ctd align=\"left\">全Ajaxリクエストの開始前\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"left\">イベント停止時、Ajaxリクエストは中断\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">BeforeSend\u003C\u002Ftd>\n\u003Ctd align=\"center\">ajax:beforeSend\u003C\u002Ftd>\n\u003Ctd align=\"left\">Ajaxリクエストが送信される直前\u003C\u002Ftd>\n\u003Ctd align=\"center\">XHR\u003C\u002Ftd>\n\u003Ctd align=\"center\">settings\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"left\">イベント停止時、Ajaxリクエストは中断\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Send\u003C\u002Ftd>\n\u003Ctd align=\"center\">ajax:send\u003C\u002Ftd>\n\u003Ctd align=\"left\">Ajaxリクエストの送信直後（通信成功時）\u003C\u002Ftd>\n\u003Ctd align=\"center\">XHR\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"left\">\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Error\u003C\u002Ftd>\n\u003Ctd align=\"center\">ajax:error\u003C\u002Ftd>\n\u003Ctd align=\"left\">通信成功後、サーバーがエラーを返した時\u003C\u002Ftd>\n\u003Ctd align=\"center\">XHR\u003C\u002Ftd>\n\u003Ctd align=\"center\">status\u003C\u002Ftd>\n\u003Ctd align=\"center\">error\u003C\u002Ftd>\n\u003Ctd align=\"left\">jQuery 1.7系まで\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Success\u003C\u002Ftd>\n\u003Ctd align=\"center\">ajax:success\u003C\u002Ftd>\n\u003Ctd align=\"left\">通信成功後、HTTPレスポンスが成功した時\u003C\u002Ftd>\n\u003Ctd align=\"center\">data\u003C\u002Ftd>\n\u003Ctd align=\"center\">status\u003C\u002Ftd>\n\u003Ctd align=\"center\">XHR\u003C\u002Ftd>\n\u003Ctd align=\"left\">jQuery 1.7系まで\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Complete\u003C\u002Ftd>\n\u003Ctd align=\"center\">ajax:complete\u003C\u002Ftd>\n\u003Ctd align=\"left\">（HTTPレスポンスの結果に関係なく）Ajaxリクエストが完了時\u003C\u002Ftd>\n\u003Ctd align=\"center\">XHR\u003C\u002Ftd>\n\u003Ctd align=\"center\">status\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"left\">jQuery 1.7系まで\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Fail\u003C\u002Ftd>\n\u003Ctd align=\"center\">fail()\u003C\u002Ftd>\n\u003Ctd align=\"left\">旧errorの後継イベント。sendイベントでのXHRオブジェクトのメソッドとして呼び出す\u003C\u002Ftd>\n\u003Ctd align=\"center\">XHR\u003C\u002Ftd>\n\u003Ctd align=\"center\">status\u003C\u002Ftd>\n\u003Ctd align=\"center\">error\u003C\u002Ftd>\n\u003Ctd align=\"left\">jQuery 1.8以降推奨\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Done\u003C\u002Ftd>\n\u003Ctd align=\"center\">done()\u003C\u002Ftd>\n\u003Ctd align=\"left\">旧successの後継イベント。sendイベントでのXHRオブジェクトのメソッドとして呼び出す\u003C\u002Ftd>\n\u003Ctd align=\"center\">data\u003C\u002Ftd>\n\u003Ctd align=\"center\">status\u003C\u002Ftd>\n\u003Ctd align=\"center\">XHR\u003C\u002Ftd>\n\u003Ctd align=\"left\">jQuery 1.8以降推奨\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Always\u003C\u002Ftd>\n\u003Ctd align=\"center\">always()\u003C\u002Ftd>\n\u003Ctd align=\"left\">旧completeの後継イベント。sendイベントでのXHRオブジェクトのメソッドとして呼び出す\u003C\u002Ftd>\n\u003Ctd align=\"center\">XHR\u002Fdata\u003C\u002Ftd>\n\u003Ctd align=\"center\">status\u003C\u002Ftd>\n\u003Ctd align=\"center\">error\u002FXHR\u003C\u002Ftd>\n\u003Ctd align=\"left\">jQuery 1.8以降推奨。HTTPレスポンスがエラーか正常かで引数が変化する\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Aborted\u003C\u002Ftd>\n\u003Ctd align=\"center\">ajax:aborted:required\u003C\u002Ftd>\n\u003Ctd align=\"left\">Ajaxリクエスト中断時（空リクエスト型）\u003C\u002Ftd>\n\u003Ctd align=\"center\">elements\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"left\">中断された際でも空リクエストとして送信される\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Aborted\u003C\u002Ftd>\n\u003Ctd align=\"center\">ajax:aborted:file\u003C\u002Ftd>\n\u003Ctd align=\"left\">Ajaxリクエスト中断時（ファイル破棄型）\u003C\u002Ftd>\n\u003Ctd align=\"center\">elements\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"center\">&#8211;\u003C\u002Ftd>\n\u003Ctd align=\"left\">中断された際、ファイルアップロード用フィールドのバイナリデータは送信されない\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd align=\"center\">Then\u003C\u002Ftd>\n\u003Ctd align=\"center\">then()\u003C\u002Ftd>\n\u003Ctd align=\"left\">イベントのレスポンス結果取得時\u003C\u002Ftd>\n\u003Ctd align=\"center\">doneCallbacks\u003C\u002Ftd>\n\u003Ctd align=\"center\">failCallbacks\u003C\u002Ftd>\n\u003Ctd align=\"center\">progressCallbacks\u003C\u002Ftd>\n\u003Ctd align=\"left\">Ajax専用イベントではないが、イベントのレスポンス結果によってCallback処理を行えるため、Ajaxのチェーン処理には欠かせない\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>よくWebでRailsのAjax系記事を調べると、旧（ふる）いjQueryのAjaxイベントである「success」や「error」を使って書いてあるのが多くて、今どきのjQuery＋Ajaxの推奨実装と合ってないよなぁ…とか思っていたんだが、その原因はRailsのjQuery＋Ajaxの処理実体である\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Frails\u002Fjquery-ujs\u002Fwiki\u002Fajax\">jquery-ujsの実装\u003C\u002Fa>によるところが大きかった。\u003Cbr \u002F>\n本記事では、その jquery-ujs の仕様に依存することなく、jQuery自体の推奨実装で処理を書いていこうと思う。\u003C\u002Fp>\n\u003Ch2>RailsでjQuery推奨仕様に準じてAjax処理を書く\u003C\u002Fh2>\n\u003Chr \u002F>\n\u003Cp>さて、具体的な処理例があった方がわかりやすいので、サンプルとしてそこそこ実用的（？…かもしれない）なAjax処理を定義してみる。\u003C\u002Fp>\n\u003Cblockquote>\u003Cp>\n  X軸Y軸が可変である範囲座標系テーブル内に、データベースから該当するデータのみをAjaxで取得してきて表示する。\n\u003C\u002Fp>\u003C\u002Fblockquote>\n\u003Cp>いやぁ、文字で書くと\u003Cstrong>まったくもって実際の仕様がピンとこない\u003C\u002Fstrong>もんだな…実用的なのかも怪しいもんだが、まぁいいや（笑）\u003C\u002Fp>\n\u003Cp>とりあえず、Ajax処理のサンプルアプリ用のrailsアプリを作成する。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$ rails new ajax-test\n$ rails g controller coordinates index show\n$ rake db:create\n$ rails g model datum name:string axis_x:integer axis_y:integer axis_slug:string description:text\n$ rake db:migrate\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>ここはあえて詳しく解説しないが、\u003Ccode>ajax-test\u003C\u002Fcode>というrailsアプリを新規作成して、\u003Ccode>coordinates\u003C\u002Fcode>というコントローラと\u003Ccode>Datum\u003C\u002Fcode> というデータベースを作った次第。次にDBに入れ込むデータが欲しいので、\u003Ccode>db\u002Fseeds.rb\u003C\u002Fcode>に初期データ作成用のスクリプトを書く。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>require 'digest\u002Fmd5'\nfor i in 1..10000 do\n  x = rand(100) + 1\n  y = rand(100) + 1\n  slug = \"#{x}-#{y}\"\n  md5_hash = Digest::MD5.new.update(\"#{i}\").to_s\n  Datum.create(name: md5_hash, axis_x: x, axis_y: y, axis_slug:slug, description: nil)\nend\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>初期データの説明としては、100×100の座標範囲内にランダムに10000個の点を打った感じ。それぞれの点にはmd5ハッシュ形式のnameが付けてある。\u003Ccode>axis_slug\u003C\u002Fcode>はフロントエンドのHTML側にデータを表示する時に利用する、数値座標のエイリアス的なものだ。\u003Cbr \u002F>\nで、seedができたので、流し込む（10000レコードあるのでちょいと時間がかかった）。流し込んだら、コマンドラインでDBにデータ入ってるか確認してみよう。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>$ rake db:seed\n$ rails db\n> .table\ndata               schema_migrations\n> select count(*) from data;\n10000\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>次に、Ajaxリクエスト発火時のルーティングを設定する（\u003Ccode>config\u002Froutes.rb\u003C\u002Fcode>）。すでに定義済みのルートを利用してコントローラ側でAjax処理を振り分けてもいいのだが、コードの見通しが悪くなるので、Ajaxのルートは別途定義した方が後々保守しやすくなる。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Rails.application.routes.draw do\n  get 'coordinates\u002Findex'\n  get 'coordinates\u002Fshow'\n  post 'coordinates\u002Fget_area'\nend\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>実際に追加するのは、最後の一行の \u003Ccode>post 'coordinates\u002Fget_area'\u003C\u002Fcode> だけ。\u003Cbr \u002F>\nそして、Ajaxレスポンスの処理実体であるコントローラを作る（app\u002Fcontrollers\u002Fcoordinates_controller.rb）。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>class CoordinatesController &lt; ApplicationController\n  def index\n    @range = {\n      min_x:    params[:min_x]  ||= 0,\n      max_x:    params[:max_x]  ||= 20,\n      min_y:    params[:min_y]  ||= 0,\n      max_y:    params[:max_y]  ||= 20,\n    }\n  end\n\n  def show\n  end\n\n  def get_area\n    @data = Datum.where('axis_x &gt;= ? AND axis_x &lt;= ? AND axis_y &gt;= ? AND axis_y &lt;= ?', params[:min_x], params[:max_x], params[:min_y], params[:max_y])\n\n    if @data.size &gt; 0\n      render json: @data\n    else\n      render json: \"No data\"\n    end\n  end\nend\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>通常アクセス時は \u003Ccode>\u002Fcoordinates\u002Findex\u003C\u002Fcode> であり、Submitボタンを押すとAjax開始で \u003Ccode>get_area\u003C\u002Fcode> のメソッドが呼ばれるというルーティングになっている。Ajax処理のサーバーサイド側の実装は \u003Ccode>get_area\u003C\u002Fcode> メソッドで、データベースから指定範囲内に属するデータのみを取得して、JSONレスポンスとしてフロントエンドに返すというものだ。\u003C\u002Fp>\n\u003Cp>今度はフロントエンド側を作って行く。まずはベースとなるHTMLテンプレートとして、HTML文書の大枠を定義する \u003Ccode>app\u002Fviews\u002Flayouts\u002Fapplication.html.erb\u003C\u002Fcode> だ。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n  &lt;meta charset=\"utf-8\"&gt;\n  &lt;title&gt;Ajax test app&lt;\u002Ftitle&gt;\n  &lt;%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' =&gt; true %&gt;\n  &lt;link href=\"\u002F\u002Fmaxcdn.bootstrapcdn.com\u002Fbootstrap\u002F3.2.0\u002Fcss\u002Fbootstrap.min.css\" rel=\"stylesheet\"&gt;\n  &lt;%= javascript_include_tag 'application', 'data-turbolinks-track' =&gt; true %&gt;\n  &lt;script src=\"\u002F\u002Fmaxcdn.bootstrapcdn.com\u002Fbootstrap\u002F3.2.0\u002Fjs\u002Fbootstrap.min.js\"&gt;&lt;\u002Fscript&gt;\n  &lt;%= csrf_meta_tags %&gt;\n&lt;\u002Fhead&gt;\n&lt;body&gt;\n\n&lt;%= yield %&gt;\n\n&lt;\u002Fbody&gt;\n&lt;\u002Fhtml&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>ここはそのままでも問題ないのだが、テーブルなどの見た目を整えたいので bootstrap をCDN経由で読み込むようにしている。そして、次にRailsアプリのフロントエンドのテンプレートを作る。パスは \u003Ccode>app\u002Fviews\u002Fcoordinates\u002Findex.html.erb\u003C\u002Fcode> である。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>  &lt;div class=\"container\"&gt;\n    &lt;h2&gt;Coordinates#index&lt;\u002Fh2&gt;\n    &lt;table class=\"table table-striped table-bordered table-condensed table-hover\"&gt;\n&lt;% @range[:max_y].downto(@range[:min_y]) do |row| %&gt;\n      &lt;tr class=\"row-&lt;%= row %&gt;\"&gt;\n  &lt;% @range[:min_x].upto(@range[:max_x]) do |col| %&gt;\n    &lt;% if col == 0 %&gt;\n      &lt;% if row == 0 %&gt;\n        &lt;th&gt;&lt;%= col %&gt;&lt;\u002Fth&gt;\n      &lt;% else %&gt;\n        &lt;th&gt;&lt;%= row %&gt;&lt;\u002Fth&gt;\n      &lt;% end %&gt;\n    &lt;% else %&gt;\n      &lt;% if row == 0 %&gt;\n        &lt;th&gt;&lt;%= col %&gt;&lt;\u002Fth&gt;\n      &lt;% else %&gt;\n        &lt;td class=\"rc&lt;%= col %&gt;-&lt;%= row %&gt;\"&gt;&lt;\u002Ftd&gt;\n      &lt;% end %&gt;\n    &lt;% end %&gt;\n  &lt;% end %&gt;\n      &lt;\u002Ftr&gt;\n&lt;% end %&gt;\n    &lt;\u002Ftable&gt;\n    &lt;%= form_tag coordinates_get_area_path(), :method =&gt; :post, :class =&gt; 'form-get-coordinates form-inline' do %&gt;\n      &lt;div class=\"form-group\"&gt;\n        &lt;label class=\"sr-only\" for=\"commit\"&gt;Set Range&lt;\u002Flabel&gt;\n        &lt;div class=\"input-group\"&gt;\n          &lt;div class=\"input-group-addon\"&gt;X-Min&lt;\u002Fdiv&gt;\n          &lt;%= number_field_tag :min_x, @range[:min_x], in: 0...100, :class =&gt; 'form-control', :readonly =&gt; true %&gt;\n        &lt;\u002Fdiv&gt;\n        &lt;div class=\"input-group\"&gt;\n          &lt;div class=\"input-group-addon\"&gt;X-Max&lt;\u002Fdiv&gt;\n          &lt;%= number_field_tag :max_x, @range[:max_x], in: 1..100, :class =&gt; 'form-control', :readonly =&gt; true %&gt;\n        &lt;\u002Fdiv&gt;\n        &lt;div class=\"input-group\"&gt;\n          &lt;div class=\"input-group-addon\"&gt;Y-Min&lt;\u002Fdiv&gt;\n          &lt;%= number_field_tag :min_y, @range[:min_y], in: 0...100, :class =&gt; 'form-control', :readonly =&gt; true %&gt;\n        &lt;\u002Fdiv&gt;\n        &lt;div class=\"input-group\"&gt;\n          &lt;div class=\"input-group-addon\"&gt;Y-Max&lt;\u002Fdiv&gt;\n          &lt;%= number_field_tag :max_y, @range[:max_y], in: 1..100, :class =&gt; 'form-control', :readonly =&gt; true %&gt;\n        &lt;\u002Fdiv&gt;\n      &lt;\u002Fdiv&gt;\n      &lt;%= submit_tag 'Get Coordinates', :class =&gt; 'btn btn-primary submit-ajax' %&gt;\n    &lt;% end %&gt;\n  &lt;\u002Fdiv&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>テーブルを動的に生成するところがちょいと見づらいが仕方ない。あと、本当はテーブルの可視範囲を下部の入力欄から指定できるようにしようと思っていたのだが、上のテーブル部分と連携させるのが結構面倒そうだったので、とりあえず ‘readonly‘ 化して入力できないようにしてある（今回やりたいAjax処理のおさらいとはちょっと外れちゃうんで割愛ッス…）。\u003Cbr \u002F>\nそして、ようやくAjaxリクエスト部のJavaScript（jQuery）をCoffeeScriptで書く。パスは \u003Ccode>app\u002Fassets\u002Fjavascript\u002Fcoordinates.coffee\u003C\u002Fcode> だ。\u003C\u002Fp>\n\u003Cpre>\u003Ccode>coordinates = -&gt;\n\n  $('.submit-ajax').on 'click', (e) -&gt;\n    e.preventDefault()\n    getCoordinatesInRange()\n\n  getCoordinatesInRange = -&gt;\n    post_data = {\n      min_x: $('#min_x').val()\n      max_x: $('#max_x').val()\n      min_y: $('#min_y').val()\n      max_y: $('#max_y').val()\n    }\n    jqXHR = $.ajax({\n      async: true\n      url: $('.form-get-coordinates').attr('action')\n      type: $('.form-get-coordinates').attr('method')\n      data: post_data\n      dataType: 'json'\n      cache: false\n      beforeSend: (xhr, set) -&gt;\n        $('td[class^=\"rc\"]').html('')\n    })\n\n    jqXHR.done (data, stat, xhr) -&gt;\n      console.log { done: stat, data: data, xhr: xhr }\n      data.forEach (obj) -&gt;\n        $(\".rc#{obj.axis_slug}\").append(\"&lt;div class=\"center-block\"&gt;&lt;a href=\"\u002Fcoordinates\u002Fshow#{obj.id}\"&gt;#{obj.id}&lt;\u002Fa&gt;&lt;\u002Fdiv&gt;\")\n\n    jqXHR.fail (xhr, stat, err) -&gt;\n      console.log { fail: stat, error: err, xhr: xhr }\n      alert xhr.responseText\n\n    jqXHR.always (res1, stat, res2) -&gt;\n      console.log { always: stat, res1: res1, res2: res2 }\n      alert 'Ajax Finished!' if stat is 'success'\n\n$(document).ready(coordinates)\n$(document).on('page:load', coordinates)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>最後に、見た目をさらによくするためのスタイルを追加する。パスは \u003Ccode>app\u002Fassets\u002Fstylesheets\u002Fcoordinates.scss\u003C\u002Fcode>\u003C\u002Fp>\n\u003Cpre>\u003Ccode>.table th, .table td {\n  text-align: center;\n  vertical-align: middle;\n  min-width: 3em;\n}\n.table th {\n  background-color: #e8e8e8!important;\n  color: #888888;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>これで完成だ。早速、ブラウザで \u003Ccode>&lt;Railsが動いている環境のホスト名&gt;\u002Fcoordinates\u002Findex\u003C\u002Fcode> にアクセスしてみると、下記のようなページが表示される。\u003C\u002Fp>\n\u003Cp>\u003Cimg decoding=\"async\" src=\"\u002Fassets\u002F2015\u002F01\u002Fajax-sample-app1.png\" alt=\"Ajaxテスト用サンプルアプリ（Ajax前）\" title=\"Ajaxテスト用サンプルアプリ\" \u002F>\u003C\u002Fp>\n\u003Cp>テーブル下の「Get Coodinates」ボタンを押すとAjax処理が開始し、データベースから20×20の範囲内座標を持っているデータを全て取得してきて、テーブル内に表示される（下図参照）。\u003C\u002Fp>\n\u003Cp>\u003Cimg decoding=\"async\" src=\"\u002Fassets\u002F2015\u002F01\u002Fajax-sample-app2.png\" alt=\"Ajaxテスト用サンプルアプリ（Ajax後）\" title=\"Ajaxテスト用サンプルアプリ\" \u002F>\u003C\u002Fp>\n\u003Cp>もしこのページをテーブルのセルを作成しつつ、合致するデータを各セルに入れ込みながらレンダリングするような仕様だった場合、ちょっと考えただけでもかなり面倒そうな処理を書かないといけなくなりそうで気が重くなる。なので、テーブルの枠だけサクっと作ってから、Ajaxでデータを流し込むというやり方は、結構スマートな方法なんではないだろうか…。\u003C\u002Fp>\n\u003Cp>本当はこのサンプル、先にテーブルの表示範囲を定義するAjax処理を行ってから、今回のデータ取得処理をチェーンさせて、連続するAjax処理の進捗率をリアルタイムに表示させる例としてまとめておきたかったんだが…この記事自体が想像以上に長文になったので、ここいらでやめておく。途中Railsアプリの作り方みたいな手順が入って本筋から外れてしまったのが痛かったかな…（笑）\u003C\u002Fp>\n\u003Cp>まぁ、Ajaxチェーンのおさらいはまた別の機会にやろうかと。\u003C\u002Fp>\n",[275,278,281,284],{"slug":276,"name":277},"ajax","Ajax",{"slug":279,"name":280},"coffeescript","CoffeeScript",{"slug":282,"name":283},"rails4","Rails4",{"slug":285,"name":286},"ruby","Ruby",[288,292,299,303],{"slug":38,"title":39,"date":40,"excerpt":41,"image":42,"categories":289},[290,291],{"slug":45,"name":46},{"slug":25,"name":26},{"slug":293,"title":294,"date":295,"excerpt":296,"image":42,"categories":297},"compare-php-and-ruby-and-javascript","RubyとPHPとJavaScriptの狭間で","2014-08-04T16:02:58","ここ1ヶ月ほど、会社の仕事でRubyを使った開発業務をしている。同時に、プライベートでは、WordPressのテーマ開発やプラグイン開発を進めてもいるため、RubyとPHPとJavaScriptのコーディングを同時並行で…",[298],{"slug":22,"name":23},{"slug":131,"title":132,"date":133,"excerpt":134,"image":135,"categories":300},[301,302],{"slug":138,"name":139},{"slug":25,"name":26},{"slug":142,"title":143,"date":144,"excerpt":145,"image":146,"categories":304},[305,306,307],{"slug":149,"name":150},{"slug":138,"name":139},{"slug":25,"name":26},{"slug":309,"title":310,"date":311,"excerpt":312,"image":42,"categories":313},"summary_of_2014_and_prospects_for_2015","2014年の総括と2015年の展望","2014-12-25T12:03:34","今年の半分はRubyな一年だった 今年の夏頃からずっと仕事でRubyでのアプリケーション開発をやって来て、先月からはRuby on RailsでそのRubyアプリのGUIサービスを作っているのだが、慣れないRuby言語と…",[314],{"slug":255,"name":256},{"slug":316,"title":317,"date":318,"excerpt":319,"image":42,"categories":320},"compared-to-goutte-and-phpquery-of-scraping-library-for-php","PHPのWebスクレイピング・ライブラリ「Goutte」と「phpQuery」を比較してみた","2015-02-02T12:06:34","Custom DataBase Tablesなど自作のWordPressプラグインを公式SVNに登録していると、ダウンロード状況等のステータスを毎度WordPress.orgまで見に行くのが億劫になってくるのはオレだけだ…",[321,322],{"slug":22,"name":23},{"slug":25,"name":26},1793391398618]