- 開発
週刊Railsウォッチ(20181210)update_columnは要注意、DBカラムコメントは書こう、個人情報扱いの注意点、Capistranoはやっぱりいいほか
こんにちは、hachi8833です。今年最後の公開つっつき会も盛況でした。ご参加いただいた皆さまありがとうございました!🙇
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話です👄
- 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください
⚓臨時ニュース: Ruby 2.6.0-rc1がリリース(Ruby公式ニュースより)
Ruby 2.6.0-rc1 released https://t.co/c9qLnLZg8D だいたいRuby 2.6の機能は出揃ったはずなので、そろそろ試していただけるとありがたく思います
— 成瀬 (@nalsh) December 6, 2018
- プレスリリース: Ruby 2.6.0-rc1 Released
公開つっつき会の翌日のリリースでした。詳しくは上をご覧ください。
その後jnchitoさんの懇切丁寧なまとめ記事も出ました↓。
今年も書きました。Ruby 2.6のまとめ記事です!個人的にはProc#>>が好き〜❤️
サンプルコードでわかる!Ruby 2.6の主な新機能と変更点 https://t.co/P8cXY4ZBgK— Junichi Ito (伊藤淳一) (@jnchito) December 9, 2018
⚓Rails: 先週の改修(Rails公式ニュースより)
⚓Rails 5.2.2がリリース
- 元記事: Rails 5.2.2 has been released! | Riding Rails
- GitHub Releases: Release 5.2.2 · rails/rails
今回社内のSlackで話題になったのは、GitHub上のreleases/tagの方がリリースノートがまとまっていて読みやすくなっていたという点でした。
つっつきボイス:「セキュリティ修正なのかな?」「今度のは普通のバグ修正のようです」「Rails 5.2.2リリースを少し詳しく見たいというリクエストをいただきましたので、他の項目は軽めで今回はここを中心に見ていく感じにしたいと思います😊」「単なるfix bugはさっと流していく感じで☺️」
⚓エスケープ復元のバグ
Fix bug where
URI.unescape
would fail with mixed Unicode/escaped character input:
「URI.unescape
のバグか↓」「バ
の濁点が分離してるのかな?」「いや、これはエスケープの種類(8進数形式とURL形式)が複数混じっているときにコケるバグ」「あーそっちですね」「そもそも混ぜるな危険☠️」
URI.unescape("\xe3\x83\x90") # => "バ"
URI.unescape("%E3%83%90") # => "バ"
URI.unescape("\xe3\x83\x90%E3%83%90") # => Encoding::CompatibilityError
⚓Active Recordの#update*
系メソッドは要注意
Allow aliased attributes to be used in #update_columns and #update.
「#update_column
や#update
でエイリアスの属性を使えるようにしたと」
「ところでActive Recordの#update_column
といえば、良心的なRailsエンジニアなら普通は使わないメソッドで有名ですね😎」「ムフフ😎」「ムフフ😎」「基本、使うもんじゃない」「使ってないですー」
「今日使いました😇」「おっと😆それは普通ならrejectされるか、さもなければNEEDFIXとか書かれるヤツです☺️」「自分も知らなかった💦」「今日でよかった☺️」
「#update_column
メソッドがよろしくない理由ですが、昔のこの記事↓をちょっと開いてみてください(古い情報です)」
参考: » Railsのコールバックまとめ TECHSCORE BLOG
以下は同記事に記載されている時点のupdate_*
系メソッドをざっくり分類したものです。
- コールバックを実行する
update
update_attribute
update_attributes
update_attributes!
- コールバックを実行しない
update_column
update_all
update_counters
「Active Recordでデータベースを更新するメソッドを大きく分けるとsave
とupdate
になるんですが、基本的にsave
を使うべき」「#update
はSQLのUPDATE文を発行するんですが、上のようにupdate
系にはコールバック(フック)が動かないものがあります: この記事の時点の記述によれば、update
はコールバックを実行するのにupdate_column
はコールバックを実行しない」「マジで?😅」「一貫性が見えない...」「これがとてもわかりにくいので、#update_column
や#update
は基本使わない方がいい」
なお、Active Recordのコールバックでは以下のまとめ記事が有名ですが、その後#25503で
update_attribute
の挙動が修正されたりしているのでご注意ください。
参考: ActiveRecord の attribute 更新方法まとめ - Qiita
「コールバックが呼ばれないと何が起きるかという話もついでにしちゃいましょう: コールバックが呼ばれないと、before_*
フックやafter_*
フックと連動している処理が全部スキップされてしまいます」「😱」「そうすると、Railsのモデルの中で期待されている制約に違反するデータができてしまう可能性がある」
「そうした制約はRDBMSの側でCONSTRAINTとか使ってかけるべきという考え方"も"あるんですが、Railsではそうしたバリデーションなどは原則としてRubyのコードで行うという文化になっていますね」「あーそうなのか: 自分は両方でやるものかと思ってた」「そこはプロジェクトのポリシーにもよるので、絶対というものではありませんね☺️」
「実際そのあたりの棲み分けって悩ましくて、非常にシンプルなCONSTRAINTだったらRDBMS側でやってもいいんですけど、ビジネスロジックに属する制約をモデルから離れたRDBMSに置くのはちょっとねー、という思いもあるわけです」「おー」「RDBMS側に置いているビジネスロジックが複雑になってきたら、そのうちストアドプロシージャになってしまうんじゃないかと😆」「😆」
「補足すると、ここで言っているRDBMSのCONSTRAINTというものは、NOT NULLなんかと同じような類の制約です: Railsから開発の道に入った人だとこの辺は普段あまり意識しないかもしれませんが」「まだNOT NULLしか使ったことなかった🤭」「RDBMSにはこうしたCONSTRAINTなどの機能が元々あるんですよ😚」
「それが実際のRailsアプリになると、だんだん単純な制約に収まらなくなってきて、たとえばカラムAがこういう状態のときはカラムBは何件以上なければならない、みたいな複雑な制約になるとCONSTRAINTだけでは表しきれないので、あくまでRDBMSでやろうとすると上述のストアドプロシージャを使うことになると」「ふーむ」「ストアドプロシージャの向こうには闇が広がってますから🌘」「😆」
「ストアドプロシージャは、要するにRDBMSの中でプログラム(関数)を書いて実行できるようにする仕組み: ただし、いわゆる手続き型言語のプログラムとはちょっと趣が違う、特徴的な書き方をします」「PL/SQLはOracleのだったかな?」「そうですね」「とにかくストアドプロシージャはRDBMSごとに違う」「つまり互換性がない😇」
「ストアドプロシージャで制約をかけていれば、仮にさっきの#update_column
メソッドを使ったとしてもRDBMS側でfailするので間違って更新されることはありませんけどね😆」「😆」
「まあそういうわけで、#update_column
は基本使わないこと: 使うなら#update_attributes
にしましょう😍」
「実はattributeの呼び出しを1回にまとめようと思って#update_column
を使いました😅」「おっと〜、それは一番残念なパターン😆」「😆」「あ、そういえばその書き方、Railsチュートリアルに載ってますよ🤓」「ありゃ~😆」「それはアカンな〜😅」「後で探しときます: それは原作者にフィードバックしないと📩」
念のため、現時点の英語版↓で確認しました。
参考: Chapter 11: Account activation | Ruby on Rails Tutorial (Rails 5) | Softcover.io
追いかけボイス: 「このコードにはバリデーションがないので辛うじて直接の問題にはなっていませんが、チュートリアルとしては一言注意が必要ですね⚠️」
# 英語版Railsチュートリアル11章の演習より
class User < ApplicationRecord
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
.
.
.
# Activates an account.
def activate
update_columns(activated: FILL_IN, activated_at: FILL_IN)
end
# Sends activation email.
def send_activation_email
UserMailer.account_activation(self).deliver_now
end
private
# Converts email to all lower-case.
def downcase_email
self.email = email.downcase
end
# Creates and assigns the activation token and digest.
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
「後もうひとつ悩ましいのは、SQLにあるUPDATEやINSERTやDELETEと同じ名前のメソッドは利用を避ける方がいいのかなと思う一方で(#select
はまた意味が違うのでこの際置いとくとして)、そうとも言い切れないところがある点: というのも#update_attributes
に相当するsaveのメソッドがないから」「むむ」「要するに、引数に属性を渡してそれを更新するメソッドがない」「save
はsave
ですからね」「save
には属性を渡せないんですよねー😢: そこが覚えにくいところ...」「できそうでできないという😓」
先日のRails Developers Meetupで、#update_column
はその挙動を知ったうえであえて使うことはあるかもしれないという声もありました。いずれにしろカジュアルに使うものではなさそうですね。
「長くなりましたが、今回のActive Recordの修正は#update_column
や#update
でエイリアスの属性を使えるようにしたと」「使えなくていいんじゃないかしら🤣」
⚓その他Active Recordの修正
※以下、changelogの引用ごとに話題が変わっています。ご了承ください🙇。
Fixes issue where "user post" is misinterpreted as ""user"."post"" when quoting table names with the postgres adapter.
「次もActive Record」「あー、PostgreSQLのテーブル名にuser post
みたいにスペースが入っていると""user"."post""
と解釈されてしまう問題があったのか」「テーブル名にスペース...だと?😅」「普通に書いていれば踏みませんけどね☺️」
Cached columns_hash fields should be excluded from ResultSet#column_types
「#34528も普通に開発する分には意識しなくてもよさそうかな」
Values of enum are frozen, raising an error when attempting to modify them.
「え、enumって今まで更新できた?😅: ああ、Active Recordでのenum(列挙型)サポートの問題を修正したのか」
「ところでenumって使ったことあります?」「うーん」「type系のカラムはenumを使う方が想定外の値が入らずに済むからいいという考え方もありますね☺️」
参考: 8.7. 列挙型 -- PostgreSQL 10.5文書
update_columns now correctly raises ActiveModel::MissingAttributeError
if the attribute does not exist.
「これはさっきのupdate_columns
の修正とつながってそう」
Do not use prepared statement in queries that have a large number of binds.
「大量にbindするクエリではprepared statementを使わないと: そんなクエリはまず再利用しないだろうからキャッシュも効かないだろうし、それに重くなるだろうし: たぶんだけど」
「たとえばどういうクエリだとbindが大量になるんでしょうか?」「雑にやるなら、INにarrayを渡せば一発🌋: 軽く数MBのクエリができるし😆」「😆」
「他のfix系は書いてあるとおりだろうからだいたいいいかな」
Prevent leaking of user's DB credentials on
rails db:create
failure.
「おー!」「db:create
に失敗するとお漏らし🌊」
⚓カラムコメントをちゃんと書いておくと後で身を助ける話
Fix bulk change table ignores comment option on PostgreSQL.
「これはマイグレーションの修正っぽい」「ところで皆さんはデータベースのテーブルやカラムにコメントって書いてます?」「あー」「あんまり...」「コメント、書いてもいいけどi18nとかで二重管理になったらヤダなー😅」「自分は、ちょろいテーブルならともかく、ゴツい仕様書が出てくるような案件では極力コメントを書いておきたいですね」
「今はマイグレーションでコメント書けばデフォルトでデータベースに入るんですよね」「ですです: 昔はmigration_commentsというgemを入れないとできなかった」
「データベースのカラムコメントをちゃんと書いておくと、後でDBツールからデータベース仕様書を自動生成できるという大きなメリット🎁があるんですよ、ね☺️」「ですね☺️」
「データベース仕様書をExcel形式で求められることってあるんですけど、Macだった頃はExcelの起動自体が重いし、仕様書を手書きするという無駄な仕事はぜひ避けたいので、コメントはデータベース側に入れておきたい」「Windowsに変わってからはどうですか?」「シートをダブルクリックするだけでExcelがすっと立ち上がるんで快適😂: クラッシュしないExcelってこんなにいいのかと😆」
「そうそう、吐き出した仕様をExcelに整形してくれるツールがあるんですが、何て名前だったかな🤔」「gemじゃなくて?」「gemじゃなーい: あの名前覚えられない」「あれ覚えられないっすよね😅」「あった: A5:SQL Mk-2↓: これは知っておくとマジでいいですよ❤️」
参考: A5:SQL Mk-2 - フリーの汎用SQL開発ツール/ER図ツール .. 松原正和
「これはほんとに神ツール⛩」「その用途としてはめちゃくちゃ使えるんですよね☺️」「いつぞやのウォッチにあったApache POIとはまた別?」「あれとは違いますね: こちらはデータベースをinspectしてテーブル定義書に整形してくれる」「これがないと生きていけない人いっぱいいそう😭」「これっこの論理名↓の列にコメントが入ってきてくれるっっ」「論理名って😆」「物理名が本来のカラム名ですか😆」「これならマイグレーション後の定義書更新もコワくない」
「こういうテーブル定義書ってSI系のドキュメントの中では価値が高い方だと思いますね: 開発環境も手元になくてソースコードすらない状態でテーブル定義書しかもらえない、なんてこともあったりしますし😭」「それもなかったら相当キツイ😭」「テーブル定義書はないよりある方が全然ありがたい🙏」
「ただこういうドキュメントを人間が手書きするという行為がイヤなだけで😆、だからこそ、この最強ツールを活かすためにはコメントを日本語でみっちり入れておかないと、ね☺️」「カラムコメントを書いて怒られることはまずないし☺️」「特にプロジェクトが長期化して後からいろいろ機能が足されていくと、カラム名から機能が予測できないものがどうしても出てきてしまうんですよ、ね☺️」「ですね☺️辞書引かないとわからないようなカラム名とかがgemで入ってきたり」「そういうときにコメントで『これはXX gemで追加された』とか書いてあるだけで大助かり」
「で話をバグ修正に戻すと、お、このバグ踏んだことある気がする😓」「あれ?このコメントバグ修正した方、この間の公開つっつき会に来てた方なんじゃ...?😳」「えっマジで?まったく気づいてなかった😅」「Railsにもコミットしたりしてますって言ってましたね☺️」
⚓Action Packの改修
「ところでAction Packって何をするところかわかります?」「う、わからない😅」「Action Packはやってることが多すぎるんですが😆、ルーティングとコントローラ周りを担当しています」「ヘルパーの一部もここにあった気がする」「自分の理解では、Action PackとAction Viewにあるヘルパーが合わさったものがビューで触れるヘルパーになるという感じ」「ですね: なんちゃら_url
みたいなのはルーティングのroutes.rbで解釈されてからでないとURLを引けないから、Action Packの方に入ってるはず」「あー、そっちに入ってるですか」「Action Viewのヘルパーはおそらく純粋に文字列を処理する方ですね」
Reset Capybara sessions if failed system test screenshot raising an exception.
「↑ちょうどCapybaraのバグ修正もここに出てる: ということはシステムテストのコンポーネントもAction Packに入ってるってことかな」「そうなの?😆」「(Action Packの中の)Action Dispatchの中に入ってますね」「Action Pack、何でも入ってる感」「Journeyなんてのもありますしね」「Railsの中で読むのが最も大変な部類」「Active Record並に読むの難しいですか?」「いい勝負かも😆」
⚓Active Jobの改修
「Active Jobは最近になってだいぶ機能修正が進んできた感ありますね: もっと早く登場して欲しかったなと思いつつ」「いつからRailsに入ったんだっけ?」「4.2ですかね」「前回のウォッチで扱ったGlobalIDもActive Jobと一緒に入ったみたいです」「やっぱり割と最近なんだなー」
「ジョブ管理はたいていのアプリで使うものですが、Active Jobの登場が比較的遅かったこともあって、今でもActive Jobを使っていながらSidekiqを生で叩いてたりする人がいますし😆」「Active Jobが出たおかげで、もうrakeタスク書かなくていいんだー!ってすごく感動しました😂」
「そうそう、Active Jobをちゃんと使えば、今までrakeタスクでやってたことがジョブの形で書けるようになったのは大きな変化なのかなという気もしますし☺️」「Active Job登場以前は、普通ならジョブキューにぽいっと渡しておしまいにできるような軽量なジョブをコマンドラインで実行しようとすると、rakeタスク以外の選択肢がありませんでしたね😢」
「そしてrakeタスクはすっごく書きづらい!」「同意」「同意」「しかも起動が遅いし」「もともシェルスクリプトやmakeコマンドの代わりみたいなものですからね、rakeタスクって」「Railsのコンテキストで動かせるシェルスクリプト的な位置づけ」「rakeタスクはいろいろ融通が利かない」「Active Jobはちゃんと個別の小さなジョブを管理するという設計思想で作られているし、当然ながら非同期ワーカーに渡してやってもらうこともできるし」
「そういえばrails
コマンドでジョブを生成できた気がするけどどうやるんだっけか?」「generateはあるみたいだけど...」「あ、正確にはこんな感じのジョブのクラス↓をRailsランナーの引数で指定できるという機能でした」
参考: Active Job の基礎 | Rails ガイド
# Railsガイドより
# 明日正午に実行したいジョブをキューに登録する
GuestsCleanupJob.set(wait_until: Date.tomorrow.noon).perform_later(guest)
「今回の修正を見ていて、Active Jobはもっと積極的に使おうという気にだんだんなってきた😋」「😋」
⚓Active Storageの改修
「Active Storageはまだまだ更新が続くだろうなと予測してます😋」「まだまだこれからですよねー?」「機能を単に使う分にはいいけど、カスタマイズしようとするとまだ何か踏むんじゃないかと😅」「今のところActive Storageを積極的に使おうという気にまだなってない🤓」
Fix uploading Tempfiles to Azure Storage.
「tmpファイルからAzureに直接置けるようになったと」「Azureだけバグってたのかな?😆」
「こうやって5.2.2の修正点をみんなでチェックするのっていいですね😋」「この間の5.2.1はそこそこクリティカルな修正でしたけど今回は割と普通の修正ですね」「こうやって細かく刻んでもらう方がうれしいという側面もありますね: 後で古いRailsアプリのコードを見たときに、これはあの頃に作られたんだなってわかったりしますし😆: マイナーバージョンが半年ぐらい続くと『これはいつのRailsだ?』ってなりそうだし」
「そういえば冒頭のGitHubのスクショにもありますが、GitHubのウォッチ機能にRelease Onlyが入ったのはさりげにデカイ: これでやっとリポジトリをウォッチする気になりましたもん😆」「今までのReleaseページはzipが置いてあるだけで情報がなかったんですが、今回の5.2.2はおそらくGitHubの改善に合わせてReleaseページにchangelogも掲載するようになったんじゃないかなって」「見やすいですー😂」
「ではそろそろ次へー👉」
⚓ActiveRecord#cache_version
の生成にDBのtime文字列を使うようにしてパフォーマンスを向上
# activerecord/lib/active_record/integration.rb#L98
- def cache_version
- if cache_versioning && timestamp = try(:updated_at)
+ timestamp.utc.to_s(:usec)
+ return unless cache_versioning
+ if has_attribute?("updated_at")
+ timestamp = updated_at_before_type_cast
+ if can_use_fast_cache_version?(timestamp)
+ raw_timestamp_to_cache_version(timestamp)
+ elsif timestamp = updated_at
+ timestamp.utc.to_s(cache_timestamp_format)
+ end
+ else
+ if self.class.has_attribute?("updated_at")
+ raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
+ end
end
end
つっつきボイス:「英語タイトルだけ見ての予想ですが、今まではタイムゾーンを変えるとキャッシュが飛んじゃったのかな?それならこの修正はわかる」
「ちなみにアクセスがものすごく多いサイトでキャッシュを飛ばすと、最悪の場合アプリが落ちることもありますからね💀」「怖っ」「キャッシュがなくても動きそうなものなのに」「普通に落ちますよ😎: キャッシュが全部なくなってしまうと、サーバーにすべてのレンダリング処理が集中するし、レンダリングが終わらないうちに次々にリクエストがやってくるし」
「アクセスのほとんどないサイトなら、キャッシュを消してもその後でレンダリングされるから別にいいよね、という感じでやれるんですが、Yahoo!ニュースクラスのサイトでキャッシュなくなったら即死」「😱」「なのでそういう大規模サイトはキャッシュも厳密に管理してたりするし」
「で、コミットメッセージを読むと、:usec
形式にすることでタイムゾーンに依存しないようにするようだ」「お、タイムゾーンをUTCにすると速くなるって」「おぉ~」「つまり、どちらかというとパフォーマンス改善がメインのPRということか」
「usecって単位知らなかった...😅」「普通に使いますヨ👓」「あ、msecがミリセカンドでnsecがナノセカンド、そのままだとマイクロセカンドもmsecになってしまって不便だからusecにしてるのかな」「ギリシャ文字のミューμ
がuに似てるからそれでuなのか」
参考: ミリ秒とは - IT用語辞典
ギリシャ文字が使えない環境などではμに形の似たアルファベット小文字の「u」(ユー)を用いて「us」「usec」と表記する場合もある。
同記事より
⚓データベース書き込みをブロックする機能を追加
# 同PRより
ActiveRecord::Base.connected_to(role: :writing) do
Dog.connection.while_blocking_writes do
Dog.create! # 書き込みをブロックしているのでraiseされる
end
end
ActiveRecord::Base.connected_to(role: :reading) do
Dog.connection.while_blocking_writes do
Dog.first # 書き込みではないのでraiseされない
end
end
つっつきボイス:「一瞬考え込んじゃいましたが、このblockは動詞でした」「Rails 6のconnected_to
の制御のようだ」「while_blocking_writes
で囲むと、書き込みしたときだけraiseされるそうです」
「これはどんなときにうれしいんでしょう?」「うーん、あるとしたら、複雑なモデルをカスタマイズしているときなんかに、この部分では書き込みしないと宣言するときとかかなー🤔」「センシティブなデータを扱うときなんかに、誰かが勝手に書き込まないという安心感を得られるとか(この方がありそうかな)」
「プルリクを見ると、primaryとreplicaを使い分けるときなんかにいいかもってありますね」「あーなるほど、Rails 6のマルチデータベース対応の一環か: primaryとreplicaでデータを移行する処理を書いていると、両方に同じ名前のモデル名があることになって危ないけど、これで間違ってもprimaryに書き込まないようにできる☺️」「これは確かに欲しい!😂」「可読性も上がるし😋」
⚓PostgreSQLの最小バージョンが9.3にアップした
# activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L426
private
def check_version
if postgresql_version < 90100
raise "Your version of PostgreSQL (#{postgresql_version}) is too old. Active Record supports PostgreSQL >= 9.1."
if postgresql_version < 90300
raise "Your version of PostgreSQL (#{postgresql_version}) is too old. Active Record supports PostgreSQL >= 9.3."
end
end
つっつきボイス:「まあ新しいRailsでPostgreSQL 9.3を使うことはもうないだろうなー☺️」
⚓番外: MySQLでutf8mb4
文字セットのバリデーションとsupports_longer_index_key_prefix?
を追加
これは例の6.0.0マイルストーンから見繕いました。
# activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb#L117
def supports_longer_index_key_prefix?
if mariadb?
version >= "10.2.2"
else
version >= "5.7.9"
end
end
つっつきボイス:「おw、ちょうど今日これを踏んだ人いましたね〜😆」「いたいた😅」「おー、このプルリクを見るとやっぱりMySQLの5.7.9が境目だし😋」「MySQLはマイナーバージョンまでチェックしないとハマる」「MariaDBがいつの間にかバージョン10超えてるし☺️」「MariaDBはバージョニングまでMySQLと違うものになってるし」
「MariaDB追ってないな〜」「AWS AuroraのチームがMariaDBにかなりコミットしているらしいと聞いてますね」「へぇ〜😳」
関係ありませんが、アザラシとセイウチとオットセイの違いが未だによくわかりません。
参考: アザラシとアシカの違いは?オットセイやセイウチも。写真と文章で紹介 | morigasuki.net
「そういえばutf8mb4
が出てきたので以下の寿司ビール記事↓も貼ってみました」「あ、longer index key prefixは寿司ビールとは別の問題ですね: これはこれで貼っておいていいと思います」「お、そうでしたか💦」
「ともあれ、MySQLのinnodb large prefixは本当に超ハマる問題で、utf8mb4
のカラムをインデックス化しようとしたときに起きる」「確か過去にその記事書いた気がする、と思ったら上の寿司ビール記事↑の中にあった↓」
⚓Rails
⚓Railsでデリケートな情報を扱うには(Ruby Weeklyより)
つっつきボイス:「どちらかというと運用視点かなと」「クレジットカード番号なんかは登録したくないのは当然として」「今どきTLS(SSL)なしでサイト立てるのもありえないし」「今ホットな情報銀行に保存するとか😆」「😆」(しばし情報銀行で盛り上がる)
参考: 情報銀行 - Wikipedia
「ちなみに個人情報を暗号化してデータベースに保存したことある人っています?」「ないかなー」「基幹システムでやったことあるかも」「暗号化した場合にできなくなることについて説明したのに、後になって検索したいとか言われたことならある🤣」「🤣」「無理無理🤣」「暗号化したらLIKEとか使えないし」
「他にはauditとか、Encryption as a Serviceとか」「ログにも注意、あるある: Railsのログをデバッグモードにするともうだだ漏れだし🤣」「後でログ見て腰抜かすヤツ🤣」
「このあたりをもっとガチガチにやりたいなら、たとえば個人情報のカラムはビューで直接レンダリングしないで、JSON経由で遅延レンダリングするぐらいの対策してもいいかも」「よくあるのが、キャッシュの設定をミスってCloudFrontのキャッシュにユーザーの個人情報ページが乗ってしまう事故⚠️」「🤣」「これは知っておかないと踏みそう😅」
「そういえばインドの旅館で、ルーターがキャッシュしてたせいで他人のマイページが見えてしまったという話ありましたね」「ひぇー🤣」「それはひどい🤣」「インターネットが高かった昔はそういうのが結構ありましたね: HTTTPプロトコルが主流だった頃」「マイページのURLがユーザーによって変わらない場合に、誰かがそのページを開いた後に別の人が自分の部屋で開くとそのページがキャッシュ経由で見えちゃうという現象ですね」「今はTLS(SSL)化されたことで経路レベルでは起きなくなりましたね」
「こうして見ると、かなり手広い記事: ごく常識的なことを網羅的に書いてあるし、センシティブな情報について意識したことない人がひととおりチェックするにはよさそう!」「無味乾燥なチェックリストよりはいいかも」「これ読みながらやればできそう」「一度は読んでおくべき」「もう少しカテゴリごとにグルーピングしてくれたらもっといいかな」「思いついた順に書いてるのかも?」「これ、翻訳したいです😍」
⚓RailsのscaffoldとTDDは相性が悪い(Ruby Weeklyより)
つっつきボイス:「scaffoldでテストコードを生成するだけだったらマジ無意味😆」「確かに😆」
⚓dpl: travis-ciのデプロイツール集(Awesome Rubyより)
- リポジトリ: travis-ci/dpl
つっつきボイス:「Travis-CIからデプロイするときのスクリプト集か」「割とズラッとありますね」
ここからCapistranoの話題になりました。
⚓Capistranoは今も優れもの
「デプロイといえば今日ちょうど社内のチームミーティングで久しぶりにCapistranoの話をしたので簡単に」「すごくいい話でした😋」
「Capistranoって最近あまり話題にならないんですが、実はツールとして十分枯れていて完成度が高いなって改めて思ったわけです: Dockerでやろう勢からすればいろいろ言いたいことはあるかもしれませんが😆」「😆」
「sshしてgit pullして、シンボリックリンク張り替えてRailsリスタートして、みたいなデプロイだったらもうCapistranoで必要十分じゃないかって」「ロールバックも履歴管理もやってくれるし、Railsサーバーの再起動だけしたい、なんてニーズにも応えてくれるし、やっぱりよくできてる😍」
「で、最近Capistranoって名前をあまり見かけないなと」「検索すると2年前の記事とか出てきましたけど😆」「完成されてるから逆に話題にならなさそう?」
「でチームミーティングでは、最近加わった人がCapistranoの使い方がよくわからないという話をしてくれたので、ちょっと詳し目に解説しました」「Capistranoの詳しい話をあんなに聞けたのはマジ初めてでした」
「話しながら、実はCapistranoのいい使い方がよくわからなくて困ってる人が他にもいるんじゃないかって思ったわけですよ: ネットを見てても、Capistranoで十分じゃね?って思えるような内容をDocker-composeで必死にやってる記事をゴロゴロ見かけるし😆」「あーわかる😆」「本当にやりたかったのはsshしてデプロイしたいだけなのに、みたいな😆」「ついにはDockerに挫折して手動でsshしてgit pullしてたりとか😆」
「ともあれCapistranoをロストテクノロジー化するのはあまりにもったいないので、改めて盛り上がるといいなと」「同意」「特に最近Railsを始めた人だとCapistranoというこんな便利なツールがあることを知らないこともあるかもしれないし」「それありそう」「BPS社内ではCapistranoはもう空気のように当たり前に使われているので、改めて説明する機会が意外になかったなー」
「単にcap deploy
するだけだとCapistranoの具体的な動きを知らずじまいになってしまいがちだし🤔」「そういえばChefやAnsibleを説明するときに『これはCapistranoと似たような振る舞いでして』と話したら( ゚д゚)ポカーンとされたことあったし😆」「😆」「Chefでデプロイまでやるのはしんどくないですか?」「しんどいです😭なのでもうやめようかなと」「😆」「Chefはもともとプロビジョニングツールだし、デプロイとは概念が違いますしね🧐」「ChefはChef料理人がいないといろいろツライ」
参考: デプロイとプロビジョニングの違い - amichang's blog
「で、さっきのTravisデプロイのリポジトリはというと」「puppetとかありますけど😆」「puppetを呼ぶんだろうか😆」「engine_yardとかもあるから、普通にシェルで叩くのと同じようなこともできそうかな」「取りあえずやれることは何でもここに置いてある感」「メンテされなくなったものがあったら消しといて欲しいな(ぽそ」「誰も消しに来ないんですよね😂」「😆」
参考: オープンソースの運用管理・運用自動化 / Puppetとは
⚓Rubyで早速サーバーレスやってみた(Awesome Rubyより)
つっつきボイス:「いまが旬のヤツですね」「動かしてみた人います?」「まだー」「そうそう、このつっつきが終わったら、今日社内勉強会で発表したAWSアットアグランスのスライドをお見せしますよ😋」「😋」
参考: AWS Lambda RubyでNative Extensionsを使用するgemを使うには?serverlessも使ってみた! - GA technologies Tech Blog
⚓その他Rails
⚓Ruby
⚓modulation: Rubyの依存関係を明示的に管理(Ruby Weeklyより)
- リポジトリ: ciconia/modulation
つっつきボイス:「gemの管理?、モジュール同士の依存関係の管理?、どうやらモジュールをimport/exportするローダーっぽい🤔」「最近のJavaScriptみたいな」「もしかしてRubyのモジュールの扱いが気に入らない人が作ったのかも?😆」「あーなるほどね☺️」
参考: import文 -- モジュール · JavaScriptの入門書 #jsprimer
「この書き方にそんな匂いをそこはかとなく感じる」「確かにESモジュールっぽい」「RubyだからDSL使えるでしょ!みたいな勢いに乗って書いてたりして😆」
# 同リポジトリより
export :User, :Session
class User
...
end
class Session
...
end
require 'modulation'
Models = import('./models')
...
user = Models::User.new(...)
...
「Ruby世界にはこういう分野もあるんだなって思いますね: 最近MatzがRubyのシンタックスハイライトは統一しなくていいみたいなことを言ってた気がするんですが、自分もいろんな書き方があっていいと思うし☺️」「☺️」「こういうgemが登場する余地があるぐらいだし、統一しなくてもいいんじゃないかなって😆」「あるいは無理だったり☺️」
⚓Rubyで行う高度な例外ハンドリング
Ruby 2.1からException#cause
というのが入っているそうです。
つっつきボイス:「どの辺がadvancedかなー?」「ああ、こういうネストした例外処理って、beginでraiseされ、rescueでまたraiseされてさらにrescueされてみたいな感じになりそう: nested rescueってマジ勘弁😭」「こーれーはーキツイ😅」
# 同記事より
class A < StandardError; end
class B < StandardError; end
the_exception = nil
begin
begin
raise A
rescue
raise B
end
rescue => exc
the_exception = exc
end
the_exception # #<B: B>
the_exception.cause # #<A: A>
the_exception.cause.cause # nil
「個人的にはですが、Rubyでrescueだけかけるのがあまり好きでない: どれを捕捉するのかわからなくなりそうでコワい😰」「Rubyのチェリー本↓にもむやみにrescue使うなって書いてあった気がします」
「ところがRailsの公式な手順だかチュートリアルだかで、コントローラの中で最後にrescueして、ダメだったときにそれで拾うみたいな書き方が確かあって、しかもRubyMineだとそこでインデントが崩れるという😆」「😆」
「記事の人は『cause
スゴイから!』って感じで書いてますね☺️」「ところでこのreraise_with
って😆」「リレイズ😆」「ファイナルファンタジー臭しかしない😆」「センス光る😆」「😆」「いやーダメでしょーそれやっちゃ😆」「reraise_with
の中でまたreraise_with
してる時点で、これは使っちゃダメだってオレの心がそう言ってる😆」
「まあ内側でraiseしたのを外でもう1回raiseするときにエラーオブジェクトを握りつぶさずにすべてをスタックトレースで辿れるようにしたってことなのかなとは思うんですが、もっといいベストプラクティスがあるんじゃないかしらと☺️」
⚓追いかけボイス
参考: ネストした例外の場合、causeも自動的に出力されるようになった -- サンプルコードでわかる!Ruby 2.6の主な新機能と変更点 - Qiita
⚓Fiberってなぜあるの?(Ruby Weeklyより)
つっつきボイス:「GuildじゃなくてFiber?」「例のRubyのライブラリです」「Fiberは大量のアクセスをさばかないといけないマルチスレッドアプリを書くのにはよさそうな設計だなと思いますね」「永遠に起こされないFiberとか作られそうだけど😆」
⚓2019 Fukuoka Ruby Awardの募集開始(Ruby公式ニュースより)
- 元記事: 2019 Fukuoka Ruby Award Competition - Entries to be judged by Matz
- イベント: myfukuoka.com – 2019 Fukuoka Ruby Award: Guidelines for Applicants
- エントリフォーム: RubyAward_ApplicationForm_2019.doc
賞金100万円ですよ。
ちなみにRuby bizグランプリの応募受付は終了しました。
つっつきボイス:「この間のRuby忘年会で高橋会長が呼びかけてたので」「Ruby bizの方はBPSも応募したのでエントリに載ってますヨ(受賞はしませんでしたが)」「知らなかった!😳」
⚓その他Ruby
- 元記事: Ruby has no class methods - DEV Community 👩💻👨💻
- 元記事: Ruby/Ruby on Rails conferences to visit in 2019 - DEV Community 👩💻👨💻
- 元記事: A Weird and Wonderful Trip through Ruby’s Standard Library(RubyFlowより)
Rubyの領土を分捕るには新陳代謝の早いWeb領域をとらないといけなくて、これを置き換えるのは正気な言語ではちょっと難しいのではないか…。安定しているWebはJavaやGoがいるし、書きすてWebはPHPがいるので激戦区
— 成瀬 (@nalsh) December 3, 2018
⚓Ruby trunkより
⚓もっとRefinementしたい
- Feature #15373: Proposal: Enable refinements to `#method` and `#instance_method` - Ruby trunk - Ruby Issue Tracking System
- Feature #15374: Proposal: Enable refinements to `#method_missing` - Ruby trunk - Ruby Issue Tracking System
# 同issueより
# Access key value with method
using Module.new {
refine Hash do
# name is Symbol or String
def method_missing(name)
self[name.to_sym] || self[name.to_s]
end
end
}
hash = { name: "homu", "age" => 14 }
pp hash.name
# => "homu"
pp hash.age
# => "age"
つっつきボイス:「どちらも同じ方からのissueです」「refinement、消したい人もいるかと思うとこういうのも☺️」「そういえばはてブでrefinement対決みたいな記事が上がってた気がする」「refinementしないといけないようなコードは使いたくないな〜😅」
「よく見たら、これ#method_missing
でやりたいって...」「な...んだと...?😆」「つまり今はできないのか!」「禁断の魔法っぽい」「どんないいことがあるんだろっ?」「これはもうrefinement強者にお任せしたい」
そういえばRuby 2.6ではpublic_send
などで呼ばれてもrefinementが効くようになったんですね。
参考: サンプルコードでわかる!Ruby 2.6の主な新機能と変更点 - Qiita
⚓クラウド/コンテナ/インフラ/Linux/Serverless
⚓clair: コンテナの脆弱性を静的チェック
CoreOS社のロゴのデザインがちょっと好きです。
⚓SQL
DB WeeklyはAWS reInvent一色な感じでした。
⚓SQLインジェクションのテクニック4種(DB Weeklyより)
つっつきボイス:「ここにいる皆さんはだいたいご存知なんだろうなと思いつつ」「SQLインジェクションは知っておく方がいいですよね: 自分が使うことはないにしてもw、アプリで脆弱性が発覚したときに影響範囲を推測するためにも知っておくのが大事🧐」「今すぐサイトをたたまないと危ないのか、このログを見て問題なければ大丈夫なのか、とかを見極められないと」
⚓Neo4j: グラフデータベース(DB Weeklyより)
- 元記事: Neo4j Graph Database 3.5: Everything You Need to Know [GA Release]
- リポジトリ: neo4j/neo4j
- サイト: Neo4j Graph Platform – The Leader in Graph Databases
つっつきボイス:「Neo4j、どこかで聞いたことある」「グラフデータベースって、グラフ理論のグラフでしょうか?」「ですね」「やっぱり」「グラフデータベースはいろいろありますね」
参考: グラフデータベースとは? | アマゾン ウェブ サービス (AWS)
⚓その他SQL
- 元記事: Pavel Stehule's blog: PostgreSQL 12 - psql - csv output(Postgres Weeklyより)
- 元記事: データベーステーブル設計の基礎の基礎〜エンティティの抽出・定義から正規化まで - エンジニアHub|若手Webエンジニアのキャリアを考える!
つっつきボイス:「psqlでCSVを吐き出せるという短い記事です」「お、CSVを書き出すだけなら前からありますが、psqlのオプションで書き出せるなら、それなりに意義がありますね: 権限がなくても書き出せるから」「あー」
「PostgreSQLには元々SELECTしたものをファイルに書き出せるOUTFILEというものがあるんですけど、これを使ってCSVを書き出すにはそのPostgreSQLユーザーにOUTFILEの権限がGRANTされてないといけないし、かつそのPostgreSQLユーザーが出力先のファイルシステムに書き込み権限を持っていないと、できない」「そっかー!」
「この障壁が意外に高くて、ちゃんとセキュアに設定されたPostgreSQLではOUTFILE権限を与えていないのが普通なんですね: 特にSE Linuxがtargetedモードで動いていたりするとPostgreSQLのプロセスから/tmp
にアクセスできなかったりしますし」「なるほどー!!」「まあ1度標準出力に出してからゴニョゴニョすればやりようはあるんですが: この記事のはpsqlコマンドのオプションということだからそれを回避できるということだと思います」「こういうことでハマった経験がないとわからない微妙な嬉しさ😆」「😆」「こうやって話を聞くとありがたみがわかってくる」
⚓JavaScript
⚓stateofjs.com: JavaScriptの最近の傾向のまとめサイト
周期表っぽいデザインです。
参考: 周期表 - Wikipedia
つっつきボイス:「サイトデザインやたら凝ってます」「もうみんなES6でいいでしょっ😆」「JavaScript開発者の給与分布まで載ってるし」「ごく...」「こういうアンケートに答える人はだいたい強者ばっかりですけどね😆」「😆」「😆」「サイトを作る側にしてみれば給与分布を上げ底するインセンティブありまくりだし😆」「あーたしかに」「正直に書くメリットがないという😆」「答える人も高めに答えるだろうし」「そこのところを差し引かないとですね🧐」
⚓CSS/HTML/フロントエンド/テスト
⚓最近のCSS Reset事情
つっつきボイス:「CSS Reset、久しぶりに見た」「今日これの翻訳記事を見た気がします」「おぉー」
ありました↓。
参考: CSSリセットの現状、どのCSSリセットが適しているか選ぶ際の指針 | コリス
「そういえば、特にBootstrapで使われているCSSリセットファイルのコメントでは、どうしてそういうリセットにしたのかという理由が書かれていて、読んでいてへぇ〜っと思いますね: たとえばIEのこのバージョンではこういう問題が発生するからとか、こんなブラウザバグがあるとか」「お〜」「勉強になりそう!」
後で調べると、Bootstrap 4ではReboot.cssというものが使われていました。
参考: Reboot · Bootstrap
参考: Reboot.css Bootstrap製Reset.cssからCSSの新しいスタンダードを読み解く | Goodpatch Blog
⚓言語
⚓最近のMicrosoftの動向
- 元記事: [速報].NET Coreがデスクトップアプリケーション対応。Windows Forms/WPF/UI XAML Libraryもオープンソース化。Microsoft Connect(); 2018 - Publickey(Publickeyより)
- リポジトリ: dotnet/wpf
- リポジトリ: dotnet/winforms
- リポジトリ: microsoft-ui-xaml
あとこんなのも↓。
追記: その後本当になりました。
⚓PHPむずい
このPHPの暗黙の型変換表を暗唱できない人は、== による比較をしてはいけない。 #YYPHP pic.twitter.com/vFTuRsiZzq
— Reo💻 (@reoring) November 30, 2018
つっつきボイス:「これはもうペチパー必須科目😆」「😆」「覚えられる気がしない...」
⚓その他
⚓GitHub Leaning Labとは
- サイト: GitHub Learning Lab
つっつきボイス:「詳しく見る暇なしのまま貼ってみました」「GitHubを使うためのチュートリアルか」「これはいい試みだと思いますね👍」
あとこんなのも↓。
⚓番外
⚓さいなら~
つっつきボイス:「ポケベル終わりましたねー☺️」「停波だから完全終了」「ポケベル世代?」「のはずですが使ってない😆」「世代じゃないけど使ってない😆」「親父が記者だったので背広のポケットで見つけたことあるだけでした: ベル鳴らす機能しかない最初期のヤツ」
「📟」というポケベルの絵文字があることに今頃気づきました。
今回は以上です。
「お疲れさまでしたー」「ちょっと早いけどよいお年を〜」「よいお年を〜」
その後の懇親会🍕🍺では、AWS reInventアットアグランスのスライドで盛り上がりました。参加いただいた皆さま、ありがとうございます!
お便り発掘
週刊Railsウォッチ(20181210)update_columnは要注意、DBカラムコメントは書こう、個人情報扱いの注意点、Capistranoはやっぱりいいほか
- [ruby]
Capistrano、もっといい方法がさすがにできているのかなあと思いながら使い続けているんだけど、いいんだ! よかった!
update_*は本当に迷うし、度々ここで紹介されてるQiitaの記事を見る気がする...
Capistranoは使いたいけど、なかなかいい文献にたどり着けないんだよなあ...未熟https://t.co/ryKG0ammux— Aoshi (@arsley_) December 10, 2018
バックナンバー(2018年度後半)
週刊Railsウォッチ(20181203)Railsのglobalidとは、AWS LambdaがRubyに対応、JSはPromiseを最初に学べほか
- 20181112 Ruby 2.6.0-preview3リリース、非同期スレッドのテストはつらい、MySQL 8のGROUP BYほか
- 20181105 DBマイグレーション9つのコツとハマった話、Railsのモデルとディレクトリの設計ほか
- 20181029 特集『肥大化したActiveRecordリファクタリング7つの方法』今ならどうなる?Redis 5のストリーム機能ほか
- 20181022 Railsの名前空間地獄とrequire_dependency、PostgreSQL 11がリリース、clean-rails.orgほか
- 20181015 Rails初心者と一発でバレる書き方、次のVue.js構想、RubyのOpenStruct、Twilioほか
- 20181001 Railsアップグレード記事と各種支援ツール、CLI向けRubyワンライナー集、Rubyアプリをワンバイナリ化ほか
- 20180925 Rails大規模支払サービス開発のノウハウ、RailsのMySQLがutf8mb4に移行、Rpush gemほか
- 20180918 ビューテンプレート探索が高速化、mini_scheduler gem、レガシコントローラのリファクタリングほか
- 20180910 公開つっつき会#2、RSpecは何を参考にするか、イベントソーシング、marginalia gem、負荷テストツールvegetaほか
- 20180903 次世代アップローダーgem「Shrine」、RSpecをどこまでDRYに書くか、Rubyのmainオブジェクトの秘密、GitLabのCookie利用許諾機能はエライほか
- 20180827 Ruby Prize 2018募集開始、Interactor gemとReader Object、書籍『Real World HTTP』、Basecampのヒルチャート機能ほか
- 20180820 Railsで構築されたサイト40選、Deviseはつらいよ、ARのスコープとクラスメソッドの使い分けほか
- 20180813 Rails 5.2.1リリース、sanitize_sql_arrayは5.2からpublicだった、Dev.toがRailsアプリのソースを公開ほか
- 20180806 Rails 5.2.1.rc1リリース、Railsガイド日本語版が5.1に対応、Regexp#match?ほか
- 20180723 Railsdm Day 3 Extremeを後追い、PSDにはZeplin.io、好みの分かれるJSX、負荷テストツール比較ほか
- 20180709 Rails Developers Meetup Day 3 Extreme今週末開催、RailsのSTI/キャッシュ/添付ファイル/Redis/PDF出力、ECMAScript 2018、プロフェッショナルIPv6ほか
- 20180702 Ruby 2.2メンテ正式終了、Ransackがつらくなるとき、書籍『Domain-Driven Rails』、GitHubの高可用MySQLほか
- 20180622 Railsの需要未だ巨大、Unicode 11.0リリース、WebDriverがW3Cで勧告、Flutter.io、2封筒問題ほか
- 20180615 TTY gemとHTTPClient gemは優秀、Rubyの謎フリップフロップ、ちょいゆるRubyスタイルガイドほか
- 20180608 特集「RubyKaigi 2018後の祭り」、
Enumerable#index_with
は優秀、コントローラから@
を消し去るほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。
PostgreSQLでpsqlするときには、以下の3つのユーザーが関連します:
-U
オプション等で指定されるPostgreSQLで管理されているPostgreSQLユーザー(PostgreSQL管理内のDBユーザー)OUTFILE記述の場合、BではGRANTとして明示的にOUTFILE権限が必要な上に、Cで出力先にファイルを書き込む権限が必要。
そして、PostgreSQLプロセスがSE Linuxのtargetedモードやapparmor経由で動いている場合、ユーザーディレクトリはそもそも書き込もうと思ってもファイルを書き込めなかったりする設定になっていることが多いです。
今回のcsv output機能では、BのOUTFILE権限はいらず(SELECT権限は必要)、Aのファイル書き込み権限さえあればいけるので、よくある「お客さんからXXXの集計データが欲しい」と言われたときに、ログインしたメンテユーザーの
~/work
ディレクトリに簡単に出力できるようになった、という話になります。ただ、元々OUTFILEしなくても出力結果を標準出力に出すことはやろうと思えばできました。
※以下のpsqlコマンド版の話。COPY TO形式の方はPostgreSQLユーザーでファイル書き込みするのでB、Cの権限両方必要なはず。
参考: postgresでcsv出力 \- Qiita
↑の記事のCOPY TOの補足に「DBサーバーから見たパス」という記述もありますが、確かにPostgreSQLプロセスが間違って越境しないようにPG_DATAディレクトリにchrootして動いてたりすると、さらに混乱はありそうではある。