Rails CHANGELOG "2019-11-25".."2019-12-01"

この期間の CHANGELOG.md へのコミットは2件。

ActiveJobに関して1件、ActionPackに関して1件。

ActiveJob

ActiveJob::Exceptions.retry_on に キーワード引数 :jitter を追加することで、複数のjobの再試行が同時に行なわれないようにした

コミット: Add jitter to :exponentially_longer · rails/rails@5f76218

rails/exceptions.rb at 5f7621878dda1b3c77bf31e6fa44a32579782bc1 · rails/rails

determine_delay メソッドにもキーワード引数 :jitter が追加され、 Karnel.rand:jitter を使って計算した値を渡すことでリトライジョブの待ち時間がランダムになる。

これにより複数のリトライジョブが同時に実行されにくくなる。

ちなみに「単独のプロセスしか処理できない状況で複数のプロセスが同時に作られ、プロセスがリソースを奪い合う状態」のことをどうやら Thundering herd problem と呼ぶらしい。

ActionPack

redirect_to.action_controller の notifications に request を含めるようにした

コミット: Add request to the payload for notifications to redirect_to.action_co… · rails/rails@23b7382

似たような変更が前にもあったな。この辺り。

今回の変更で、リダイレクト先でもリクエスト元の情報を取り扱うことができるようになる、ということかな?

コミットメッセージに↓のように書いてあった。

This change will allow subscribers to the notification to report on anything related to the request that they might need

だいたい認識あってそうかな。たぶん。

鹿児島Ruby会議01 発表資料リンク集

2019/11/30 に開催された 鹿児島Ruby会議01 の発表資料へのリンクを集めた。

招待講演01 Ruby 3 の型解析に向けた計画(仮)

wip

一般講演01 bruby

wip

一般講演02 ruby-jp

一般講演03 ruby-vipsを利用した画像処理Tips

一般講演04 Haconiwaが越えたあの夏〜3年間を振り返る

一般講演05 RubyOSSコードリーディング

一般講演06 福岡の方から参りました Fukuoka.rb です

一般講演07 かごっま弁のDeep LearningRubyできばっ

一般講演08 How to make a gem with Rust

一般講演09 あまり知られていないRubyの便利機能

一般講演10 "regional” wasn’t going to mean “provincial”

一般講演11 Rubyで作るネット回線の自動速度測定ツール

一般講演12 Location-based API with Ruby

wip

招待講演02 Rails Girlsのお話や、初めての方向けのコミュニティについてなどお話

www.slideshare.net

Rails CHANGELOG "2019-11-18".."2019-11-24"

この期間の CHANGELOG.md へのコミットは6件。

ActiveRecordに関して1件、ActiveSupportに関して1件、ActionPackに関して4件。

そのほか Fixup CHANGELOGs [ci skip] · rails/rails@214f439 でマークダウンの整形(インデントの調整や文末のピリオド付与など)もされている。

ActiveRecord

nil を含むArrayをwhere句に指定した場合に、そのwhere句に対する unscope が正しく動作しないバグを修正した

コミット: Fix unscoped grouped where · rails/rails@12afdba

unscope ってなんだっけ

Removes an unwanted relation that is already defined on a chain of relations. This is useful when passing around chains of relations and would like to modify the relations without reconstructing the entire chain.

引用: ActiveRecord::QueryMethods

「すでに定義されたリレーションから不要なリレーションを消すよ。これはリレーション全体を作り直すことなくリレーションを変更できるから便利だよ。」的な感じだ。

手元(Rails 6.0.1)でバグを確認してみる

[1] > users = User.where(id: [1, 2])
=>   User Load (0.9ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2)
[2] > users.unscope(where: :id)
=>   User Load (1.0ms)  SELECT "users".* FROM "users"
[3] > users = User.where(id: [nil, 1, 2])
=>   User Load (1.0ms)  SELECT "users".* FROM "users" WHERE ("users"."id" IN (1, 2) OR "users"."id" IS NULL)
[4] > users.unscope(where: :id)
=>   User Load (1.1ms)  SELECT "users".* FROM "users" WHERE ("users"."id" IN (1, 2) OR "users"."id" IS NULL)

なるほど確かに [4] で unscope が効いていない。これが効くように修正したとのこと。

Arel.fetch_attribute を修正している。

Allow attributes to be fetched from Arel node groupings.

引用: Fix unscoped grouped where by gmcgibbon · Pull Request #37733 · rails/rails

