Rails tips vol2

最近Railsを触っていていろいろ知ったことをメモ。

コントローラから部分テンプレートのみを render したい場合

状況としては、Ajaxのレスポンスとしてある程度複雑なhtmlをテンプレートから生成し、かつ layout の application.html.erb を含めたくない場合。render :partial を使えば良い。

render :partial => 'tasklist',  :locals => {:tasks => @tasks}

部分テンプレートへの引数は :locals => で渡す事もできる。
明示的に渡さなくても部分テンプレート内で @tasks でアクセスしてれば省略可能。

余談だけど、部分テンプレートに引数を渡すか、@val でグローバルっぽくアクセスするかの判断基準でいつも迷う。その部分テンプレートがどのくらい共通で使われているかにも寄るのかな。ポリシー決めないと複数人で開発する際に迷いそう。

日本語のパラメータをモデルで検索用に変換する

パラメータで日本語文字を受け取って、モデルで検索をかけたい場合、そのまま where に入れてもエンコードされているためヒットしない。そこで、モデルで検索パラメータとして使う前に URI.decode() する

where("name = ? and status = ? and msg LIKE ?", name , StatusTable[status] , "%#{URI.decode(filter)}%")
  • filter がパラメータで受け取った日本語検索対象文字列
  • LIKE で検索対象文字列を含むモデルインスタンスを抽出している

Jsonでレスポンスを返す

Ajaxのレスポンスで js.erb でコントローラで生成したデータ群を特定の js メソッドに渡すだけのコードを書くくらいなら、 json で返してクライアント側で js 呼び出しに渡すのがスマートらしい。

json を使うには以下の2点に注意する。

Ajaxリクエスト時に dataType: "jsonp" を付加する

これをやらないとサーバから json を受け取ってもコールバックを呼んでくれない。

   $.ajax({
     type: "PUT",
     cache: false,
     url: "/tasks/" + id,
     data: request_str,
     dataType: "jsonp"      //★ここ重要
   });
render :json でレスポンスを返す

コントローラで json として返したいデータをハッシュで生成して render :json に渡す。
その json データを受け取って処理するクライアントサイドの javascript のメソッドを :callback として指定してあげる。

render :json => counts, :callback => 'updateCounts'

devise で rspec のテスト

ユーザ認証機能付加してくれるプラグイン devise はとても便利なんだけど、フィルターに適用するとコントローラはそれまでの rspec が通らなくなってしまう。

あらかじめあるユーザでログインした状態でコントローラのテストを行いたい場合は以下のようにする。

# spec/support/devise.rb

RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :controller
end
  • テストコードでは sign_in するコードを追加する。
  describe "GET 'index'" do
    it "レスポンスが正常であること" do
      sign_in User.first
      get 'index'
      response.should be_success
    end
  end