- Ruby / Rails関連
週刊Railsウォッチ(20200907前編)スライド『Rails 6.1で新しく入る機能について』、Railsコミュニティサーベイ、TruffleRubyでZeitwerkが動いたほか
こんにちは、hachi8833です。RubyKaigi Takeout 2020が無事開催されましたね。主催者/登壇者/参加者/スポンサーの皆さまお疲れさまでした!
1日目のライブ動画冒頭に映ったBPS株式会社のスポンサー表示です↓。
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
今回のつっつき会はRubyKaigi Takeout 2020前日ということもあり、つとめて軽くしました。
ところが録画に失敗してしまったため今回はつっつき成分が少なめとなりました🙇。
⚓Rails: 先週の改修(Rails公式ニュースより)
今回は以下のコミットリストのChangelogを中心に見繕いました。
- コミットリスト: Comparing master@{2020-08-29}...@{2020-09-03} · rails/rails
- 6.1マイルストーン: 6.1.0 Milestone -- 26件
⚓where
で関連付け名をjoinしたテーブルのエイリアス名として参照できるようになった
whereでassociation namesがそのまま使えるの便利そう。そして、diffを見ても何も理解できなかった...ActiveRecord難しい...https://t.co/4k4Mz7QQST
— 神速 (@sinsoku_listy) August 30, 2020
テーブルが複数回joinされると、それらのテーブルは最初のテーブルを除いてエイリアスされる。
これは自己参照する関連付けで起きやすく、その場合現在は、where
条件内のエイリアスされたテーブルでカスタム属性(型キャスト)や属性エイリアスの解決を行う方法がない。
この問題を修正するため、where
で関連付け名をテーブルエイリアスとして参照できるようになる。where
の中で関連付け名が参照されると、joinされたテーブルでそれらの名前がエイリアス名として使われる。
同PRより大意
class Comment < ActiveRecord::Base
enum label: [:default, :child]
has_many :children, class_name: "Comment", foreign_key: :parent_id
end
# ... FROM comments LEFT OUTER JOIN comments children ON ... WHERE children.label = 1
Comment.includes(:children).where("children.label": "child")
つっつきボイス:「生SQLを使わずにActive Rcord wayな形でJOINしたテーブルの条件を付与できるようになったのはうれしい」「神速さんと同じくdiff見ただけだとわからない...」「やっぱりActive Recordを知り尽くしている人じゃないと」「修正されたissueを見る方が早いかも↓」
⚓Active Storageの動画ストリームがduration情報に基づいてフォールバックするよう修正
# activestorage/lib/active_storage/analyzer/video_analyzer.rb#L46
def duration
- Float(video_stream["duration"]) if video_stream["duration"]
+ duration = video_stream["duration"] || container["duration"]
+ Float(duration) if duration
end
つっつきボイス:「以下のAPIドキュメントに基づいてduration情報を取れるようにしたみたい」
注: MatroskaやWebMなど、ストリームレベルでdurationを保存しないフォーマットではduration=N/Aとなる。Format (container) durationを参照。
trac.ffmpeg.orgより
⚓changes_applied
の後でdecorateされたtimeオブジェクトが誤って返される問題を修正
# activerecord/lib/active_record/type/time.rb#L3
module ActiveRecord
module Type
class Time < ActiveModel::Type::Time
include Internal::Timezone
class Value < DelegateClass(::Time) # :nodoc:
end
def serialize(value)
case value = super
when ::Time
Value.new(value)
else
value
end
end
+
+ private
+ def cast_value(value)
+ case value = super
+ when Value
+ value.__getobj__
+ else
+ value
+ end
+ end
end
end
end
つっつきボイス:「これは明らかにバグですね」「decorated timeって何でしょう?」「issue↓にあるように、Time
がActiveRecord::Type::Time::Value
になるということだと思います」
- fixed issue: Time attribute changes from Time to ActiveRecord::Type::Time::Value · Issue #36910 · rails/rails
timeオブジェクトはもともと
changes_applied
の後でforgetting_assignment
(value_for_database
)によってデコレートされていた。
def forgetting_assignment
with_value_from_database(value_for_database)
end
def value_for_database
type.serialize(value)
end
#36352までは運良く、
value.change
を呼ぶたびにapply_seconds_precision
がデコレートされない新しいtimeオブジェクトを毎回返していた。
現在はcast_value
でtimeの値がデコレートされているかどうかを明示的にチェックする必要がある。
同PRより大意
「おや、今GitHub画面上でメソッドをマウスオーバーしてGo to definitionをクリックしたらIDEっぽい画面にジャンプしたのが見えましたけど、それは?」「たぶんSourcegraphのChrome拡張が効いたんでしょう↓」「なるほど、後で入れてみます」
参考: Sourcegraph - Chrome Web Store
このChrome拡張いいですね😋。
⚓Railsのrakeタスクが複数回読み込まれないよう修正
#39137ではrakeコマンドを呼び出すたびに新しい
Rake::Application
インスタンスが作成されていた。RailsタスクがRake::Application
ごとに定義されるよう、rails/tasks.rbがインスタンスごとに読み込まれていた。しかしRake::Application#load_rakefile
がアプリケーションのRakefileを読み込み、これがRails.application.load_tasks
を呼び出すのでこのRailsタスクも読み込まれる。あるrakeタスクが複数回定義されていると、タスク実行時にすべての定義ブロックが実行される。つまりRailsのタスクブロックが2回実行された。
このコミットは、二重実行回避のため不要な読み込みを削除する。
同PRより大意
# railties/lib/rails/commands/rake/rake_command.rb#L18
Rake.with_application do |rake|
- load "rails/tasks.rb"
rake.init("rails", [task, *args])
rake.load_rakefile
if Rails.respond_to?(:root)
rake.options.suppress_backtrace_pattern = /\A(?!#{Regexp.quote(Rails.root.to_s)})/
end
rake.standard_exception_handling { rake.top_level }
end
⚓ZeitwerkがTruffleRubyでデフォルトで有効になった
- PR: Enable Zeitwerk by default on TruffleRuby by eregon · Pull Request #40141 · rails/rails
- 関連commit: Move TruffleRuby check to select the autoloading mode to 6.1 defaults · rails/rails@94ba417
つっつきボイス:「TruffeRubyでZeitwerkが動くようになったとは!」「おめでとうございます🎉」
The test suite of Zeitwerk passes on truffleruby-head ✅💪🎉 pic.twitter.com/x3hobJ94Pr
— Xavier Noria (@fxn) August 29, 2020
⚓Rails
⚓スライド: Rails 6.1で新しく入る機能について
つっつきボイス:「@willnetさんがまとめてくれた🎉」「なるほど見やすい」「ありがたいです😂」「既視感ある機能も結構ありますね」「まあうちらは毎週追ってますから😆」
参考までに、スライドで紹介されているRails 6.1の新機能のうち、これまでRailsウォッチの「先週の改修」で追ってきたものを漁ってみました(スライド順)。
- #38848: ビューのHTMLにテンプレート名を含められるようにした
- #39313: Active Recordで署名付きidをサポート
- #37400:
strict_loading
を追加 - #38531: 水平シャーディングのサポートが追加
- #37940: 新機能:
GitHub::Deprecation.disallowed_warnings=
- #37901: 新機能: Active Storage variantをデータベースでトラッキングするようになった
- #32313: RaiilsのActiveModel::Errorで各バリデーションエラーをカプセル化
- #34727: Orphan Recordを検索するメソッド
- #39820: Active Recordの
enum
に_default:
でデフォルト値を設定できるようになった - #18496: Base64のstrict_decode64をurlsafe_decode64に変更
- #39328: 同じカラムをmergeしたときの条件の扱いをRails 6.2で統一
- #39558: 新機能: Active Recordでリレーション名.andをサポート
以下は「先週の改修」で扱ってなかった機能です。ルーティングファイルの分割は話題に出たような覚えがあったのですが...頑張ります。
- Bring back feature that allows loading external route files: by Edouard-chin · Pull Request #37892 · rails/rails
- Active storage add proxying by fleck · Pull Request #34477 · rails/rails
- Add basic support for check constraints to database migrations by fatkodima · Pull Request #31323 · rails/rails
- Support cookie migration in distributed settings. by qnighy · Pull Request #37628 · rails/rails
⚓Railsの低レベルキャッシュをマスターする
# 同記事より
class UpdatePricesJob < ApplicationJob
def perform
Commodity.each { |commodity| commodity.update!(price: <fetch_api_price>) }
end
end
class Commodity < ApplicationRecord
belongs_to :invoice, touch: true
end
class Invoice < ApplicationRecord
has_many :commodities
def total_value
Rails.cache.fetch([self, :total_value]) { commodities.map(&:price).sum }
end
end
見出しより
「キャッシュとは、ある種のコードの結果の保存を意味する一般的な用語」
- 低レベルキャシュとは
- しくみ
- 低レベルキャッシュを使うとき
- キャッシュのキーと期限
- モデルで
touch:
する- 時間ベースの期限設定
- ユースケースの例
- APIからフェッチした商品の「現時点の価格」に依存して大量の計算が発生する
- さまざまなレベルのネステッド集計が発生する
- 注意点
- ビューがボトルネックになるとき
⚓Railsコミュニティサーベイ
“Security should always be a priority and automated security tools will ensure that you can find and fix issues before attackers find you.” Read the community insight by @andrewmcodes about automated security tools at https://t.co/TMbZmI0w7Y#RailsSurvey2020 #rubyonrails pic.twitter.com/q6D2yBJhoF
— Planet Argon (@planetargon) September 4, 2020
つっつきボイス:「この間取り上げようと思って見落としてました」「参加者の国のグラフ↓に日本がない?」「日本はその他に含まれてるみたいです」「やっぱり英語のアンケートに回答する日本人って少ないのかな🤔」
「面白い項目いろいろある」「しかし長いアンケート結果」「たしかに長いですね」「きりがないので次へ〜」
⚓JetBrains IDEにペアプロ機能が入るか
つっつきボイス:「とりあえずペアプロ用機能は入れてみた」「VSCodeのLive Shareっぽくやれるようになるんですね」
参考: 概要 - Visual Studio Live Share - Visual Studio Live Share | Microsoft Docs
⚓その他Rails
#Ruby メッチャ使われてる...!! 😳✨ https://t.co/zBK9fqpF9a
— 安川要平/Yohei Yasukawa (@yasulab) August 28, 2020
つっつきボイス:「ソフトウェアスタートアップ企業トップ50か」「たしかにRuby使ってるところ多い」「あくまで初期のバックエンド言語ということなので今は違う言語を使っているところもあるでしょうけど、立ち上げにRailsを使うのは理にかなっていると思います」「このランキングの基準が時価総額なので、今どきのモダンなアーリーステージの企業はランクインしにくいんですよ」「現時点の初期開発言語はこれだけではわからないということなんですね」「何年かすればまた内訳も変わってくるでしょうし」「1社だけLispのところがある😆」「ホントだ😆」
参考: LISP - Wikipedia
前編は以上です。
バックナンバー(2020年度第3四半期)
週刊Railsウォッチ(20200901後編)RubyKaigi 2020 Takeout登壇者発表、Ruby開発版が2.8から3.0へ、マイクロサービス分割ほか
- 20200831前編 GitHubがRuby 2.7にアップグレード、Durationに変換メソッドが追加、hair_triggerでデータベーストリガほか
- 20200825後編 Rubyクラスライブラリをgem化、Rubyテストフレームワークrr、ChromebookでWindowsが動くほか
- 20200824前編 「Active Jobスタイルガイド」は有用、SiderがGitLabに対応、eager loading時のselectを修正ほか
- 20200818後編 ruby_jardデバッガがスゴい、RubyオンラインマニュアルにEdit機能が追加、Ruby 2.7のBundlerを消す方法ほか
- 20200817前編 お盆も続くRails改修、Rails 6.1にManyモナドが入る?rails-auth gemでクライアント認証ほか
- 20200811山の日短縮版 RSpec Queueでパラレルテスト、カロリーメイトとRubyのコラボ、Rubyのcoercionほか
- 20200804後編 「RubyKaigi Takeout 2020」9月オンライン開催、メールバリデータtruemail、Gitのmasterが変更可能にほか
- 20200803前編 書籍『パーフェクトRuby on Rails』増補改訂版、マルチDBで抽象クラスをscaffold生成、GitLabがPumaに乗り換えほか
- 20200721後編 『パーフェクトRuby on Rails』増補改訂版発売間近、scan_left gemでレイジーなinjectほか
- 20200720前編 10月開催「Kaigi on Rails」CFP募集中、enumにデフォルト値設定機能、RailsでBitemporal Data Modelほか
- 20200714後編 ruby-warning gemでワーニングを手軽に抑制、rubocop -aの振る舞いが変わる、書籍『MySQL徹底入門 第4版』ほか
- 20200713前編 rspec-openapiでスキーマ自動生成、Rails Architect Conf動画、
where()
ハッシュキーに比較演算子条件を書ける機能ほか - 20200707後編 Rubyで無名structリテラル提案、書籍『AWS認定ソリューションアーキテクト』、21世紀のC言語ほか
- 20200706前編 Railsでのマルチテナンシー実装戦略を比較、Railsでサブクエリを使う、URI.parserが非推奨化ほか)
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。