- Ruby / Rails関連
週刊Railsウォッチ(20201020前編)Percona Toolkitは優秀、Active Admin非公式ガイド、Railsをリアクティブにするガイドほか
こんにちは、hachi8833です。
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
- お気づきの点がありましたら@hachi8833までメンションをいただければ確認・対応いたします🙇
※今回録音に失敗したため、つっつきボイスがいつもより短めとなっております🙇。
⚓Rails: 先週の改修(Rails公式ニュースより)
今回の更新は少なめで、Changelogは更新されていませんでした。
- コミットリスト: Comparing @{2020-10-09}...master@{2020-10-15} · rails/rails
- 6.1.0マイルストーン: 6.1.0 Milestone -- 25件オープン
⚓ render_in
に応答するオブジェクトのレンダリングでレイアウトもサポート
#37919で、コントローラ内で
render_in
に応答するオブジェクトのレンダリングサポートが追加されたが、この実装ではレイアウトがサポートされていなかった。
今回の変更では#37919の実装を更新してActionView::Template
と統一し、レイアウトを利用できるようにした。
また、ViewComponentがRailsの一部でないという点を明示するため、「component」という用語を「renderable」にリネームした。
#39869より大意
つっつきボイス:「render_in
か」「これを入れた背景が知りたい」「例のViewComponentからつながる流れかなと思ったら#37919で以下へのリンクを貼っているのでそのようですね↓」「ViewComponentはウォッチでも話題にしましたね(ウォッチ20200330)」
ViewComponentは、React Componentsにインスパイアされたビューレンダリングクラスであり、データを受け取って出力安全なHTMLを返す。PresenterやDecoratorやViewModelパターンの進化系と思えばよい。
コンポーネントは、ビューのコードが再利用されるほとんどの場面で効果を発揮し、直接テストできるというメリットもある。
週刊Railsウォッチ20200330より再録
「この改修はどんなときにいいんでしょうか?」「新しいViewComponentを通したレンダリングを考えると、複数のViewComponentを状況に応じて切り替えるのに使いたいんだと思います」
⚓ DatabaseConfigurations#find_db_config
を安定ソートにした
つっつきボイス:「たしかにconfigの項目順序が変わると思わぬバグやエラーの温床になるかもしれないので怖い」「安定ソートにRubyのwith_index
を使っていますね↓」
# activerecord/lib/active_record/database_configurations.rb#L81
def find_db_config(env)
configurations
- .sort_by { |db_config| db_config.for_current_env? ? 0 : 1 }
+ .sort_by.with_index { |db_config, i| db_config.for_current_env? ? [0, i] : [1, i] }
.find do |db_config|
db_config.env_name == env.to_s ||
(db_config.for_current_env? && db_config.name == env.to_s)
end
end
- Rubyドキュメント:
Enumerator#with_index
(Ruby 2.7.0 リファレンスマニュアル)
⚓ ActiveSupport::Cache
でカスタムキャッシュエンコーダーを設定できるようになった
Rails api: ActiveSupport::Cache
背景
自分たちは現在https://github.com/Shopify/memcached_storeを使っているが、中期的にdalliベースがデフォルトの
MemCacheStore
に移行したいと思っている。カスタムキャッシュエンコーダーを設定できる機能が現在ないので欲しい。
何らかの形でMemCacheStore
内の圧縮を無効にしてからdalliクライアントにカスタムエンコーダーを渡せば一応やれるが非常にアドホックだし、RedisStoreを使おうとするとどちらもできない。
このあたりを調べてみていくつかわかったことがある:
- 最小エントリのオーバーヘッド
Marshal.dump(ActiveSupport::Cache::Entry.new("")).bytesize # => 107
の無駄が大きい。これを大きく削減して圧縮フラグをたとえば1バイトにまで減らせる。MemCacheStore
をデフォルト設定で使うと、ZLib.deflate(Marshal.Dump(Entry.new(ZLib.deflate(Marshal.dump(actual_value)))))
と値が何度もシリアライズおよび圧縮され、無駄な計算が行われている。- issue #9494を見つけて読んでみたところ数年前にも同様の改良が試みられていたらしいが、前方および後方互換性維持のため取り消されていた。
提案
このプルリクは最初の一歩にすぎない。自分の関心は用途に特化した極めて高効率のエンコーダーを利用できるようにすることだが、
Entry
エンコーディングメカニズムが置き換え可能になればより新しく効率の高いシリアライゼーション形式をすべてのユーザー向けにロールアウトしやすくなるだろうと思った。
以下のような3つのステップになるだろう。
- 次バージョンのリリースでは新旧フォーマットをどちらも読める(が旧フォーマットで書き込む)デフォルトのコーダーをリリースし、互換性を維持する。
- 新しく作成されるアプリは最適化済みの新しいフォーマットでのみ読み書きできるよう設定される。
- キャッシュをフラッシュせずにアプリを移行したい場合は、第三の設定を用いて旧フォーマットで読み、新フォーマットで書き込む。
同PRより大意
つっつきボイス:「Shopifyからのプルリクです」「エンコーダーを差し替えできるようにすることでキャッシュを飛ばさずにCache Storeのエンジンを切り替えたいということでしょうね: キャッシュヒット率の高いアプリだったり、事前に生成したキャッシュを積極的に使うようなアプリの場合、キャッシュをいきなり全飛ばしするとサイトが落ちる可能性があるので」「なるほど」
参考: 3 キャッシュのキー -- Rails のキャッシュ機構 - Railsガイド
「上の3つのステップで互換性を維持しつつキャッシュエンコーダーを段階的に移行すると」「そういえばRailsの今のMemCacheStore
はデフォルトでdalliベースになっていますね」
参考: 8.7 Action Pack -- Rails アップグレードガイド - Railsガイド
Rails 4.0のデフォルトのmemcachedクライアントがmemcache-clientからdalliに変更されました。アップグレードするには、単にgem 'dalli'をGemfileに追加します。
Railsガイドより
⚓ WIP: 高粒度なロールやシャーディングスワップを実装
- PR: Implement granular role and shard swapping by eileencodes · Pull Request #40370 · rails/rails -- 現在オープン中
これは6.1.0マイルストーン経由で見つけました。
つっつきボイス:「まだマージされていませんけど」「以下の上の図が従来で、下の図が提案だそうです」「ソシャゲのようにシャーディングが非常にうまく機能する世界だと上の図のような構成がよくありますね」
「プルリクの文章長いですね...」「マルチデータベースのシャーディングはまだproductionでやったことがないのでちゃんと読まないといけないと思いますが、見た感じでは従来だとreadとwriteでConnectionHandlerが別だったのを、ひとつのConnectionHandlerにしてその中でreadとwriteを切り替えるということらしい」「readとwriteが一つのtransactionなり一連のフローの中で使われるときに、異なるConnectionHandlerに分かれているよりも一つのConnectionHandlerにまとまっている方が扱いやすいということでしょうね」
「ConnectionHandlerが一つにまとまると、まさにこのサンプルコードのようにコンテキストを共有できますね↓」「role: :writing, shard: :one
やrole: :writing, shard: :two
を指定してる」「こうやって入れ子にしたときにたとえばDog.first
が1回目と2回目で読み出し元が変わるのか」
# 同PRより
ActiveRecord::Base.connected_to(role: :reading) do
User.first # reads from default replica
Dog.first # reads from default replica
AnimalsRecord.connected_to(role: :writing, shard: :one) do
User.first # reads from default replica
Dog.first # reads from shard one primary
end
User.first # reads from default replica
Dog.first # reads from default replica
ApplicationRecord.connected_to(role: :writing, shard: :two) do
User.first # reads from shard two primary
Dog.first # reads from default replica
end
end
⚓Rails
⚓ Active Admin非公式ガイド(Ruby Weeklyより)
つっつきボイス:「元記事冒頭に、Active Adminが合うのは15分で構築するブログぐらいなのはわかっているけど他にも機能があるよと書かれていました」「Active Adminは、もし入れるなら極力カスタマイズしないて欲しいですね、せいぜいカラムのオンオフぐらいに留める感じで」
「Active Adminは短期間で開発する小規模プロジェクトなら向いていると思いますが、カスタマイズすればするほどconcernsやら何やらで深みにハマっていく傾向があるんですよね」「ちなみにこの間管理画面が必要になったときにActive Admin入れました」「最近は画面づくりをフロントエンド側でやることが増えてきているので、Railsは基本的にAPIに徹するのがいいのかもしれないという気持ちがちょっとありますね」「それわかります」「Active Adminはそういう部分を理解したうえで導入するのが大事」
参考: 2020 Ruby on Rails Community Survey Results | 2020 Ruby on Rails Community Survey Results
「なお元記事は上のアンケート↑のfrustrated gem top 10にActive Adminが入っていたのをきっかけに書いたそうです↓」「同じtop 10にRailsも入ってる😆」「RuboCopが入っているのはちょっとわかる気がする」「RuboCopは素の設定が厳し目なので、ある程度設定を案件に合わせてカスタマイズしてから使うのが常道ですね」
⚓ Railsをリアクティブにするガイド(Ruby Weeklyより)
obie/guide-to-reactive-rails: A comprehensive guide to online resources about "Reactive" Ruby on Rails development https://t.co/ZrQYVgPO0I
— Yukihiro Matsumoto (@yukihiro_matz) October 16, 2020
つっつきボイス:「この記事ではRailsアプリをインタラクティブにするための最新情報をまとめてくれています」「少人数で開発できるなら、記事にもあるAction CableとTurbolinksとStimulusというRails wayでやるのが定番でしょうね」「なおReactive Railsという言葉はこの記事で独自にそう呼んでいるみたいです」「フロントエンド界隈の技術スタックをなるべく使わずに、Rails Wayを主体としたフロントエンド実装でやりたいのであればこの記事を参考にするとよさそう👍」
⚓ Departure: MySQLをダウンタイムゼロでマイグレーション(Ruby Weeklyより)
つっつきボイス:「このDepartureというgemは以前Percona Migratorという名前だったそうです」「この中身はPercona Toolkitのpt-online-schema-change
を呼び出しているのね」
# 同リポジトリより
$ PERCONA_ARGS='--chunk-time=1 --critical-load Threads_running=55' bundle exec rake db:migrate:up VERSION=xxx
⚓ Percona Toolkitは優秀
「Percona Toolkitは昔からありますけど、とてもいいですよ」「え、そんなにいいんですか?」「自分はMySQLのチューニングするときにまずこれを入れますし、これなしではチューニングする気にならないほどです」「うう、MySQL派なのにPercona Toolkit知らなかったとは😅」
参考: MySQL Tools and Management Software to Perform System Tasks by Percona
「たとえば以下の記事↓でも紹介されていますけど、Percona Toolkitを使うと普通なら別々の項目になってしまうN+1クエリのログをグループ化して見つけやすくできます」「おぉ〜!」「MySQLデフォルトのslow_logは『1回の実行で遅いクエリ』は取れるけど『アプリケーションの1リクエスト中で何度も呼び出されてその合計時間が遅いクエリ』は取れません: pt-query-digestは、そういったN+1的な単体ではそこまで遅くないけど大量に呼び出されると全体のパフォーマンスに影響を与えるようなクエリを特定することができます」
参考: スローログの集計に便利な「pt-query-digest」を使ってみよう | Think IT(シンクイット)
後でPercona Toolkitは以前Maatkitという名前だったと教わりました。
以下はつっつき後に見つけた昨年のPercona公式ツイートです。
Percona announces the release of Percona Toolkit 3.1.0, a collection of advanced open-source command-line tools engineered to perform a variety of #MySQL, #MongoDB, #PostgreSQL, and system tasks often too complex to perform manually. https://t.co/O7p4KBTSnK #opensource #Percona pic.twitter.com/05ppTi1KJf
— Percona (@Percona) September 17, 2019
⚓ その他Rails
- 元記事: Everything You Ever Wanted To Know About View Caching In Rails - Honeybadger Developer Blog(Ruby Weeklyより)
2020年10月03日 に開催された Kaigi on Rails のアーカイブ動画を、本日から毎日公開してまいります。
当日参加できなかった方や、振り返りをされたい方はぜひご視聴ください!#kaigionrails— Kaigi on Rails (@kaigionrails) October 14, 2020
つっつきボイス:「RubyKaigi Takeout 2020Kaigi on Railsの動画が順次公開されててYouTubeに通知が表示されてますね」「運営の仕事は大変」「皆さまお疲れさまです!」
YouTubeチャンネル: (6) RubyKaigi - YouTube
2020/10/21: ご指摘をいただき上記誤記を訂正いたしました。両イベント関係者にお詫び申し上げます🙇🙇。
"DHH: First of all, our approach to software development is heavily inspired by the Agile Manifesto and the Agile values. It is not so much inspired by the Agile practices as they exist today." https://t.co/Hp8FAZqQsZ
— yomoyomo (@yomoyomo) October 14, 2020
- サイト: アジャイルソフトウェア開発宣言
つっつきボイス:「上のアジャイルソフトウェア開発宣言↑をこのツイートで初めて知りました」「DHHはアジャイルの具体的なプラクティスよりマニフェストから受けた影響の方が大きかったんですね」「DHHがこう言うのは何だかとてもわかる: こういう技術の思想的哲学的な部分って、最初のうちはなかなかわからないけど、読んだ後に何年か経ってからある日突然『そうか!』って腑に落ちたりしますよね」「それたしかに!」「先週話題になって買ったClean Agileも自分にとってそういう本かもしれないと思いました↓」
参考: Clean Agile 基本に立ち戻れ【委託】 - 達人出版会
「でもその本を他の人にすすめても、同じポイントで感動してもらえるとは限らないということもよくあります」「まさに」「経験上そういう本が相手に刺さることってなかなかない気がしました」「本って本当に出会いとしか言いようがないですね」「出会わなかったらそれまでですよね」「そういう出会いの機会を増やすという意味でも多読や速読は有用だなって思いました」「自分に合う本に出会うまで乱読して数をこなすのも一つの方法かなと思います」
以下はつっつき後に見つけたツィートです。
【Clean Agile 基本に立ち戻れ/Robert C.Martin】アジャイルの哲学書。本来のアジャイルがなんであったか?
それは小さなチームの小さな問題を解決するアイデア。大きなことは小… → https://t.co/wH32ne0MqW #bookmeter— monotony (@monotony84) October 18, 2020
前編は以上です。
バックナンバー(2020年度第4四半期)
週刊Railsウォッチ(20201013後編)ruby-type-profilerがtypeprofにリネーム、AWS API Gatewayの実行ログは便利、M5Stackほか
- 20201012前編 Railsの隠し機能routing visualizer、action_args gem、N+1用goldiloader gemほか
- 20201006後編 Rubyの
defined?
キーワード、Ractorベースのジョブスケジューラ、Caddy Webサーバーほか - 20201005前編 Ruby 2.7.2がリリース、Shopifyのモジュラー化gem「packwerk」、stimulus_reflexほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。