2010年12月21日火曜日

auto completion for rails3 using prototype.js as backend

戦型を追加するときにオートコンプリートを有効にしようとして、 auto_complete_for なんてマクロがあるのか!とググって感動していたら、かなり前にプラグインとして分離されていたみたいで、しかもDHHさん(Railsの作者)によるメンテナンスが2007年止まり…。

代替策はないのかとGoogle先生を酷使するも、 rails3-autocomplete-jquery とかそんなんばっか。

時代はjQueryなのか…Rails3という(地雷かもしれない)最新版を使っておきながらJavaScriptのバックエンドはprototype.jsのほうがいいという保守的な考えのボクには道はないのか…そう思っていたところが!

あまりにも検索トップで荒ぶっているので見逃していた「このサイト」で配布されている autocomplete という、一見Railsとは何の関係も無さそうなライブラリが大活躍。まずは配置。





$ wget http://www.devbridge.com/projects/autocomplete/local/downloads/autocomplete-1.0.4.zip
$ unzip autocomplete-1.0.4.zip
$ rm prototype-6*
$ mv shadow.png public/images
$ mv styles.css public/stylesheets

で、 application.html.erb<%= javascript_include_tag :defaults %> と書く。っていうか普通は書かれてる。

ほいで、

forms_controller.rb:
  # GET /forms/autocomplete
  def autocomplete
    @forms = Forms.all
    respond_to do |format|
      format.json {
        render :text => {:query => params[:query], :suggestions => @forms}.to_json
      }
    end
  end

次にコントローラにこんな感じのことを書く。

クエリは params[:query] に入ってくるみたいだけど、今回は「戦型」という限定されたものを推察してくれればいいので、 Form.all にしてます。

戻り値のフォーマットに JSON (よくわからんけどYAMLっぽいもの)を要求しているので、 suggestions には配列を渡してやります。っていうか、ソースからコピペしてるんだけど、これ @forms.map{|form| form.name} とかになってないとやばいんじゃね? なんで動いてるんだ? まぁいいや。

で、 query 属性には(なぜか)渡ってきたクエリワードを入れてやる必要があるみたいです。他にも返せるものがあったけど、後から確認しよう。

Railsは Hash#to_json という超便利すぎる代物をあらかじめ用意してくれているので、いざというときに頼りになりまくりますね。ついさっき存在を知ったのだけれど。っていうかJSONってなんですか状態ですけれど。

えーそんで、肝心のビューのほうには、

render 'kifu_documents/autocomplete'

HAMLを使っているのでパーシャル化してやって、古くからの慣習に従い末尾から render で呼び出して、

_autocomplete.html.erb:
<script type="text/javascript">
  new Autocomplete('form_name', { serviceUrl:'<%= forms_autocomplete_path %>' });
</script>

中身にはこんな感じのことを書きます。
new Autocomplete の第一引数がオートコンプリートの対象となるフォームで、 serviceUrl にはさきほどコントローラに書いた JSON (いっつもJASONとtypoする…)を返すアクションを指定してやります。今回は意味もなくルーティングしたので forms_autocomplete_path です。

たったこれだけでオートコンプリートできました!
たまにはgemやプラグイン以外にも目を向けなきゃダメってことですね。

おしまい。

押してねっ→BlogPeople「趣味の世界」ブログランキング

0 件のコメント:

コメントを投稿