respond_to |format| は複数のフォーマットがなくても便利です(翻訳)

July 21, 2016 blog.arkency.com 原文です。英語の勉強のために興味ある記事を日本語訳しています。間違いあればご指摘ください。(#)は私の補足です。


controllerのactionでHTMLのレンダリングしかしない場合、respond_toを使う理由が少ないと考えられるかもしれません。それは恐らくRails Scaffoldの影響です。

class PostsController < ApplicationController
  def index
    @posts = Post.all
  end
end

しかし、このコードが例外に繋がる非常に厄介な状況が1つあります。それは、クライアントが間違ってあなたのページをXML形式でリクエストしたときです。
試してみてください。

curl -H "Accept: application/xml" localhost:3000/posts

例外が発生します。

Missing template posts/index, ... :formats=>[:xml]

クライアントは、サーバ側に問題あることを示す500エラーを受け取ります。

<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <status>500</status>
  <error>Internal Server Error</error>
</hash>

この問題(# エラー)は、Railsアプリの例外トラッカーによってログに書き出されます。ただし、クライアントがアプリのランダムなページでXMLを取得できると考えている事実に対して、私たちが対応できることは何もありません。私たちはこれが起こっても通知を受け取りません。そしてあなたのWebサイトが大きくなればなるほど、そのようなバカバカしいリクエストが起こります。

しかし、これらのエラーが起こっている事実を完全に無視したいわけじゃない。そのエラーは本当の問題(即ち、リファクタリングのミスなど)を見つけるのに役立つかもしれません。

どうすれば今の状況を修正できますか?対応するフォーマットを示すために、respond_to セクションを追加するだけです。html呼び出すのにブロックを渡す必要さえありません。(# format.htmlの後に引数を渡す必要がないということ)

class PostsController < ApplicationController
  def index
    @posts = Post.all
    respond_to do |format|
      format.html
    end
  end
end

あるいは、respond_to :htmlを使うこもできます。しかし、それだけでは十分ではなく、respond_withを一緒に使う必要があります。

class PostsController < ApplicationController
  respond_to :html

  def index
    @posts = Post.all
    respond_with @posts
  end
end

上記の変更後、サポートされていないフォーマットでアクセスした場合、クライアントは406エラーを受け取ります。

<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <status>406</status>
  <error>Not Acceptable</error>
</hash>

サポートされているMINEタイプ(この例ではHTML)のテンプレートに本当に問題がある場合にのみ、テンプレートにミスがあることを示す500エラーを表示します。

P.S. Post-Rails Way Book Bundleについてお知らせです。55%の割引であなたの開発現場で多いに役立ちます。


わたしの見解

複数のフォーマットの場合のみ respond_toを使うものだと思ってた。確かにscaffoldの影響だなって思う。エラー原因を区別したエラーメッセージを出すためにもrespond_toを使っていこう。