Rails 5.1 の新機能

Rails 5 の新機能おさらいしとこうと思ってググって以下のスライドを見ていたところ
思っていたよりも変更があってショック受けていたら、Rails 5.1 の資料でした。 フライングしちゃった気分だわ。
まだリリースされていないので、ご参考程度に。

Rails 5.1: upcoming features // Speaker Deck

気になるところ

tagが便利になる

New syntax for tag helpers i.e. tag.br instead of tag('br') #25195 by marekkirejczyk · Pull Request #25543 · rails/rails
tag 使ったことなかったですが、content_tag も tag で代用できるようです。
気持ち少し短く書けます。

# before
tag(:br, nil, true)

<%= content_tag :div, class: "strong" do -%>
  Hello world!
<% end -%>


# after
tag.br

<%= tag.div class: "strong" do -%>
  Hello world!
<% end -%>

新しいFormメソッド: form_with

Provide form_with as a new alternative to form_for/form_tag · Issue #25197 · rails/rails
なんと form_for / form_tag に代わる新しいメソッドが用意されるようです。
修正としては大きいですね。
デフォルト remote: true になるだとか。 既存のform_for / form_tag は、5系ではそのまま使えて、Rails6 からはdeprecate warning 対象予定とのこと。

以下のように content が存在しない場合の考慮ができるようです。
check_boxとかselectも簡単にかけるようになる?

# before
<%= form_for(@post) do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :content %>
<% end %>


# after
<%= form_with(model: @post) do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :content, "Overwrite @post.description if present, if not, it will still work" %>
<% end %>

capybara

WIP: Capybara Integration with Rails (AKA System Tests) by eileencodes · Pull Request #26703 · rails/rails
なんとcapybaraがデフォルトで利用できるようです。
setupの必要がなくなるとのこと。 puma/ selenium / chrome / port: 28100 / screen [1400, 1400] で動作し ドライバとしては以下のものが利用できるとのこと。 Capybara drivers: poltergeist, webrick, selenium (with no setup), and rack_test
screenshotとってくれたりするのは良いかも。

Add :fallback_string option to Array#to_sentence

Added :fallback_string option to Array#to_sentence by oss92 · Pull Request #25811 · rails/rails
日本人には馴染みがないかもしれませんが、Array#to_sentence というメソッドがあったようです。私も知りませんでした。

# before

["one", "two", "three"].to_sentence
# => "one, two, and three" なるほど readable

[].to_sentence
# => ""


# after
["one", "two", "three"].to_sentence(fallback_string: "none")
# => "one, two, and three" これは一緒

[].to_sentence(fallback_string: "none")
# => "none"

Railsのエラー画面は動的か静的か

Railsのエラー画面を静的なものにするか動的名ものにするかという話は、よく上がるかと思います。 Assetsを利用したいし、他言語化したいし、エラーコードでメッセージだけ出しわけしたいし、 というので動的エラー画面を選択することがあるかと思います。

ちょっと待って

結論から書くと、いろいろ調べるとできなくはないが、問題が発生しうるケースがあるので 可能であれば、静的で行く方が良いようです。
 
どうしてもという場合は、yuki24/rambulance を使いましょう。
 
そもそも503考慮するなら静的ページ用意しなくちゃならないですしね。

昔話

詳しく知りませんでしたが、3.2ぐらいからRailsの動的エラー画面の生成方法が変わっていたようです。 2.3時代は、rescure_action_in_public を利用していました。 RailsCasts懐かしい。

上記RailsCastsは、Pro(有料)版でrevisedされているようです。
#53 Handling Exceptions (revised) - RailsCasts

githubのソースを見ると、self.routes を突っ込むタイプのようでした。 この方法は、かつて Edge RailsGuides に載っていたらしいのですが(今は載ってない)、 問題があるようです(後述)。

config.exceptions_app = self.routes

動的エラーについて

ググると rescue_from 方式がたくさんヒットします。
確か rescue_from って問題あったんじゃなかったけっと、さらに調べると

yuki24 さんのコメントを見つけました。
qiitaではこの手の話題に対して、いろんなところでフォローしてくれているようでよく見かけました。
Railsの404,500エラーページをカスタマイズ - Qiita

ActionController::RoutingError は ApplicationController に
到達する前に投げられる例外なので、
rescue_from ActionController::RoutingError, ... は期待した通りに動かない
(get '*path', to: ... によって、動いているように見えているだけ)

なるほどそういうことなんですね。

ApplicationController で rescue_from Exception, ... 
すると Airbrake や Bugsnag なんかが動かなくなる。

これはよくわからないので調べます(後述)。

では、どうするのがよいかというと、Rails には config.exceptions_app という設定があり、
ここに Rack mountable なオブジェクトを与えることで動的なエラーページを生成可能になります。
とはいえ、エラーページのためだけにもうひとつ Rack アプリを作るのも面倒なので、
とりあえず ErrorsController というのを作って、lambda で囲って渡しちゃえば動きます。
config.exceptions_app = ->(env) { ErrorsController.action(:show).call(env) }

なるほど、そんなことになってたんですね。

もう少し調べてみる

以下が非常に参考になりました。
Rails の rescue_from で拾えない例外を exceptions_app で処理する - Qiita
rescue_from の問題点、exceptions_app でも完璧ではない点。

Railsアプリの例外ハンドリングとエラーページの表示についてまとめてみた - Qiita
ActionDispatch::PublicExceptions、NewRelic, Airbrake などは Rack Middleware に差し込むタイプのgemなので、使えなくなる。

Railsでエラーページを動的に - Qiita
config.exceptions_app = routes の問題点と rambulance について記載があります。
動的ページの問題を解決するために作成したとのこと。
でも、静的ページを用意するためのあくまでつなぎとして使って欲しいとのこと。

Rails Tutorials 2週目を終えて

第3版となりパワーアップしたのを知ったので
9月中頃からちょっとずつ実施してきた Rails Tutorials ですが
1ヶ月ちょっとで終えることができました(ちょっと掛かりすぎた)。

感想

改めてやってみた感想ですが、Railsやる人なら1回くらいやっといて損はない内容ですね。
書いた人もすごいし、訳した人もすごいわ。
 
時間的には、後半のchapmter のvolumeが少し大きいので、平均すると2時間ぐらい掛かっていたような気がします。
全体のボリュームとしては、1日1時間で約1か月ぐらいのスケジュール感で臨むと良いかもしれません。
 
内容としては、やはりテスト周りの充実度は高くて良いです。
minitestの書き方を知れます。minitestはあまり書いたことがなかったのでとても勉強になりました。
 
当初、herokuの作業は初心者には不要かなと思ったのですが
メール配信したり、fog経由で画像ファイルをs3に保存することが体験できるので
可能であればやっておいた方が良いと思いました。
 
ただ、通常production環境では assets precompile が必要ですが、
herokuでは不要だったりするので、初心者は誤解する可能性があります(そこは躓いて学べば良いだけですが)。
最後に軽めのSQLのチューニングの話がありましたが、eager loading (N+1)の話などもあっても良いかなと 思いましたが、この辺りは次のstepでしょうか。
 
あと、内容とは関係ないですが、
commitの粒度が大きいと感じました。もう少し小分けにcommitすべきかな。
 
また、第3版からCloud9を使うようになったのですが
これ自体は結構使いやすく、これが無料というのはすごいと思いながら触っていました。
windows ユーザなどは良いかもしれません。
最後までCloud9を使いましたが、個人的には若干のレイテンシを感じるので、
環境が容易に整えれる人であれば、local の方が良いかなという印象。