「ノードグループから属性を取得できるようにしたよ」ということなので、

多分ノードグループというのが手元で動かしたときの ("users"."id" IN (1, 2) OR "users"."id" IS NULL) のことで、ここから "users"."id" と特定できるようにしたよ、的なことじゃないかなぁと思う。

修正前まではこれが特定できなかったから、 unscope しようとしてもその対象が見つからないため、 unscope できなかったんじゃないかな。

ActiveSupport

定数名の修正

コミット: Follow up 997770f5955a36f0c800388c4592c961e184aec4 · rails/rails@9714d5d

Check the actual constant used · rails/rails@997770f の修正の follow up

元々の修正を辿ると、issue は これ `cpu_time` in `ActiveSupport::Notifications::Instrumenter` using incorrect clock? · Issue #37441 · rails/rails で、CLOCK_PROCESS_CPUTIME_ID じゃなくて CLOCK_THREAD_CPUTIME_ID を使おうぜ〜、というやつ。

CHANGELOG の定数名が CLOCK_PROCESS_CPUTIME_ID のままだったので CLOCK_THREAD_CPUTIME_ID に書き換えている。

ActionPack

ActionController::Parameters にkeyの存在確認をする member? メソッドを追加した

コミット: Add params.member? to mimic Hash behavior · rails/rails@34b6e8c

もともと has_key? はあったから機能的には十分だったはず。

だけど、 Hashが has_key?member? を両方使えるのに ActionController::Parameters では has_key? しか使えないのはややこしい?から統一した、という感じかなぁ。

システムテストでスクショを保存するとき、pathの / \- に書き換えるようにした

コミット: Remove slashes and backslashes from image paths · rails/rails@3c3b80e

ActionDispatch::SystemTesting::TestHelpers::ScreenshotHelper の修正。

スクショのディレクトリが階層構造になっていると tmp:clear でファイルを消そうとしたときにエラーになってしまうとのこと。

respond_to#any に関して、リクエストに基づくContent-Typeではなく、blockで指定されたContent-Typeを返すようにした

コミット: Modify respond_to behaviour always setting the request's content type: · rails/rails@42c5157

def my_action
  respond_to do |format|
    format.any { render(json: { foo: 'bar' }) }
  end
end

get('my_action.csv')

引用: Modify respond_to behaviour always setting the request's content type: · rails/rails@42c5157

修正前はCSVが返るようになっていたけど、修正後はJSONが返るようになる。

もし今 respond_to { |format| format.any } を使っているコードがある場合、この修正前後でアプリケーションの挙動が変わる可能性があるので注意が必要。

↑と同じ内容

コミット: Merge pull request #37617 from Edouard-chin/ec-respond-to-contenttype · rails/rails@4fe7675

さっきのと全く同じ内容っぽいけど、コミットは別なのか 😮

Rails CHANGELOG "2019-11-10".."2019-11-17"

この期間の CHANGELOG.md へのコミットは4件。

ActiveRecordに関して2件、ActiveSupportに関して1件、ActionPackに関して1件。

ActiveRecord

implicit_order_column を指定しているとき、結果を確定的にするために primary_key でもソートするようにした

コミット: Additionally order by primary key if implicit_order_column is not uniq · rails/rails@31d31fc

もともとimplicit_order_column= メソッドのドキュメントには

Note that using a non-unique column can result in non-deterministic results.

引用: ActiveRecord::ModelSchema

「一意じゃないカラムを指定すると結果が確定的にならないから気をつけてね」と書いてある。

implicit_order_column に指定したカラムに重複している値がある場合に、環境の違いで取得するレコードの順番が変わったりする、ということ。

ああ、そういえば昔MySQLを使っていて、同じクエリでもInnoDBMyISAMで取得順序が違っている現象に遭遇したことがあるなぁ。

他にも同じクエリに対して取得順序が変わるケースがあったりするのかな。

で、「確定的な結果が得られた方が良いよね?」ということで今回の修正。

implicit_order_column に指定したカラムが primary_key ではない場合、その指定したカラムに加えて primary_key でもソートするようになったので、確定的な結果が得られるようになった。

ConnectionAdapters::Resolver を削除して DatabaseConfigurations を優先するようにした

コミット: Remove ConnectionAdapters::Resolver in favor of DatabaseConfigurations · rails/rails@8d5a4ff

ConnectionAdapters::ResolverDatabaseConfigurations は共通するメソッドが多い一方で微妙に一貫性がない部分もあって複雑だから共通化しようぜ?、ということ。

