deviseを入れたrailsアプリのscaffoldで生成されるコントローラが少し変わった話


環境

  • ruby 2.1.3
  • rails 4.1.7
  • devise 3.4.1

※いずれも2014/11/7時点で最新安定バージョン

本題

rails g scaffold hoge

したときに、今ままで

# GET /hoges
# GET /hoges.json
def index
  @hoges = Hoge.all
end

みたいに生成されていたコントローラが、

def index
  @hoges = Hoge.all
  respond_with(@hoges)
end

というように生成されるようになっていた。

このまま動かすと、

In order to use respond_with, first you need to declare the formats your controller responds to in the class level.

というように、どのフォーマットで返すか指定しろや〜〜と怒られてしまう。

原因

最近、railsがrespond_withを別メソッドに切り出すようになった余波。
deviseがrespond_with使いて〜ぜ〜ってなったときに、railsの中から消えていたので、respondersというgem呼ぶぜ〜〜ってなって、responders使うための一手間が必要になったみたい。

https://github.com/plataformatec/responders/blob/master/lib/action_controller/respond_with.rb#L190

解決方法

いろいろあるけど、コントローラ内で respond_to :html 宣言すると手っ取り早い。

respond_to do |format|
  format.html
end

とかでも対応できる。

背景

なんでrails4.2からrespond_withさん別gemになったん?
http://stackoverflow.com/questions/25998437/why-is-respond-with-being-removed-from-rails-4-2-into-its-own-gem

DHHさんの考え(https://github.com/rails/rails/pull/12136#issuecomment-50216483)

I'd like to take this opportunity to split respond_with/class-level respond_to into an external plugin. I'm generally not a fan of the code that comes out of using this pattern. It encourages model#to_json and it hides the difference between HTML and API responses in ways that convolute the code.
So how about we split this into a gem for 4.2, with the current behavior, but also with an option to get the new behavior as suggested here through a configuration point.

「respond_withみたいなパターンのコードは好きじゃないから切り出したいなーって思ってた。respond_withはHTMLとAPIのレスポンスの違いを隠しちょるからな。」みたいなことをおっしゃってる。

respond_withについて

ここが分かりやすい。
http://blog.livedoor.jp/sasata299/archives/51804693.html