Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

週刊Railsウォッチ: Rails 7リリース、5.2系と6.0.x系のサポート終了時期決定、localhost gemで自己署名証明書生成ほか(20211221前編)

こんにちは、hachi8833です。今年最後の週刊Railsウォッチ前編をお送りします。

週刊Railsウォッチについて

  • 各記事冒頭には🔗でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • お気づきの点がありましたら@hachi8833までメンションをいただければ確認・対応いたします🙏

TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)

🔗Rails: 先週の改修(Rails公式ニュースより)

今回はRails 7に最近マージされたプルリクから見繕いました。

🔗 URL安全でないCSRFトークンを非推奨化

このプルリクでは、urlsafe_csrf_tokensをtrueにする設定も非推奨化されるので、Rails 7.1ではこの設定を完全に除去可能。
概要
#39076の続き。Rails 7.0でこの設定オプションを非推奨化する。次のマイナーリリースでこのオプションを削除できるようにする。
その他の情報
これはRails 7.0.0で出す必要はないが、7.1で設定を削除できるようマイナーリリースの間に非推奨にしておきたいので、7-0-stableで出すべき。mainブランチへのプルリクは7.1用になるはずなので、7-0-stableに対して行うことにする。
同PRより


つっつきボイス:「これまでデフォルトでfalseだったurlsafe_csrf_tokensを、デフォルトでtrueにしつつ、今後オフにできなくなるwarningを出すようになった」「こんな設定があるんですね」「URL-safeは、URLとして利用してよい文字だけで構成されているという意味か」「この設定はfalseにできなくなるようですね: あえてURL安全でないCSRFトークンを使うことはないと思うので大丈夫そう」

# actionpack/lib/action_controller/metal/request_forgery_protection.rb#L95
-     self.urlsafe_csrf_tokens = false
+     self.urlsafe_csrf_tokens = true
+
+     singleton_class.redefine_method(:urlsafe_csrf_tokens=) do |urlsafe_csrf_tokens|
+       if urlsafe_csrf_tokens
+         ActiveSupport::Deprecation.warn("URL-safe CSRF tokens are now the default. Use 6.1 defaults or above.")
+       else
+         ActiveSupport::Deprecation.warn("Non-URL-safe CSRF tokens are deprecated. Use 6.1 defaults or above.")
+       end
+       config.urlsafe_csrf_tokens = urlsafe_csrf_tokens
+     end

🔗 エンコーディングが無効なSQLクエリの扱いを改善

  • エンコーディングが無効なSQLクエリの扱いを改善
Post.create(name: "broken \xC8 UTF-8")

上は、書き込みクエリを検出するコードですべてのアダプタが制御不能な方法で失敗する。
このクエリがデータベースコネクションに適切に渡されるようになり、データベースコネクションで処理可能かどうかにかかわらず、より適切な方法で成功または失敗するようになる。
Jean Boussier
同PRより


つっつきボイス:「\xC8はいかにも無効なUTF-8コードですね」「そういう文字がクエリに混入したときに適切に扱われるようになったのね」

参考: UTF-8 - Wikipedia

「改修で正規表現に追加されたnオプションって何だろう?」「Rubyのドキュメントを見るとASCII-8bitエンコーディングにするオプションとありますね」「理屈はよくわからないけど、無効なUTF-8文字の検出用にここだけエンコーディングを変えてるのかな?」「通常のコードでは影響はなさそうですね」

