- Ruby / Rails関連
週刊Railsウォッチ(20210309後編)RubyのIRBに隠れているイースターエッグ、Power Automate Desktop、SQLクエリのありがちなミス6つほか
こんにちは、hachi8833です。
🔗Ruby
🔗 RubyのIRBに隠れているgem(Ruby Weeklyより)
つっつきボイス:「gemでないものも含めてIRBにはいろんなものが入っているという記事です」
「Ruby 2.7から入ったと記事に書かれているreline gem↓もIRBで使われている」「relineといえば、@aycabtaさんが心血を注いだgemですね」「他にRipper(パーサー)も使われている」
参考: class Ripper (Ruby 3.0.0 リファレンスマニュアル)
RubyKaigi Takeout 2020の動画を見つけました。
「loader
というextensionが入っている: こんなふうにIRBのコンテキストでファイルを読み込んで評価できる↓」「おぉ〜」「-r
付けてファイルを読み込む、そういえばやったことあったかも」「irb_load
でIRBの中でもファイルを読み込めるのか」
# 同記事より
$ irb -r ./hi.rb
Hi codenamev!
irb(main):001:0>
参考: ruby/loader.rb at master · ruby/ruby
参考: ruby/loader.rb at master · ruby/ruby · GitHub
「use_tracer
は自分も使ってます」「最近入ったmeasure
はウォッチでも話題にしましたね(ウォッチ2021_02_02)」
参考: ruby/tracer.rb at master · ruby/ruby
参考: ruby/measure.rb at master · ruby/ruby · GitHub
「以前だとpryを入れないとできないことがありましたけど、今はRuby標準のIRBでできることがとても増えましたよね」「IRBはすごく使いやすくなったと思います」
🔗 IRBに隠された「イースターエッグ」
「お、IRBにはイースターエッグが隠されているようですよ」「どれどれ👀」「こんなのが隠れてたなんて!」
参考: ruby/easter-egg.rb at master · ruby/ruby
「Ruby 3.0のIRBを立ち上げてIRB.send :easter_egg
と入力したら動きました!」「このeaster-egg.rbを明示的に読み込めば他のバージョンのRubyでも動かせそうですね」
「手元のRuby 2.7.1だと以下のような静止画↓で表示されたけど、easter-egg.rbのソースを見るとtypeに:logo
と:dancing
がある: ということは、IRB.send :easter_egg, :dancing
と入力すると...動くイースターエッグが出た!🎉」
(注: 微妙に色が付いているのはhachi8833のiTerm設定によるものです)
ちょうどもうすぐイースターなので季節感ありますね。
後で手元のrbenv環境でRubyのバージョンを変えて試したところ、easter-egg.rbはどうやらRuby 2.7.1から入ったようです。Ruby 3.0.0から動くイースターエッグがデフォルトになったんですね。もしやと思って履歴を調べると、動くバージョンを入れたのはやはりmameさんでした。
ついでにeaster-egg.rbをローカルにダウンロードし、easter-egg.rbが入っていないRuby 2.7.0でirb -r ./easter-egg.rb
を実行してIRB.send :easter_egg
を実行すると、動くイースターエッグが表示されました。
🔗 bundle open
でgemを検索・デバッグする(Ruby Weeklyより)
つっつきボイス:「Bundlerにもいろいろ機能が隠れていますね」「bundle open gem名
でgemをエディタで開けるらしい」「このopen
ってもしかしてMacのopen
コマンドにしか対応してないのかなと思ったら、Ubuntuでも動いたので大丈夫ですね」「お、なるほど」
「自分も手元でGemfileのあるプロジェクトでやってみたら環境変数でエディタを設定しろと言われたので↓、BUNDLER_EDITOR=vi bundle open nokogiri
としたら動きました」
$ bundle open nokogiri
To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR
🔗 Enumerable#filter_map
(Ruby Weeklyより)
↑記事の末尾にあります。filter_map
はRuby 2.7で入ったそうです。
つっつきボイス:「小ネタですが、Ruby Weeklyの末尾に載ってるTip of the Weekを拾いました」「filter_map
という名前からして、filter
とmap
を一度にできそう」
参考: Enumerable#filter_map
(Ruby 3.0.0 リファレンスマニュアル)
「まさにfilter
したものに対してmap
する処理を1個のブロックでまとめて書けるんですね↓」「これは使いたい機能👍」
# Ruby Weekly #541より
[1,2,3,4,5,6].filter_map { |x| x ** 2 if x.even? }
#=> [4,16,36]
「ところでfilter_map
はあるけどselect_map
はないらしい」「言われてみればfilter
とselect
ってどちらかがエイリアスでしたっけ?」「ドキュメントを見ると、Rubyのfind_all
とselect
とfilter
は等価ですね↓」
参考: Enumerable#filter (Ruby 3.0.0 リファレンスマニュアル)
🔗 Rubyのnot
(Hacklinesより)
つっつきボイス:「シンタックスハイライトなしでベタに書くと混乱するタイトルをわざと使ってますね☺️」
後でタイトルを手元でハイライトしてみました↓。最後の「(not)」は、「でも実は同じではない」というニュアンスのようです。
Ruby's
not
keyword is notnot
but!
(not)
「Rubyの否定演算子といえば!
ですけど、not
ってあったかな?」「自分も知らなかったんですが、探すとnot
キーワードがありました↓」「not
は!
よりも優先度が低い、なるほど」
参考: 演算子式 (Ruby 3.0.0 リファレンスマニュアル)
# docs.ruby-lang.orgより
高い ::
[]
+(単項) ! ~
**
-(単項)
* / %
+ -
<< >>
&
| ^
> >= < <=
<=> == === != =~ !~
&&
||
.. ...
?:(条件演算子)
=(+=, -= ... )
not
低い and or
「Rubyのnot
は、and
やor
の次に優先順位が低いんですね」「スペルアウトしたand
やor
があるならnot
があるのもわかる気がする」「記事では!
やnot
を再定義してみてますね↓」「not
を実際に使うことはあまりなかったな」
# 同記事より
# ~/code/ruby/rubys_not_is_not_not_but_!_(not).rb
class Banger
def !
:bang
end
end
class Naysayer
def not
:nay
end
end
(Ruby 1.9の)ドキュメントにあるように、Rubyの
!
はオーバーライドできるので、! message()
のようにメッセージの前に置いても値をオーバーライドできます。しかしnot
キーワードのオーバーライドは、instance.not()
のようにインスタンスの戻り値にしか効きません。
!
をオーバーライドするとnot
にも効くので、not
は何らかの形で!
を使っていることがわかります。
ただし!
とnot
は機能(つまり優先順位)が異なるので、互いにエイリアスではありません。
同記事より大意
🔗 その他Ruby
つっつきボイス:「よく言われている話ですが一応取り上げてみました」「『macOSに最初から入っているRubyは使わないこと』というのはMacで開発するときの常識になっていますが、初心者がハマる原因でもありますね」
「最近Mac使っていないので昔の話になりますが、macOSに最初から入っているRubyはバージョンが古かったし、記事にもあるようにgemをインストールするのにroot権限を要求されたりとかいろいろ不便でしたね」「あれはつらかったです...😢」
「今のmacOSに入っているRubyのバージョンっていくつなんだろう?」「あ、そういえば今はどうなってるのかな?」
後で調べると、自分のMacBook(OSはCatalina: 10.15.7)の/usr/bin/ruby
は2.6.3p62でした。
$ /usr/bin/ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]
今ならウォッチでも取り上げたRails Girlsのインストールレシピ↓を参考にするのがよいでしょうね(ウォッチ20210126)。
参考: Rails Girls インストール・レシピ: Rails Girls - Japanese
🔗DB
🔗 SQLクエリのありがちなミス6つ(DB Weeklyより)
つっつきは6つから抜粋しました。
🔗 NULL
値に対してNOT IN
を使うミス
つっつきボイス:「記事にあるNOT IN (c001, c003, c004, NULL)
のように書いたり、なんとか=NULL
のように書いたりしても期待どおりには評価されないので、基本的にはカラム定義でNULL
を許すときは気をつける必要がありますね」「たしかに」「なお、SQL標準でも多くのRDBでもNULL = NULL
はfalseになります」
「RailsのActive Recordではそういう場合にIS NOT NULL
をAND条件でつないでくれますが、生SQLを書くときには自分でこうした点に注意する必要があります」
🔗 クエリの句の順序が正しくないミス
「SELECT
とFROM
とWHERE
の次は、『GROUP BY
してHAVING
してからORDER BY
する』という順序で書くのがSQLの構文レベルで決まっているので、順序を間違えるとその時点でシンタックスエラーになります」
-- 同記事より: 間違っている例
SELECT empName
FROM employees
WHERE empCategory='DevOps'
ORDER BY empName
GROUP BY branchCode
HAVING count(*) = 1;
-- 同記事より: 正しい例
SELECT empName
FROM employees
WHERE empCategory='DevOps'
GROUP BY branchCode
HAVING count(*) = 1
ORDER BY empName;
🔗 BETWEEN
を両端の値を含まない範囲指定として使うミス
「そうそう、SQLのBETWEEN
は両端の値を含むのが要注意ですね: 4月中の日付で取ろうとして以下のように書いてしまうと、5月1日のものまで取ってしまう↓」
-- 同記事より
SELECT *
FROM products
WHERE manuf_date BETWEEN ‘2020-04-01’ AND ‘2020-05-01’
「そういえば学校で教える英語では常識的にbetweenは両端を含まない(exclusive)なので、英語圏の人がそこで間違えやすそうですね」「そうそう、自分もそこが昔から気になっているんですが、どういうわけかSQLのBETWEENは境界値を含む(inclusive)仕様になっているんですよ」「英語圏では直感に逆らいそう...」
参考: [SQL] 5. データの参照 5 | TECHSCORE(テックスコア)
「少なくとも翻訳の世界では、たとえば"between 2020-01-01 and 2020-02-01"と書かれていたら、1月1日と2月1日は含まないと解釈するんですが、原文が正しくそのつもりで書かれているとも限らないのが要注意だったりします」「へ〜」「ちなみに境界値を含めたい場合はfromとtoで書きます」「たしかにfromとtoで書く方が誤解されなさそう」
「SQLのBETWEENはそうやって面倒になりがちなので、最終的には以下のように書くことが多いかな↓」「なるほど」「これもRailsのActive Recordなら、rangeで指定するとinclusive/exclusiveに応じてBETWEENを使うか使わないかを自動で判断してくれますね」
-- 同記事より
SELECT *
FROM products
WHERE manuf_date => ‘2020-04-01’
AND manuf_date < ‘2020-05-01’
後で調べて思い出しましたが、英語のbetweenは「その期間のどこかの時点」という単発的なニュアンスを含み、fromとtoだと「その期間ずっと」という継続のニュアンスを含むことがよくあります。
参考: 7つの不思議な仕事?(from A to Bの違い?) | 実践で使える英語をマスター!GLJ英語学院/ビズ英アップ!スクール
ついでながら、英語の"between you and me"は「ここだけの話なんだけど」「これは二人だけの秘密だよ」というイディオムです。
🔗 実行時の暗黙のフィールド定義型変換
「これはRDBMSに依存する部分も大きいのでなかなか厄介な問題ですね: 以下のpin
がvarcharの場合暗黙で強制変換されて、ランタイムエラーにこそならないけどパフォーマンスが落ちることがある」
-- 同記事より
SELECT *
FROM myAccount acc
WHERE acc.pin = 123654789286
AND acc.isPending IS null;
「MySQLはこういう場合に割といい感じに型変換してくれますが、PostgreSQLはデフォルトだとお固い傾向がありますね」「なるほど」「PostgreSQLもimplicit conversionを指定すればMySQL並に型変換できるようになりますが、それらも含めてこの問題はRDBMSによって変わってきます」
参考: PostgreSQL 12.4文書 CREATE CAST
「これについてもActive Recordはよしなに対応してくれるので、自分でクエリを書くときもActive Recordが出すクエリを参考にすれば、MySQLでは通るのにPostgreSQLでは通らないということを避けたいときにいいでしょうね」「なるほど!」
🔗 kamipo TRADITIONAL
「特にMySQLを使う場合は、通称『kamipo TRADITIONAL』を参考にするといいと思います」「お、何ですかそれ?」「これです↓」
参考: ルーク!MySQLではkamipo TRADITIONALを使え! | おそらくはそれさえも平凡な日々
@songmu TRADITIONALは複合モードのなかでいちばん厳しめだけどNO_AUTO_VALUE_ON_ZEROとONLY_FULL_GROUP_BY(こっちは5.7.5からデフォルト)も指定しとくのがぼくのオススメです! https://t.co/MAVMgy9TC0
— Ryuta Kamizono (@kamipo) February 25, 2015
「記事にもあるようにsql_mode
を以下のような感じで設定しておくと、MySQLでも標準SQLに近いクエリしか通らなくなりますので、そうした問題を回避できます」「知らなかった〜」
# https://songmu.jp/riji/entry/2015-07-08-kamipo-traditional.html より
SET SESSION sql_mode='TRADITIONAL,NO_AUTO_VALUE_ON_ZERO,ONLY_FULL_GROUP_BY'
「特にONLY_FULL_GROUP_BYは付けることを習慣づけておくといいと思います: ただMySQLの楽な書き方に慣れていると、SELECTするカラムが多い場合にGROUP BYをすべて書くのが面倒に感じられたりもするんですよね...」
「以上、昔からよくあるありがちなSQLのミスでした」
🔗言語/ツール/OS/CPU
🔗 マイクロソフトのRPA「Power Automate Desktop」(Publickeyより)
- 元記事: [速報]マイクロソフト、無料でRPA機能「Power Automate Desktop」をWindows 10ユーザーに提供開始。Microsoft Ignite 2021 - Publickey
つっつきボイス:「ちょっと試してみたそうですね」「そうそう、こんな感じでEC2インスタンスを取得したりできます↓」
「Power Automate Desktopは、一度動かすと右のペインで変数の値を参照できたりするのがなかなかよくできていると思いました」「お〜、ExcelのVBA画面みたいですね」「少しずつ動かしながら変数の値を確認して書き足す、といった使い方ができます」
参考: Visual Basic for Applications - Wikipedia
「もちろんまだ成熟していない機能もいろいろありますが、変数の宣言方法以外はドキュメントをほとんど見ないで書けたのはよかった」「へ〜!」「Power Automate Desktopは前から有料版があったのが無料でもダウンロードして利用できるようになったそうです」「記事にも今後はWindows 10に標準搭載されるとありますね」
参考: Power Automate Desktop のよくある質問集 - 吉田の備忘録
「Macに入っているApple ScriptのAutomatorよりはイケてる感じでしょうか?」「Automatorはほとんど使ったことがありませんが、感覚的にはZapierに近いかな」「なるほど」
参考: Automator Actionを実行 – AppleScriptの穴
参考: Zapier | The easiest way to automate your work
「Power Automate Desktopはプログラマーでない人でも作ることができて、この種のツールとしては比較的機能が揃っているのがいいですね: プログラマー向けにはPythonスクリプトの実行やSFTP接続といった項目もあります」「ホントだ」「ちょっとした日々の運用タスクをある程度自動化するのによさそう👍」
🔗 cosmopolitan: 複数環境で実行できるポータブルバイナリを出力(StatusCode Weeklyより)
cosmopolitan: 国籍や国境にとらわれない国際人
つっつきボイス:「マルチな環境で動くシングルバイナリを出力できるそうです」「リポジトリに貼ってある動物の絵はスカンクかな?」「Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOSで動くって、そんなことが可能なのかしら?」
「リポジトリに謎のタイトルの関連ブログ記事が貼ってある↓」「あ、それはニセのギリシャ語で書かれた英語タイトルです」「ニセギリシャ語😆」「記事を眺めた限りでは、シングルバイナリをマルチな環境で動かす方法があるらしい」「へ〜!」
参考: αcτµαlly pδrταblε εxεcµταblε
「以下のredbeanも同じ人がcosmopolitanをベースに作ったそうです」「実用性はともかく技術的なチャレンジとして面白い」「誰得感ありますね」「スゴい人がいるもんだ...」
げぇ、redbeanなんだこれすごすぎる。確かに即席でWebサーバできたし、Linux(x86_64)でもmacOSでもWindowsでも同じファイルが動いた。実行ファイルだけじゃなくzipとしても振るまってファイルを追加できる。https://t.co/kzaI45nYbI pic.twitter.com/Bku2zwVhsJ
— ぐれさん😉 (@grethlen) March 2, 2021
redbeanの中身。fileの結果はWindowsの実行ファイルだけどよく見たらシェルスクリプトになっている。あーーそういうことか。どちらにも解釈できるのか。 pic.twitter.com/IkfstfuEpU
— ぐれさん😉 (@grethlen) March 2, 2021
後編は以上です。
バックナンバー(2021年度第1四半期)
週刊Railsウォッチ(20210308前編)書籍『Ruby on Rails Performance Apocrypha』、rswag gemほか
- 20210303後編 Bundlerのセキュリティ修正、Rubyのガベージコレクション記事、Rubyが2/24に誕生日ほか
- 20210222 ActiveRecord::Relationの新メソッドload_asyncとexcluding、Active Jobのperform_laterの改善ほか
- 20210209後編 Rubyでミニ言語処理系を作る、Kernel#getsの意外な機能、CSSのcontent-visibilityほか
- 20210208前編 Rails次期リリースがバージョン7に決定、thoughtbotのアプリケーションセキュリティガイドほか](/hachi8833/2021_02_08/103801)
- 20210202後編 Ruby 3 irbのmeasureコマンド、テストを関数型言語のマインドセットで考えるほか
- 20210201前編 Webpackerのガイドがマージ、RailsはRuby 3でどのぐらい速くなったかほか
- 20210126後編 Google Cloud FunctionsがRubyをサポート、Ruby 3のパターンマッチングでポーカーゲームほか
- 20210125前編 Railsリポジトリのデフォルトブランチがmainに変更、Rails 6.1はMySQLのENUM型に対応済みほか
- 20210120後編 Ruby 3.0の新機能で遊ぶ、RubyスニペットをJSに変換するRuby2JS、rspec-parameterized gemほか
- 20210113後編 Ruby 3.0 Ractor解説記事、Vercelホスティングサービス、教育用OS xv6ほか
- 20210112前編 Active Recordの範囲指定バリデーション改善、soleとfind_sole_byメソッド、AlgoliaとRailsほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。
週刊Railsウォッチについて
TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)