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

週刊Railsウォッチ: スライド『GraphQLスキーマ設計の勘所』、Turbopackが話題にほか(20230208後編)

こんにちは、hachi8833です。

週刊Railsウォッチについて

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

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

🔗Rails

🔗 evil-seed: productionデータを加工してダンプするツール

evilmartians/evil-seed - GitHub


つっつきボイス:「この間取り上げたEvil Martiansのgem記事(ウォッチ20230131)を現在翻訳していますが、その中で紹介されていたgemです」

参考: Gemfile of dreams: the libraries we use to build Rails apps—Martian Chronicles, Evil Martians’ team blog

「このgemは、本番などの実データが入った環境から一部データを絞り込んだりマスキングしたりして取り出した上でseedデータを作ってくれるというもののようですね」

「seedデータについては、マスタデータくらいなら手で整備するんですが、関連付けを含む複雑なデータ構造、かつ実環境に近いデータを手でメンテナンスするのはかなり大変なんですよ」「たしかに」「単にテーブルのデータをダンプするくらいなら手でスクリプトを書いて使うこともありますが、マスキングとかを考え始めるとこういう高機能なものがあるとうれしいかも👍」

# 同リポジトリより
require 'evil_seed'

EvilSeed.configure do |config|
  # First, you should specify +root models+ and their +constraints+ to limit the number of dumped records:
  # This is like Forum.where(featured: true).all
  config.root('Forum', featured: true) do |root|
    # It's possible to remove some associations from dumping with pattern of association path to exclude
    #
    # Association path is a dot-delimited string of association chain starting from model itself:
    # example: "forum.users.questions"
    root.exclude(/\btracking_pixels\b/, 'forum.popular_questions')

    # It's possible to limit the number of included into dump has_many and has_one records for every association
    # Note that belongs_to records for all not excluded associations are always dumped to keep referential integrity.
    root.limit_associations_size(100)

    # Or for certain association only
    root.limit_associations_size(10, 'forum.questions')
  end

  # Everything you can pass to +where+ method will work as constraints:
  config.root('User', 'created_at > ?', Time.current.beginning_of_day - 1.day)

  # For some system-wide models you may omit constraints to dump all records
  config.root("Role") do |root|
    # Exclude everything
    root.exclude(/.*/)
  end

  # Transformations allows you to change dumped data e. g. to hide sensitive information
  config.customize("User") do |u|
    # Reset password for all users to the same for ease of debugging on developer's machine
    u["encrypted_password"] = encrypt("qwerty")
    # Reset or mutate other attributes at your convenience
    u["metadata"].merge!("foo" => "bar")
    u["created_at"] = Time.current
    # Please note that there you have only hash of record attributes, not the record itself!
  end

  # Anonymization is a handy DSL for transformations allowing you to transform model attributes in declarative fashion
  # Please note that model setters will NOT be called: results of the blocks will be assigned to
  config.anonymize("User") do
    name  { Faker::Name.name }
    email { Faker::Internet.email }
    login { |login| "#{login}-test" }
  end
end
# 同リポジトリより
require 'evil_seed'
EvilSeed.dump('path/to/new_dump.sql')

「ちなみにevil seedという名前の映画や小説やヘビメタバンドがあるようなので、そのあたりになぞらえた名前なのかなと思いました」

参考: Evilseed (Filmation) | Wiki Grayskull | Fandom
参考: ジョアン・ハリス - Wikipedia
参考: Evil Seeds - Heavy Metal Band - Evil Seeds Web

🔗 マイグレーションからモデルにアクセスしないこと(Ruby Weeklyより)


つっつきボイス:「定期的にあがってくる話ですが、以下のComment.find_eachのようにマイグレーションのコードからモデルにアクセスしてはいけません」「これはやっちゃいけないヤツ」

# 同記事より
class MoveCommentsToCommentable < ActiveRecord::Migration
  def change
    create_table :commentable do |t|
      t.references :subject, polymorphic: true
      t.string :message
    end

    # move all article comments
    Comment.find_each do |comment|
      Commentable.create!(subject: comment.article, message: comment.message)
    end

    # remove old table
    drop_table :comments
  end
end

