- Ruby / Rails関連
週刊Railsウォッチ(20200811山の日短縮版)RSpec Queueでパラレルテスト、カロリーメイトとRubyのコラボ、Rubyのcoercionほか
こんにちは、hachi8833です。昨日は山の日ということで短縮版でお送りします。
回答しそびれましたが、Ruby 2.7のirbがとてもよくなったので自分も最近pryを使わなくなってました。
Rubyプログラマのみなさんにアンケート!REPL(対話型インタプリタ)はirbとpry、どっちを使ってますか!?何か強いこだわりがあればコメントも一緒にお願いします!
— Junichi Ito (伊藤淳一) (@jnchito) August 8, 2020
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
⚓Rails: 先週の改修(Rails公式ニュースより)
今回はchangelogの更新はありませんでした。
⚓validates_inclusion_of
メソッドにeach_object:
オプションを追加
- PR: Validate inclusion of each object in an array by KevinSjoberg · Pull Request #22610 · rails/rails
特定の属性に対応する値が配列の場合、バリデーションでは指定のメンバーにその配列が含まれているかどうかをチェックする。
:each_object
を使うと配列内の各オブジェクトが指定のメンバの中になければならないということを指定できる。
これは、たとえばデータベースカラムでarray: true
オプションを使っていて、指定の有効な値リストが配列のメンバーに含まれているかどうかを指定したい場合に有用。
変更前:features
属性が["Bluetooth"]
を含む配列の場合、以下のバリデーションは失敗する(["IR", "Bluetooth", "Wireless"].include?(["Bluetooth"])
がfalseになるので)。
validates_inclusion_of :features, in: %w(IR Bluetooth Wireless)
変更後: 以下はパスする(
features
の各オブジェクトが指定のメンバーに含まれているかどうかが実際にチェックされるので)。
validates_inclusion_of :features, in: %w(IR Bluetooth Wireless), each_object: true
Railsに初めて投げたプルリクにつき、フィードバックは大歓迎です。
同PRより大意
つっつきボイス:「だいぶ昔のプルリクがマージされていました」「2015年って書いてますけど互換性とか大丈夫だったのかしら?」「さすがにgit rebase
とかやってるでしょうけど」
「validates_inclusion_of
っていう書き方がそもそも古いですし: Rails 3ぐらいじゃなかったっけ?」「あ、もっと簡潔な書き方があるんですね」「もう随分前からvalidates :age, inclusion:
みたいに書くのが普通です」「道理でvalidates_inclusion_of
って見覚えないと思った😆」
- API:
validates_inclusion_of
-- ActiveModel::Validations::HelperMethods - API:
validates
-- ActiveModel::Validations::ClassMethods
# api.rubyonrails.orgより
validates :terms, acceptance: true
validates :password, confirmation: true
validates :username, exclusion: { in: %w(admin superuser) }
validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, on: :create }
validates :age, inclusion: { in: 0..9 }
validates :first_name, length: { maximum: 30 }
validates :age, numericality: true
validates :username, presence: true
「このプルリクは、今までだと:features
がstringならうまくいくんですけど、array of stringだと期待どおりに動かなかったのをeach_object: true
を指定することで動くようにしたということでしょうね」
# 変更前
validates_inclusion_of :features, in: %w(IR Bluetooth Wireless)
# 変更後
validates_inclusion_of :features, in: %w(IR Bluetooth Wireless), each_object: true
「それにしても5年越しのマージとは」「こんなに塩漬けにされてたのって何でだろ?」「改善内容はわかるけど、たぶんこれで困る人が少なかったからじゃないですかね」「必要なものなら色んな人が推すでしょうし」「これなら自分でバリデーター作れるでしょうし」「コメント見ると年に1度ぐらいレスやstale
タグが付けられてますね」「七夕みたい💫」「そして4日前にマージされたと」「初プルリクがついにマージ、お疲れさまです...」「これでRailsのプルリクも1個減りましたね」
⚓マルチプルDBのdb:migrate:redo
で名前を指定できるようになった
» bin/rails db:migrate:redo:secondary
== 20200728162820 CreateAnimals: reverting ====================================
-- drop_table(:animals)
-> 0.0025s
== 20200728162820 CreateAnimals: reverted (0.0047s) ===========================
== 20200728162820 CreateAnimals: migrating ====================================
-- create_table(:animals)
-> 0.0028s
== 20200728162820 CreateAnimals: migrated (0.0029s) ===========================
つっつきボイス:「ああマルチプルDBのdb:migrate:redo
ね」「これは?」「マルチプルDBのrakeタスクは指定先データベースの識別子を渡せるようになっているんですけど、redo
で対応していなかったのを対応したんでしょうね」「redo
の対応が漏れてたのか」
「db:migrate:redo
を開発で使う機会ってめったにないと思いません?」「自分もないな〜」「もちろん機能としては前からありますし、CIで使いたいときもありそうですけどね」
⚓StiClass.all
で暗黙のcreate_with
を回避するようにした
現在は暗黙の
create_with
を使っても使わなくても、ensure_proper_type
によってsti_name
が設定されている。
def initialize_internals_callback
super
ensure_proper_type
end
# Sets the attribute used for single table inheritance to this class name if this is not the
# ActiveRecord::Base descendant.
# Considering the hierarchy Reply < Message < ActiveRecord::Base, this makes it possible to
# do Reply.new without having to set <tt>Reply[Reply.inheritance_column] = "Reply"</tt> yourself.
# No such attribute would be set for objects of the Message class in that example.
def ensure_proper_type
klass = self.class
if klass.finder_needs_type_condition?
_write_attribute(klass.inheritance_column, klass.sti_name)
end
end
create_with
はtype_condition
を抑制したりオーバーライドするのが目的。type_condition
はscope_for_create
ですべてのSTIサブクラス名の配列になるので、scope_for_create
では望ましい振る舞いにならず、find_sti_class
が失敗する。
この想定外の振る舞いは、ArelのIn
ノードが誤ってEquality
ノードのサブクラスになっていたことによる。私見ではほぼバグと思われるが、この振る舞いに依存している人もいる(#39288も参照)。
残念ながらこの暗黙のcreate_with
には、or
がSTIサブクラスのリレーションで失敗するという不本意な副作用があった(#39956)。
今回の変更は、type_condition
を抑制したりオーバーライドする方法が変わる。#39956のor
の問題を修正するため、暗黙のcreate_with
は、scope_for_create
のtype_condition
で除外される。
同PRより大意
つっつきボイス:「@kamipoさんによるArel周りの修正です」「Arel難しくて黙り込んでしまう自分😅」「説明にも書いてある#39956の問題↓を解決するためのプルリクなのでこっちを見る方がわかりやすそう」
「昔Arelのコードを叩いてゴニョゴニョするコードを見たことがあってですね」「あ〜それはつらいヤツ」「コードレビューに出すのがとてもつらくて、それ以来Arelの直いじりは止めて欲しいと思ってます」「その書き方は止めましょうと自信を持って言いたい😆」「少なくともメンテしやすいコードにはなりませんし」
参考: Rails 6.0で不要なArel.sqlを減らす - koicの日記
⚓selenium-webdriver gemが必須でなくなった
# actionpack/lib/action_dispatch/system_testing/driver.rb#L6
def initialize(name, **options, &capabilities)
@name = name
@browser = Browser.new(options[:using])
@screen_size = options[:screen_size]
@options = options[:options] || {}
@capabilities = capabilities
- @browser.preload unless name == :rack_test
+ if name == :selenium
+ require "selenium/webdriver"
+ @browser.preload
+ end
end
つっつきボイス:「これだけ5月にマージされたプルリクなんですけど、以下の翻訳記事の原著者が投げたプルリクとのことだったので拾ってみました↓」
「Selenium使わないときでもドライバが入ってきてたので必須でないようにしたと」「poltergeistとかちょっと懐かしい名前が見えた」「他のWebブラウザドライバを使うならSelenium要らないので、もっともな修正」
「Seleniumに限らないけど、使わないものが入ってくると違和感ありますね」「Seleniumって依存関係もサイズも大きそうな印象ありますし」「Webブラウザのドライバだけならそこまででかくなさそうですけど、どうなんだろう?」
参考: Seleniumプロジェクトとツール :: Seleniumドキュメント
Seleniumのロゴがいつの間にかフラットなデザインに変わってますね↓(参考: 以前のロゴ)。
⚓Rails
⚓Railsのマイグレーションはスレッドセーフであるべきか(Ruby on Rails Discussionsより)
つっつきボイス:「Railsディスカッションから拾いました」「マイグレーションは稼働中のアプリでも動作させる前提になっていることを考えるとスレッドセーフであって欲しいですけど」「そりゃその方がいいですよね😆」
「そうか、マルチプルDBだと複数のマイグレーションが同時に走る可能性もないわけじゃないのか」「schema migrations tableもDBごとにありそうですし」「この辺あんまり考えたことなかったな〜」
参考: Active Record マイグレーション - Railsガイド
「DB単位で同時にマイグレーションが走ることはないけど、DBをまたいだアプリケーション全体レベルで考えると2つのDBのマイグレーションが同時に実行されることはありそう」「そのときにスレッドセーフに書くべきかどうかということですか、やっと理解」「自分は踏んだことないんですけど、2つのデータベースが密に連携してたりするとデッドロックしたりするのかな?」「いわゆる競合状態のお手本にありそうなシチュエーションっぽい」
「この辺は推測になりますけど、Railsレベルでは複数DBを跨いだマイグレーションの同時実行制御はしてなさそうな気がします: DBをまたいで保証しようとしたら相当大変そうですし」「一般的にDBをまたいで相互にロックするようなマイグレーションはあんまりしないと思いますけど、やったらどうなるのかな?」
「マルチじゃない場合、schema migrations tableをトランザクションでロックするぐらいはしてるかも: そしたらrakeタスクが複数動いてもスレッドが同時にクリティカルセクションに入ることはなくなるのでrakeタスクを実行しても大丈夫でしょうけど」「それがマルチDBになると、複数のDBをまたぐ処理を書いたらスレッドアンセーフになる可能性はありそう」「あ、ちょっと見えてきたかも」「1つのデータベース単位ではマイグレーションがスレッドセーフでも、データベースが複数になったらクリティカルセクションを同時に通るときに何か起きそうな感じですね」
追いかけボイス: Railsレベルではマイグレーションロックがあるみたいですね。
参考: Railsのmigrationにロックが掛かっているのか調べた(Mysqlの場合) - Qiita
⚓bundle exec
すべきかどうか、それが問題だ(Ruby Weeklyより)
- 元記事: Understanding Bundler - to `Bundle Exec` or Not? That Is the Question - The Lean Software Boutique
つっつきボイス: 「記事は見出し冒頭にあるようにBundler入門という感じですね」「割と基本的な話みたいでした」「サブタイトルの方が目立ってる😆」
⚓Railsのbinstub
「ところで今のRails wayではbundle exec
よりbin/rails
みたいなbinstubから実行するのが正式じゃなかったっけ?」「はい、最近はRailsガイドでもそうなってるはずです」「まあ自分は今もbundle exec
でやっちゃいますけど😆」「実は私も😆」
参考: Rails のコマンドラインツール - Railsガイド
「bin/rails
って気にしたことなかったんですけど、bundle exec rails
と同じということなんでしょうか?」「同等でよかったと思います」「へ〜」
「今のRails wayではbin/
の下にあるbinstubもGitにコミットすることになってますし、.gitignoreでもbinstubは無視されないようになってますし」「え〜、自分まったく気づかずにずっとbundle exec
でやってた😭」「bundle exec
でも間違いではないと思います」「使っても大丈夫ですよ〜」
「あくまでRails wayとしてはbinstubが正式ということなので、Railsの教科書やリファレンスを書くならbin/rails
とかで書くべきでしょうね」「なるほど、そういう本でbundle exec
を使いまくってたら違うと」「まあ細かい話なのでそんなに気にしすぎることはありませんけど、一応ということで」
「ところでいつ頃からRailsでbinstubが正式になったんだっけ?」「Rails 4あたり?」「そんな昔からだったんですね...」「binstubの話は当時ことさら話題になってなかったような覚えあります」
後で調べると、どうやらRails 4の頃みたいです↓。
参考: Rails 4.0 と bundler install --binstubs について - おもしろwebサービス開発日記
⚓RSpec Queue: RSpecをパラレルに分散実行(Ruby Weeklyより)
つっつきボイス:「Rspecをキューイングしてパラレルに実行できるヤツか」「RSpec Queueのgem名がrspecqってなっているのが個人的に好き❤️」「短くてよくわかりますし」「こういうネーミングセンスを身に付けたい」
「こうやってワーカーを分けてビルドidを付けるといい感じにキューイングしてくれるみたい↓」「おぉ〜」
# 同リポジトリより
$ rspecq --build=123 --worker=foo1 spec/
「RSpecってそのままだとパラレルにならないから、こういう形でパラレルにすることになるのかな?」「完全おまかせでパラレルにするよりも多少制御はしやすいでしょうね」「すごく大きいテストだとうれしいかも」「前処理が極端に重いテストなんかも制御しやすいかも」「テストのワーカーをいっぱい立ち上げたときなんかだと、完全にラウンドロビンにするんじゃなくて多少制御したいこともありそうですし」
⚓Rubyと「Firefox Send」で巨大ファイルをセキュアに転送する
Sendは無料の暗号化ファイル転送サービスで、任意のブラウザから安全かつシンプルにファイルを共有できます。エンドツーエンド暗号化を用いて、ファイルを共有した瞬間からファイルを開くまでの間のデータをセキュアに保ちます。
同記事より
つっつきボイス:「Firefox Sendって何でしょう?」「ブラウザ内のサービスなのか外部サービスなのかと思ったら、どうやらMozillaがやってる外部サービスみたい」「ブラウザ同士の認証不要なファイル転送をサポートするインフラというかサービスっぽい」「コマンドライン版もあるのね↓」
「any browserってあるからどのブラウザでもやれそう」「記事ではOpen3でRubyから操作してますね↓」「デカいファイルを渡すときに四苦八苦することがときどきあるので、こういう手段があると知ってたら使うかも」「あとはそれを思い出せるかどうか😆」
参考: module Open3
(Ruby 2.7.0 リファレンスマニュアル)
動画では期限を設定できて、最大2.5GBまで扱えるとありますね。なお、後で見たら「改装中」となっていました↓🚧。
- サイト: Firefox Send
⚓その他Rails
Railsがminitestをいろいろ独自拡張してるせいで、「あれ?」って思うことが結構ありますよね〜😅
ちなみにEveryday Railsを買うと付いてくるこの本に「Minitestオリジナルのメソッド」と「Railsの独自拡張」の情報をまとめています。(少し情報が古いかもしれませんが)https://t.co/SmtzTIujxk pic.twitter.com/9sMJpEovwD— Junichi Ito (伊藤淳一) (@jnchito) August 6, 2020
つっつきボイス:「ついさっき流れてきたツイートです」「Everyday Rails買うとこんなおまけがついてくるのね」「Rails独自のMinitest拡張ってあんまり気にしたことなかったかも」
参考: Everyday Rails… Aaron Sumner 著 et al. [Leanpub PDF/iPad/Kindle]
⚓RailsとMinitest
「自分はRailsアプリでMinitest使おうと思ったことないな〜」「お、自分は新しいRailsプロジェクトはしれっとMinitestで書き始めましたよ😋」「私も今度はこっそりMinitestにしようと思ってます」「え〜、マジですか?😳」
参考: library minitest/unit (Ruby 2.0.0)
「RSpecってセットアップも毎回地味に面倒じゃないですか: 今やってるのは自分がrails new
から始めてるので速攻でMinitestでセットアップしましたし」「やべ〜今までRSpecちまちま入れてたけど、今度は自分もMinitestでやってみようかな...😅」「作っているのはAPIサーバーなのでそんな高度なことがしたいわけでもありませんし、それならMinitestのassert
でいいよねって思いますし」
つっつき後のツイートです。
🎊4⃣0⃣0⃣0⃣0⃣🎊https://t.co/NXkuqcREzn
— Ryuta Kamizono (@kamipo) August 7, 2020
⚓Ruby
⚓Ruby 3の型付け進捗
Updated. » The State of Ruby 3 Typing | Square Corner Blog https://t.co/ZQNNFFOBPC
— Yukihiro Matz (@yukihiro_matz) July 30, 2020
» Types in Ruby 3, RBS, and Sorbet · Sorbet https://t.co/Akgqqrohcc
— Yukihiro Matz (@yukihiro_matz) July 31, 2020
つっつきボイス:「Rubyの型付け進捗気になってた」「soutaroさんとSorbetブログで2つ記事が出てました」「RBSという型付け用DSL」「何の略だろう...?」
RBSとはRubyプログラムの構造を記述する言語で、これを用いてクラスやモジュールの定義(クラス内で定義されたメソッド、インスタンス変数とそれらの型、継承関係やmix-in関係)を書き下せます。定数やグローバル変数も定義できます。
同リポジトリより大意
# 同リポジトリより
module ChatApp
VERSION: String
class User
attr_reader login: String
attr_reader email: String
def initialize: (login: String, email: String) -> void
end
class Bot
attr_reader name: String
attr_reader email: String
attr_reader owner: User
def initialize: (name: String, owner: User) -> void
end
class Message
attr_reader id: String
attr_reader string: String
attr_reader from: User | Bot # `|` means union types: `#from` can be `User` or `Bot`
attr_reader reply_to: Message? # `?` means optional type: `#reply_to` can be `nil`
def initialize: (from: User | Bot, string: String) -> void
def reply: (from: User | Bot, string: String) -> Message
end
class Channel
attr_reader name: String
attr_reader messages: Array[Message]
attr_reader users: Array[User]
attr_reader bots: Array[Bot]
def initialize: (name: String) -> void
def each_member: () { (User | Bot) -> void } -> void # `{` and `}` means block.
| () -> Enumerable[User | Bot, void] # Method can be overloaded.
end
end
「RBSは型定義を別ファイルにするのね」「Rubyにもいよいよ型が入ってくるのか〜」「別ファイルにするのは懐かしのC言語開発で.hファイルとかを思い出すのでそんなに違和感はないかな」「すべてに型を付けなくても必要なところにだけ型を書ければいいんじゃないかなって思いますし」「自分もそう思います」
「このソルベットって?」「ソルベ(Sorbet)はShopifyが以前から手掛けているRubyの型付けですね」「アイコンが可愛い❤️」
1本目記事流し読み:
- Ruby 3のRBSという型シグネチャ用言語を発表
- 背景:
- 動的型付けvs静的型付けは古くから問題にされている: 静的型付けは大規模プロジェクト向きだが柔軟性が低下し、動的型付けは短期開発に向いているがコードベースの規模や人数の拡大が難しい
- 4年前にMatzがRuby 3で静的型チェックを導入すると宣言以来、さまざまな言語の型チェックを調べたうえでRubyコミュニティは型チェッカー構築基盤の開発を決定した
- RBSは以下のような感じ
# 同記事より
# sig/merchant.rbs
class Merchant
attr_reader token: String
attr_reader name: String
attr_reader employees: Array[Employee]
def initialize: (token: String, name: String) -> void
def each_employee: () { (Employee) -> void } -> void
| () -> Enumerator[Employee, void]
end
- RBSの主な機能とRubyの重要な特性
- ダックタイピング
- 不統一性(non-uniformity)
- RubyプログラムでRBSの型を使ってできること
- バグを見つけやすくなる
- nil安全性
- IDE統合の向上
- ダックタイプをより安全に
- SorbetとRBS
- RubyコミュニティはSorbetチームとも連携し、RBSがSorbetやSorbet独自のRBI型シグネチャ形式とぶつからないようにしている
- SorbetやSteep(Ruby製でRBSを使用)のような静的型チェッカーもRBSの型定義を使える
- 相互利用のためRBS gemにはRBI->RBS変換機能も付属(逆変換は開発中)
- まとめ
⚓カロリーメイトとQuine
既にあちこちでバズってますが。
コード監修してます。
» CalorieMate to Programmer | 大塚製薬 https://t.co/poB7ajd9pR— Yukihiro Matz (@yukihiro_matz) August 3, 2020
カロリーメイトリキッドのプロモーション用に、Ruby でちょっとした面白プログラムを書かせていただきました!
次のサイトを開いて、cd .Quine と入力し、さらに ruby CML_quine.rb を打ち込めば動きます。Quine の前のピリオドを忘れないこと。https://t.co/Mh5xgpaFU0 pic.twitter.com/RZcpP2qcsI
— Yusuke Endoh (@mametter) August 5, 2020
つっつきボイス:「かなり盛り上がってますね」「mameさんの書いたQuine、マーケティング用のサイトにこういうのをしれっと仕込むオーバーキル感がすごい」「読める気がしない...」
# otsuka.co.jpより
caloriemateliquid .Quine $ cat CML_quine.rb
n=2;eval$s=%q{Z=?\s;eval"$><<S=Z*4"+(%w{+"n=#{-~n%3};eval$s=%q{#$s}#YE";$>.isat ty&&
(r="\e[43;3#{C="#{n*5%9+1}m"}#{T}\e[4"+C+S[1568,79]+E="\e[0m";r[81,21]="\e[37m# {(["Ca
f\u00e9_au_lait","Yogurt","Fruit_mix"][n].chars*Z).tr(?_,"").center(21)}\e[3"+C ;a=%~POS
A[`ER]`PASX1cTc22V6NNP.QOYGMXXIG7KK:bCCaVN8WZ[]UQMMS`cBFFJJHHY`QTUIUURRPTOcRV_a LLUT`WXL
W]a_c_bV`XXYa_9}+[T=' B A L A N C E D F O O D ']*0+%w{bZZYb_][9cc ????`9^acG
G,,N9DU`DKcUKU3K4!4!4!QXTSSS""9`9`#U`KcK--S;;/GOT<QE$U=>F==Q0@%U/P/B=S0Q`PM&XVV V15CMRHMSH
RKO>==QMQVR 'b`&DK>BS<XE$T>T33DDDUM<V@@E(((TCT0A<0A"')5CXPcQa54X@@Y#KcK--S;; /GOT<Q`$)T)T
:a4A%%#X VS6a ' b`&DK>BS<T7**] ^^b6+++]~; P=Str uct.new(:x,:d,:p,:v );M=(-5**7..
b=0).m ap{[]};A=s =[];t=Time.now;q=?y.succ;( s=S .scan(/.+/ );M[0]<<P [25i-b%3*5i-
9,0,0 ,2+1 i] ;6 0.t ime s { |i |j= i %2 0 ;i< 40 ? [ M[j -1],m=M[j],M
[j+1 ]]. ea ch {| n| m. ea ch {| p| n. ea ch {| q| d=p .x -q .x ;w=d.abs-4;w
<0& &( i<2 0? p. d+= w *w: p. p+= w *( d *(3 -p. d- q.d) +(p.v-q.v)*4
)/p .d )} } } :M . shif t .ea c h{ |p| y, x= ( p. x+= p.v +=p.p/10).re
ct; p.p = [4 3- b/9 .0-y,1 ]. m in- [x,p .d=0 , x -9 2].s ort[1]*2i;p.
v/=[ 1,p.v.a bs/2].max;M[20-j+[0 ,(x+ 4).div(5 ),19].sort[1]]<<p;35.tim es{|w|v=x.to
_i-3+w %7;c=s[w=y.div(2)-2+ w/7];(x-v)**2+(y-w*2)**2<16&&0<=w&&c &&(k=(w*2-21
)**2/99)<=v&&c[v]&&k+79!=v&&c[v]=q}}};(24-b/18..21).map{|k|s[k]=Z*(k=(k*2-21)** 2/99)+q*79
+Z+q*2*(6-k)};s*="\e[B\r";" Your favorite flavor ";b+=1;A<<"\e[A\r"*21+s.gsub (/\172+/){
"\e[43m"+$&.tr(q,Z)+E})while+s.count(q)<1950;A.map{|q|sleep([t-Time.now+3,2e-2] .max);$>
<<s=q};$><<s.gsub(?m,";33m").gsub(Z){S.slice!(/./)};b=?]*33.upto(91){|i|a=~/../ ;a=$'.gs
ub(i.chr,$&)}*2;Z<<8;(b+a.gsub(?^,"^]"*41)+b).bytes{|c|c-=86;c<8?sleep(3e-2):$> <<(c<(
'CalorieMate-Liquid-Quine';9)?r.slice!(/\e.*?m|./):c>9?"\e[%X"%c:Z)});puts})*"" }#YE
ちょっと整形しようとして諦めました😅。
直接関係ありませんが、mameさんご本人が別のコードで音楽付き動画をアップしているのをruby-jp Slackで知りました。なるほどの選曲です。
⚓Rubyのcoercion系メソッドには注意(Ruby Weeklyより)
つっつきボイス:「nil
のcoercion(強制型変換)に注意しようという記事みたいです」「Rubyのcoercionってそんなにあったかなと思ったらto_i
みたいなヤツね」
# 同記事より
nil.to_h => {}
nil.to_a => []
nil.to_f => 0.0
nil.to_r => (0/1)
nil.to_c => (0+0i)
参考: 型変換 - Wikipedia
「文字列のto_i
はたしかに予想外のことになりやすい↓」「まあ使い方がよくないという説もありますけど」
# 同記事より
"312".to_i
# 312
"312 oh hai".to_i
# 312
「大文字で始まるInteger()
みたいなcoercionメソッド↓、そういえばこういう機能あったな〜」
# 同記事より
Integer(nil)
# TypeError (can't convert nil into Integer)
Float(nil)
# TypeError (can't convert nil into Float))
「昔は使った覚えあるけど基本的にはcoercionってそんなに使わないかも」「Integer(nil)
ってダメなんだ😳」「ホントだ、今やってみたらエラーになった」「こういうのを型チェックで救えるといいですよね」「書いた時点で見逃すとなかなか見つからなくてproductionでnilエラーになったりするヤツ」
後で気づきましたが、記事を書いた人はvirtusやdry-typeを作った方でした。
以下の翻訳記事も趣旨が似ていますね。
⚓Rubyのrescue
でやんちゃしてやった(Ruby Weeklyより)
つっつきボイス:「パーサーの目を盗んでrescue
にクラス定義を書いたということみたいです」「壊しに行く気満々のコード😆」
# 同記事より
begin
raise "omg"
rescue =>
(class Box
class << self
attr_accessor :contents
end
end; Box).contents
end
puts Box.contents
# => "omg"
「こういう凶悪なコード、よく考えつくな〜」「やったらできちゃうんですね」「Ruby公式とかに投げたら盛り上がりそう」
⚓その他
⚓コントのような
クッソ吹いたw 稼働中の物理サーバーをダウンタイムなしで隣の建物に移動した話。https://t.co/8XEHcMDsVE
— 江添亮@足首靭帯の手術から12週間 (@EzoeRyou) August 5, 2020
つっつきボイス:「200mばかし離れたところに物理サーバーを無停止で移設せよというミッションを頑張ってクリアしたそうです」「本当にそういうミッションがあったんですか?」「5分ぐらいサーバー止めたらダメ?って聞いたら一瞬たりともダメと言われてますね😆」
「移設元サーバーのインターフェイス次第ですけど、意外にやりようはありそう: 電源は今の時代ならUPSつないで発電機回せば割とどうにでもなるんですけど、それよりネットワークが切れないようにする方が大変そうかな🤔」「そんな感じですね」 「移設元と移設先で上流の同じスイッチにつなげられるならやりやすいんですけど」「DNSアップデートとか書いてるから別ネットワークなのかも」「ネットワークが変わると途端に大変になるんですよ...完全なゼロダウンタイムは難しいでしょうし」「お、記事見ると移設先から延々ネットワークケーブルを引いて、先にネットワークを移行してからカートに乗せて移動してるのか、それならやれるかも」
「それにしても一瞬たりとも止められないサーバーって...」「それならどこかクラウドのデータセンターに置けばいいのにって思っちゃいますけど」「作業料の他にコンサル料ももらったって書いてあってよかったよかった」「じゃいいか😆」
「こういうのを考えること自体は結構楽しいですよね😋」「やった人お疲れさまです!」「こういう移行方法の問題点は、途中で何かあったときのリカバリープランがないことですけど」「雨が降ったらどうするとか」「ネコがケーブルかじったりとか」「子どもがぶつかってサーバー落っことしたりとか」「周りを用心棒で固めないと」「途中に道路があったらさらに大変そう...」
「こういうの最近あんまりやってないけど、たまにやると楽しいんですよ」「責任抜きでやれるなら😆」「ISUCONの物理サーバー版みたいな企画あったら面白いかも」
参考: ISUCON公式Blog
後で日本語記事も出ましたね↓。
参考: 物理サーバーを稼働させたまま引っ越しさせた意外な方法がネットで話題に - GIGAZINE
今回は以上です。
バックナンバー(2020年度第3四半期)
週刊Railsウォッチ(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など)です。