この結果として establish_connection メソッドに不正な引数(adapter が指定されていないHashなど)が渡された時に例外を吐くようになった。

ActiveSupport

ActiveSupport::Testing::TimeHelpers#travel_back にブロックを渡せるようになった

コミット: Accept block in travel_back time helper · rails/rails@21f907b

そもそも travel_back って何かというと、

Returns the current time back to its original state, by removing the stubs added by travel, travel_to, and freeze_time.

引用: ActiveSupport::Testing::TimeHelpers

travel, travel_to, freeze_time によって追加されたスタブを削除することで、現在の時刻を元の状態に戻すよ」というもの。

今回の修正でブロック引数に対応したので、そのブロックのなかだけ時間を戻せるようになった。

ブロックの外はスタブした時間のままになる。

具体例はこんな感じ↓

Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00

travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00

travel_back do
  Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
end

Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00

引用: rails/time_helpers.rb at 21f907bb51df95a26f129277fe817019b8c37f0a · rails/rails

ActionPack

process_action.action_controller の notifications に response を丸ごと含めるようにした

コミット: Provide the whole response · rails/rails@b5c6f33

Rails CHANGELOG "2019-11-04".."2019-11-09" - tanaken’s blog で紹介した、「 process_action.action_controller の notifications に Location レスポンスヘッダを含めるようにした」に関連した修正。

response.filtered_location だけ含めるのではなく、 response を丸ごと使えば良いじゃん、となったらしい。

Rails CHANGELOG "2019-11-04".."2019-11-09"

この期間の CHANGELOG.md へのコミットは5件。

ActionPackに関しての3件、ActiveJobに関して2件。

ActionPack

process_action.action_controller の notifications に Location レスポンスヘッダを含めるようにした

コミット: Add :location to process_action.action_controller payloads · rails/rails@7222594

周辺知識がなさ過ぎてよくわからん。

process_action.action_controller の notifications」ってなんじゃ。

ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
  result = super
  payload[:status]   = response.status
  payload[:location] = response.filtered_location
  result
ensure
  append_info_to_payload(payload)
end

引用: rails/instrumentation.rb at 722259444ae3a2dbdea7df50b4652e9d4aaaccdb · rails/rails

ふむ。 ActiveSupport::Notifications ってのがあるんすね。payloadの :locationresponse.filtered_location を入れてる。

responseActionDispatch::Response だ。

ActionDispatch::Response のなかで ActionDispatch::Http::FilterRedirect を include している。

filtered_locationActionDispatch::Http::FilterRedirect の中で定義されてる。

memo: そもそもLocationレスポンスヘッダ

Location レスポンスヘッダーはリダイレクト先の URL を示します。 3xx (リダイレクト) または 201 (created) ステータスレスポンスを返すときのみ意味を成します。

引用: Location - HTTP | MDN

process_action.action_controller の notifications に uuid も含めるようにした

コミット: Add :uuid to process_action.action_controller payloads · rails/rails@8ec75a1

さっきと似たような修正。 payloadの :uuidrequest.uuid を含めるようになった。

uuidActionDispatch::Request クラスの uuid で、request_id のaliasだ。

一意なリクエストidを notifications に含めることでデバッグしやすくなったりするよ、ということかなぁ。

process_action.action_controller の notifications に request を丸ごと含めるようにした

コミット: Provide the whole request · rails/rails@32b99f9

さっき uuid を含めるようにしたけど、「もういっそのこと request 全部含めちゃえばよくね??」となってる。

uuid を含める処理は決して、代わりに request(= ActionDispatch::Request クラスのインスタンス)をまるっと、payloadの :request に含めるようにしている。

ActiveJob

ジョブをキューに入れて実行するとき、引数のログを無効にするオプションを追加した

コミット: Add an option to disable logging for jobs with sensitive arguments · rails/rails@ce085f6

これまでは引数のログが出ちゃってたんだよなぁ。確かにそうだった。

例えば個人情報を含む引数を渡した時にログに出てしまうとあまりよろしくないわけだ。

class SensitiveJob < ApplicationJob
  self.log_arguments = false

  def perform(my_sensitive_argument)
  end
end

引用: Add an option to disable logging for jobs with sensitive arguments · rails/rails@ce085f6

self.log_arguments = false を指定するだけで良いんだ。便利。