「マイグレーションファイルは(スカッシュでもしない限り)そのまま残るけど、モデルは将来ファイルごと消えたり名前が変わったりする可能性があるのでモデルの呼び出しは当てにできない」「忘れた頃にrails db:migrate:resetを実行したりするとハマりますね」「create_tableした後で初期データを入れたくなったりする気持ちはわかるんですけどね」「このあたりは経験がないとやってしまいそう」

🔗Ruby

🔗 asyncの冒険(Ruby Weeklyより)


つっつきボイス:「Thoughtbotの人がasyncを使おうとして頑張った記事です」「asyncはウォッチでも何度か取り上げたasync gemのことですね↓」「記事では、asyncはコードの変更が少なく済んで非常にスケーラブルだけどドキュメントが少ないとも書かれていますね」

socketry/async - GitHub

# 同記事より
  def generate_content
    5.times.map { |i|
      Async do
        generate_paragraph(i)
      end
    }
    .map(&:wait) # <--- wait after creating all tasks
    .join("\n")
  end

🔗 engtagger: 英文の品詞をタグに分割(Ruby Weeklyより)

yohasebe/engtagger - GitHub


つっつきボイス:「part-of-speechは"品詞"ですね」「英文を<nnp>Alice</nnp> <vbd>chased</vbd>みたいに品詞分解するんですね」「NNPが固有名詞とかVBDが過去形動詞みたいな感じでタグが付くのね」

# 同リポジトリより
require 'engtagger'

# Create a parser object
tgr = EngTagger.new

# Sample text
text = "Alice chased the big fat cat."

# Add part-of-speech tags to text
tagged = tgr.add_tags(text)

#=> "<nnp>Alice</nnp> <vbd>chased</vbd> <det>the</det> <jj>big</jj> <jj>fat</jj><nn>cat</nn> <pp>.</pp>"

「engtaggerは、もともとPerlのLingua::EN::TaggerをRubyに移植したものだそうです↓」

参考: Lingua::EN::Tagger - Part-of-speech tagger for English natural language processing. - metacpan.org

🔗 その他Ruby


つっつきボイス:「Rubyコミッターの柴田さんと遠藤さんを交えた濃厚な対談です」「mameというハンドルネームの由来は割と想像どおりですね」「後編でやっと本編が始まるのもすごい」「Rubyコミッターが現場に来ることで、Rubyになぜこういう要望が寄せられるかという理由を実感できた、なるほど」

「oneshot coverageとは?」「たしかRuby 2.6から入った機能で、1回も実行されていないコードがあるかどうかを測定するもので↓、カバレッジとして欲しい情報ですね」「なるほど」「oneshot coverageはその後強化された覚えがあります」

参考: Ruby 2.6 新機能:本番環境での利用を目指したコードカバレッジ計測機能 - クックパッド開発者ブログ

oneshot coverage とは、各行の実行回数ではなく、各行が 1 回でも実行されたかどうかを計測するコードカバレッジです。コードカバレッジ測定ツールは伝統的に、行ごとの実行回数を数えるものが多いですが、実際の用途としては、未テストの行(実行回数が 0 の行)を探すというのがふつうです。なので、実行回数が取れなくなることにデメリットはほとんどないと思います。
Ruby 2.6 新機能:本番環境での利用を目指したコードカバレッジ計測機能 - クックパッド開発者ブログより

「このあたりの話↓は、この間@tenderloveさんがブログで書いていた"言語とフレームワークとIDEの連携を強化したい"にも通じていそう(ウォッチ20230125)」「今の言語は開発環境まで含めてセットになっていると言ってもいいぐらいですよね」「言語単体だと難しい改良もあるんでしょうね」「最近のRubyのIRBはめちゃくちゃ強力になっていますけどね」「たしかに」

柴田:はい、そうですね。昨今のプログラミング言語界隈の流れというか流行りみたいな部分の話をちょっとしたいんですけど、VS Codeと呼ばれるエディターが割とメインというかメジャーな存在となっていて、VS CodeはTypeScriptであるとか、Go言語であるとか、最近だったらRust言語みたいなもののサポートが非常に豊富なんですよね。
柴田:それもちろんMicrosoftが今すごい投資をしているんですけど、開発者体験という言葉があってデベロッパーエクスペリエンスというんですけど、開発者が何かをしようとした時に「うっ」てつまずかないように、なおかつ、こういうものを書きたいと思った時にスラスラっと書けます、テストも実行できます、不具合があった場所を見つけますみたいなものをできる限り提供していこうというのがどのプログラミング言語でも非常に重要視されています。
【後編】企業所属のRubyコミッター対談! 〜Ruby開発の裏話と今後の取り組み〜 - クックパッド開発者ブログより