# activerecord/lib/active_record/connection_adapters/abstract_adapter.rb#L68
      def self.build_read_query_regexp(*parts) # :nodoc:
        parts += DEFAULT_READ_QUERY
        parts = parts.map { |part| /#{part}/i }
-       /\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
+       /\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/n
      end

参考: 正規表現 (Ruby 3.0.0 リファレンスマニュアル)

🔗 Rails 7.0でbutton_toヘルパーの挙動変更を明記


つっつきボイス:「お、これは先週話題にしたbutton_to周りの変更の話ですね(ウォッチ20211214)」「リリースノートとアップグレードガイドで明記したそうです」「お〜、button_to("Do a POST", [:do_post_action, Workshop.find(1)])のようにbutton_toの第2引数にオブジェクトを配列で渡すとPATCHメソッドとして扱ってくれるようになっていたんですね(#43413)、これは賢い👍」

# guides/source/7_0_release_notes.md#L91
+*  `button_to` infers HTTP verb [method] from an Active Record object if object is used to build URL
+
+   ```ruby
+   button_to("Do a POST", [:do_post_action, Workshop.find(1)])
+   # Before
+   #=>   <input type="hidden" name="_method" value="post" autocomplete="off" />
+   # After
+   #=>   <input type="hidden" name="_method" value="patch" autocomplete="off" />

なお、Railsアップグレードガイド↓には反映済みです。

参考: 2.1 ActionView::Helpers::UrlHelper#button_toの振る舞いが変更された
— Rails アップグレードガイド - Railsガイド

Rails 7.0以降のbutton_toは、ボタンURLをビルドするのに使われるActive Recordオブジェクトが永続化されている場合は、patch HTTP verbを用いるformタグをレンダリングします。現在の振る舞いを維持するには、以下のように明示的にmethod:オプションを渡します。

-button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)])
+button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)], method: :post)

または、以下のようにURLをビルドするヘルパーを使います。

-button_to("Do a POST", [:my_custom_post_action_on_workshop, Workshop.find(1)])
+button_to("Do a POST", my_custom_post_action_on_workshop_workshop_path(Workshop.find(1)))

Railsアップグレードガイドより

🔗 Railsメンテナンスポリシーの変更


つっつきボイス:「ガイドのメンテナンスポリシーも更新されました」「お、これは大事なヤツ: Slackにメモしておこう」「Rails 5.2系は来年2022年6月1日でサポート終了なのか〜」「公式なサポート終了時期を事前に宣言してくれるのはありがたい👍」

# guides/source/maintenance_policy.md#L67
-**Currently included series:** `7.0.Z`, `6.1.Z`, `5.2.Z`.
+**Currently included series:** `7.0.Z`, `6.1.Z`.
...
+ NOTE: Rails 5.2.Z is included in the list of supported series until June 1st 2022.
+ NOTE: Rails 6.0.Z is included in the list of supported series until June 1st 2023.

🔗 ファビコンから”shortcut”リンク種別を削除


つっつきボイス:「実はこのプルリクは私が投げたものが7.0に滑り込みでマージされました😊」「お〜ついにRailsコントリビュータじゃないですか」「ファビコンに”shortcut”リンク種別をつける仕様がこんな昔になくなっていたとはね〜」「以下の翻訳記事↓を読み返していて、ふとRails 7ではどうなっているんだろうと思って調べたら、rails newで生成されるfavicon_link_tagで”shortcut”リンク種別が付けられていて、類似のプルリクもなかったので、ドキドキしながらプルリク投げました」

2021年のファビコンを極める: 本当に必要なファイルはほぼ6つ(翻訳)

icon より以前はリンク種別 shortcut がよく使用されていましたが、これは非準拠で無視されますのでウェブ作者は今後使用してはいけません。
リンク種別 - HTML: HyperText Markup Language | MDNより

「根拠がはっきりしているプルリクなのでマージしやすいですね👍」「Rails 7リリース直前の慌ただしいときのプルリクでしたが、押し流されなくてよかった😂」

🔗Rails

🔗 Rails 7.0.0

Rails 7.0.0がリリースされました


つっつきボイス:「Rails 7出ましたね🎉」「予想より早く出た🎊」「記事のRails 7 Gemfileを見ると、propshaftが入るかと思ったらsprocketsがデフォルトなんですね」「propshaftがデフォルトになる説もありましたがsprocketsになりました」「rails new-a propshaftを指定すれば入れられるのね」

rails/propshaft - GitHub

「その代わりimportmap-railsがデフォルトになって、yarnはデフォルトでは入らなくなった」「これを待っていました: rails newも速くなりました」「つまりnodejsもnode_modulesディレクトリもデフォルトでは不要になった、なるほどこれは脱Webpackerせねば」「rails newするときのnodeのバージョンを気にしなくてよくなったのは嬉しい👍」

rails/importmap-rails - GitHub

🔗 Rails 7リリース直前のセキュリティ修正

Railsセキュリティ修正6.0.4.4/6.1.4.4がリリースされました


つっつきボイス:「記事の注にも書きましたが↓、セキュリティ修正でdev環境のアクセスに問題が起きて修正のために再々リリースされたという流れでした」「最終的に修正されてよかった😊」「最初のセキュリティ修正と次の修正を手元で反映したら動かなかったので、issueプルリクをチェックして再々リリースを待ってから記事を出しました」「config.hosts << '.EXAMPLE.com'を環境変数で設定していたりすると見落としそう」

当初は6.0.4.2/6.1.4.2/7.0.0.rc2がリリースされましたが、localhost:3000でアクセスできない問題(#43865)があったので6.0.4.3/6.1.4.3/7.0.0.rc3がリリースされました。しかしlvh.me:3000のようにポート番号を指定できない問題(#43864)があったので、最終的に6.0.4.4/6.1.4.4がリリースされました。
同記事より

🔗 wicked: Railsでウィザードを作るgem(Ruby Weeklyより)

zombocom/wicked - GitHub

参考: Wizard-ify Your Rails Controllers with Wicked


つっつきボイス:「Railsでいわゆるウィザード的なインターフェイスを構築するのに使うgemだそうです」「ウィザード風のUIを構築するgemは他にもありますね」「欲しい人は多いでしょうね」「ウィザード風に作ろうとするとRails wayから外れてしまいがちなんですよ」

参考: ウィザード (ソフトウェア) - Wikipedia

「こうやってステップを書いてビューを切り替えていく感じなのはなかなかよさそう↓」

# 同リポジトリより
class AfterSignupController < ApplicationController
  include Wicked::Wizard

  steps :confirm_password, :confirm_profile, :find_friends

  def update
    @user = current_user
    case step
    when :confirm_password
      @user.update_attributes(user_params)
    end
    sign_in(@user, bypass: true) # needed for devise
    render_wizard @user
  end

  private
  def user_params
    params.require(:user)
          .permit(:email, :current_password) # ...
  end
end
app/
  views/
    controller_name/
      first.html.erb
      second.html.erb
      # ...

「途中で画像ファイルを添付したりしてもうまく扱えるかな?」「それ面倒そうですね」「ステップバイステップのウィザードの実装はそういう部分が大変なんですよ: テキストならhiddenフィールドに埋めたりできますけど、途中にファイル添付が入ると急に難易度が上がるし、途中でパスワードをhiddenフィールドに入れ直すのも避けたい」

「しかしwicked(邪悪な)とはすごい名前」「魔法使いを形容するのによく使われる言葉だからでしょうね」


オズの魔法使いに登場する「西の悪い魔女」がWicked Witch of the Westだったり、レイ・ブラッドベリのファンタジー小説「何かが道をやってくる」の原題が「Something Wicked This Way Comes」だったのを思い出します。

参考: オズの魔法使い - Wikipedia
参考: Something Wicked This Way Comes (novel) - Wikipedia

🔗 spyke: her gemの改良版(Ruby Weeklyより)

balvig/spyke - GitHub


つっつきボイス:「spykeは、ウォッチで何度か話題になったher gemのオルタナだそうです(ウォッチ20211108)」「たしかに、このコンフィグでアダプタやパーサーを指定しているあたりがherっぽい↓」

# 同リポジトリより
# config/initializers/spyke.rb

class JSONParser < Faraday::Response::Middleware
  def parse(body)
    json = MultiJson.load(body, symbolize_keys: true)
    {
      data: json[:result],
      metadata: json[:extra],
      errors: json[:errors]
    }
  end
end

Spyke::Base.connection = Faraday.new(url: 'http://api.com') do |c|
  c.request   :json
  c.use       JSONParser
  c.adapter   Faraday.default_adapter
end

remi/her - GitHub

「spykeのREADMEによると、herはいいgemだけど新しくないのとパフォーマンスに難があるのでspykeを作ったそうです」「あとherはプログラムの構成上なのか、サイズが割と大きいですね」「herの最初のリリースを見てみたら2013年頃からあるみたい」「その頃からherを使ってたな〜」

🔗 localhost: pumaですぐ使える自己署名証明書gem

socketry/localhost - GitHub


つっつきボイス:「今日のWebチーム内発表で話題になっていたgemです」「これは何ですか?」「このgemだけでローカル開発環境にSSL/TLSアクセスを簡単に組み込めます」「へ〜!」

参考: 自己署名証明書 - Wikipedia

「最近はローカル環境でもhttpsでリッスンしないと動かせないようなコードが増えてきていて、特にブラウザのAPIによってはGPSの現在地取得のようにhttpだとアクセスできないものもあったりするので、そういうのをローカルで検証するときに便利」「なるほど」

参考: Webブラウザで現在地情報を正しく取得できない場合の原因と対策:Tech TIPS - @IT

「localhost gemの実装はシンプルですが、pumaでも公式にサポートされているのがポイント高い↓」「手順までちゃんとREADMEに書かれてるんですね」

puma/puma - GitHub

「ローカルでhttps接続するときに大変なのは自己署名証明書を作る部分: 証明書に署名するために自分用の認証局を作らないといけないし、CSR(Certificate Signing Request)を埋めるためにcommon nameなども入力する必要があるとか、作業が多いんですよ」「あ〜たしかに」「こういう自動化ができるとありがたい」

「そういう作業をopensslコマンド手打ちでやるのは大変すぎるので、一般にはubuntuなどのパッケージにも入っているmkcertというツールを使ってやることが多いですね↓」「mkcert使ったことあったかも」「mkcertは証明書をデフォルトでユーザーのホームディレクトリの下に保存するといった細かいところがよくできている」「そういうの大事ですよね」

FiloSottile/mkcert - GitHub

「ちなみにlocalhost gemは鍵ファイルの作成が不要で、証明書を実行時に動的に作ってくれるのでさらに便利👍」「お〜」


前編は以上です。

バックナンバー(2021年度第4四半期)

週刊Railsウォッチ: RailsでGDPRに対応する、stateful_enum gem、rubyzip 3.0ほか(20211214前編)

今週の主なニュースソース

ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。

Rails公式ニュース

Ruby Weekly


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。