ぱっと見、logを非表示にしたい引数を個別に指定できるともっと便利そうだなぁと思った。けどそんなに需要ないかぁ。

Fix Typo

コミット: Fix small typo in activejob changelog · rails/rails@d6a7aab

arguments のスペルが間違ってたので修正された

"越境" について考えている

今月末に鹿児島Ruby会議01がある。

鹿児島での初の地域Ruby会議。

テーマは「越境」

k-ruby.github.io

プログラミング言語Rubyを通して越境する

実行委員長 黒瀧悠太 (GMOペパボ株式会社 テクニカルリード)

私がK-Rubyに何回か参加して思ったのは、大学の先生がふらっとコミュニティに参加していたり、自分達で会社を作ってRubyを書いている人が多くいらっしゃいました。東京から来た自分はその光景に驚きました。もう一つ驚いたことは女性のエンジニアが少ないという事、これは鹿児島だけの話ではないかもしれませんが、都内で女性のエンジニアが多く活躍されているのを沢山見て来たので新鮮な光景でした。

プログラミングRubyの楽しみを通じて、県内から県外へ、九州から日本へ、世界へ、人種とか性別とか生まれた場所を越えていけたらもっとおもしろい未来が見える気がしました。

鹿児島のコミュニティの方がやっている事を他の県の人にも知ってもらいたい、他の県でやっている事を知りたい。これからもお互いにRubyというプログラミング言語を通して交流を深めていければ嬉しいです。

みなさんのRubyを使ったアイデアで”何かを越えた!”という発表をお待ちしています。

「越境」は「境界は無いぜ」という意味じゃなくて「境界があることを受け止めた上で越えていこうぜ」という意味だと捉えている。

それぞれ様々なバックグラウンドを持っていて、それぞれは誰一人同じじゃなくて、みんな違っている。

その中で、似ている部分・共通している部分があったり、全く違う部分があったりする。

「似ている部分・共通している部分を認識して理解を深める」

その上で

「全く違う部分を見せあって語り合って、お互いの幅を広げていく」

そんな想いがこの「越境」という言葉にはありそうだなぁと思った。

自分は鹿児島Ruby会議に運営スタッフとして関わっていて、この「越境」というテーマに沿った何かをしたいなぁと思っている。

当日まであと3週間。準備を進めよう。

福岡 RailsGirls Fukuoka 2nd に行ってきた

f:id:tanaken0515:20191104144350p:plain

11/01~02 に開催されたRails Girls Fukuoka 2ndでコーチをしてきた。

コーチ陣で入念な準備をしていたおかげで無事に初日のインストールdayを乗り越え、2日目のアプリ開発も無事に全員Herokuへのデプロイまで完了することができた。

インストールdayを乗り越える過程でWindowsへのRuby, Railsの環境構築を完全に理解した。

2日目のアプリ開発で、完全に初めて開発をする人に対して説明してみて、「ああ、膨大な知識量なんだなぁ」と感じた。

自分の中で当たり前になっていること、染み付いていることを、改めて言語化して、相手にわかるように説明しようとするとすごいおしゃべりすることになる。

What(何をやっているのか) Why(なぜやっているのか)をなるべく端的に、なるべく理解してもらえるように説明するのは、脳トレっぽかった。

brew install した時にターミナルに🍺絵文字が出て「この🍺は何ですか?」と聞かれて、ああそうか、初見だったら気になるよなぁ〜、と和んだ。

最初から全てを理解してもらうのは難しいと認識していたけど、ガールズは一生懸命「理解しよう」と話を聞いたり質問してくれるので、自分を含めコーチ陣はみんな一生懸命「理解してもらおう」と話をしていたと思う。それが、なんか、とてつもなく『良い空間』だった。

参加してくれたガールズには「なんか詳しいことはよくわからなかったけど、コーチと一緒にやったら自分で作ったRailsのやつをインターネットに公開できた!」という感触を持ち帰ってもらえていたら嬉しいな。

この成功体験があるのと無いのとじゃ、心持ちがだいぶ違う気がする。何かに壁にぶち当たった時に「必ず成功する方法があって、一度は自分でそれができた」という体験があると、自信を持ってその壁に立ち向かえる。

というか、分からないことや出来ないことがあったらRailsGirlsのSlackで「コーチとやった時は出来たんですけど〜〜!」と聞けばだいたい教えてくれるから最高だよなぁ笑

RailsGirlsへの初参加&初コーチだったけど、学びのある楽しい2日間だった。

大感謝。