Ruby 3.2のIRBに導入された新機能(翻訳)

🔗 設計

🔗 スライド『GraphQLスキーマ設計の勘所』


つっつきボイス:「今日の社内技術トピックで取り上げられていたスライドです」「GraphQLサーバーはgraphql-rubyなどのライブラリを使って実装すると思うんですが、こうしたライブラリを使うと自然と個別のPayloadやInputが作られるようになっています」

rmosolgo/graphql-ruby - GitHub

「これまでは"ライブラリが推奨して勝手に作るからそういうもんだろう"と思っていた箇所について「なぜそのような設計がbetterか」という答えを与えてくれる内容でとても参考になるスライドでした👍」「末尾の参考文献もよさそうですね」

🔗DB

🔗 relationとrelationship


つっつきボイス:「恥ずかしながら、この間『データベース実践入門』という本を読んだときにリレーションとリレーションシップの区別が曖昧だったことに気づきました😅」

「テーブルやビューなどの中にある行のまとまりがrelationで、relationとrelationの関連がrelationshipか」「ER図を書くときとかに、このテーブルとこのテーブルの間のリレーションみたいに書いちゃったりすることならあるかも」「ポイントを外してなければ、それほど大きな誤解にはつながらないような気もしますけどね」「テーブルをわざわざリレーションと呼ぶ人がいるんだろうか?」

「relationという概念にはテーブル以外にやビューやサブクエリなども含まれるので、そこは注意が必要ですね」「たしかに」「設計の話をするときはあまり抽象度を高めたくないので、リレーションよりはテーブルとかビューといった言葉を使うかな」「自分も同じ気持ちです」「強いて言うなら、WITH句やサブクエリで新たな表を組み立てるときとかだったらリレーションと書いてもいいかも」


「技術用語と関係ないんですが、relationとrelationshipの語源をちょっと調べてみました: 現代の日常英語だと、relationは"親戚"とか"血縁関係"あたりを指すことが多いんですが、語源もそうなのかなと思ったらフランス語(ラテン語)由来で、relationの"親戚"みたいな意味は後からついたんだそうです」「defaultみたいに元の英語の意味からだいぶ変わったりする技術用語もありますよね」「近年のrelationshipは、日本語の"肉体関係"みたいなニュアンスでも使われるみたいです」

参考: relation | Etymology, origin and meaning of relation by etymonline
参考: relationship | Etymology, origin and meaning of relationship by etymonline
参考: default | Search Online Etymology Dictionary

🔗クラウド/コンテナ/インフラ/Serverless

🔗 act: GitHub Actionsをローカル実行するツール

nektos/act - GitHub


つっつきボイス:「社内SlackでRailsのCIエラー対応スレッドに貼られていた記事です: GitHub Actionsワークフローをローカル実行するこのactというツールは昨年も取り上げました(ウォッチ20220511)」「actって動くようになるまで悩むことが多いですよね」「自分もGitHub Actionsがエラーを出したときにローカルでactを試してみたんですが、actそのものがまだ動かない状態です😅」「そうそう、結局GitHub Actionsで直接試す方が早かったりして」「actはちょっと試してみたことがありますが、GitHub Actionsとまったく同じ環境にはできないので、それを踏まえたうえで使うことになるでしょうね」

🔗JavaScript

🔗 webpackとTurbopack(Publickeyより)

webpack/webpack - GitHub


つっつきボイス:「webpack、ちょっと前まではトレンドだったのに」「webpackの開発メンバーがVercelに移ってTurbopackというツールをRustで開発しているそうです」「webpackという名前を使い続ける限り後方互換性を保ったままサポートし続けないといけなくなるので、breaking changesをきっかけに別のツールに移行するというのはあってもいいんじゃないかな」「そういえばEvil Martiansは例のgem記事ではViteを使っていると書いていました」

参考: Turbopack - The successor to webpack
参考: Vite | 次世代フロントエンドツール


後編は以上です。

バックナンバー(2023年度第1四半期)

週刊Railsウォッチ: RailsにHealthControllerが追加、Active RecordのNormalizationほか(20230207前編)

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

Ruby Weekly

Publickey

publickey_banner_captured


CONTACT

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