Ruby Weekly #370: 日本語サマリー
職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。
Highlights
do; end
ブロック内rescue
対応。yield_self
新規追加。- bundler 同梱。
- 同一ネームスペース内で見つからなかった定数をルートネームスペースから探すのがなくなった。
RubyGems シリアライゼーション脆弱性を解説した Aaron Patterson 先生。 gem のチェックサムが YAML で保存されているのが原因。 RubyGems.org はこの脆弱性で攻撃された痕跡はない。 シリアライズ可能なオブジェクトをホワイトリストすることで解消済み。
レポート用 Rails engine。
Introducing hanami-cli: A New Framework for Command Line Tools
hanami-cli を紹介した、Hanami 作成者 Luca Guidi 先生。 thor では実装しづらい下記機能がある:
- サブコマンド。例えば
$ hanami generate action
のgenerate action
。 - 拡張性。外部 gem が Hanami にサブコマンドを追加できるようになった。
Hanami じゃなくても使えるので、thor の代替案として考えれば良い。
同一ネームスペース内で見つからなかった定数をルートネームスペースから探すのが Ruby 2.5 からなくなった。その経緯を語る Redmine チケット。
Surrealist gem に対応するように、Array
と ActiveRecord::Relation
のモンキーパッチを検討した話。
下記条件全部満たせなければ、モンキーパッチやめたほうがいいと。
- これ以上のモンキーパッチはない。
- モンキーパッチしたコードに依存しているものが壊れない。
- モンキーパッチ以外の選択肢がない。
- 新しいインタフェースが作れない。
カンファレンスを初めて主催した経験談。地方カンファレンスがなくなってきたのがきっかけ。
- 昔あったナッシュビル市の Ruby Hoedown カンファレンス主催者から許可を得た。
- ドメイン取得(自腹)。
- 会社設立(自腹)。
- ロゴ発注(自腹)。
- キーノート登壇者を招待した。
- CFP を 1.5 ヶ月開催。もうちょっと長くすればよかった。
- 予算計算。$199 のチケットを 175 枚売れば黒字。
- 会場探し。
- スポンサー探し。大変だったため、プランはもうちょっと安くすればよかった。
- 登壇者宿泊 + 交通費負担することにした。
- チケット発売。SNS + Ruby Flow + Reddit で宣伝。87 枚売れた。
- カンファレンス 3 日間開催。
赤字だったが、Ruby コミュニティに貢献できた充実感で、来年も開催予定!
News
Rails 5.2 では、暗号化・署名付きクッキーの有効期限が設定可能に。
台北の RubyElixirConf Taiwan 2018、CFP 開始。
Mastering Ruby: Strings and Encodings 本発売。
Tutorial
Receiving and Parsing Email in Rails 5 Using Griddler and Mailgun
Build a SaaS App in Ruby on Rails 5 本の抜粋。Rails 5 + Griddler + Mailgun でメールを受信・パースする手順。
- ngrok で手元マシンへの URL を用意。
- Mailgun で受信したメールを ngrok URL に転送するように Mailgun を設定。
- Griddler gem を Rails アプリにマウント。
EmailProcessor
オブジェクトでパース・処理を実装。
Rails 5.2 の HTTP2 Early Hints を発表した Eileen Uchitelle 先生。Rails がレスポンスを 2 つ返すようになる:
- Early Hints(HTTP ステータス 103)
- 通常のレスポンス(HTTP ステータス 200、404、500 など)
Early Hints はブラウザーが優先的にダウンロードするファイル(JavaScript、CSS など)の指定。Rails での検証手順も記載されてる。
Ruby 2.5 スタックトレースの見た目改善。エラー発生行番号が一番下になった。長いスタックトレースの上までスクロールすることがなくなって便利。しかし Rails・RSpec では効かない。
巨大メソッドをクラスに抽出した話。
Ruby のよく知られてないメソッド。
Integer#digits
(Ruby 2.4 以降)#tap
Array#values_at
Hash#transform_values
(Ruby 2.4 以降)Kernel#itself
(Ruby 2.2 以降)Array#count
Enumerable#cycle
Paperclip で Rails GraphQL API から画像を S3 にアップロードした話。REST アプリならドキュメンテーションはいっぱいあるが、GraphQL アプリは一切ない。画像を Base64 文字列に変換してから mutation の引数として Paperclip に渡した。
HexaPDF gem の PDF ファイル読み込み処理解説。
- PDF ファイルは不特定多数のストリームで構成されてる
- 各ストリームには不特定多数のフィルターが指定されてる
- フィルターはストリームデータの解読方法を定義している(例:JPEG 画像は
DCTDecode
フィルター、ASCII 文字列はASCIIHexDecode
フィルター) - フィルターはそれぞれ
HexaPDF::Filter::ASCIIHexDecode
のようなモジュールで実装されてる - ストリームは
HexaPDF::StreamData
オブジェクトでカプセル化 - ストリームのデータは非同期で読み込むため、Ruby の Fiber 採用
Rails フォルダー構造まとめ。
RSpec で深階層の nested attributes を指定した話。手で組み立てるのが大変だった。先輩に相談したら、ログからコピペすることになった。
Tools
nullalign: Generate Warnings for Missing Not-Null Constraints
NOT NULL
制限のない validates presence: true
を検知してくれる nullalign gem。
Code
ActiveRecord + PostgreSQL 10 パーティション管理用 gem.
Ruby Weekly #369: 日本語サマリー
職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。
Highlights
Symbol
と String
の不一致がバグの根源なので、Ruby から Symbol
を捨てないかという提案。
- 下位互換性を維持するには、
Symbol
を#freeze
したString
にすれば良い。 Symbol#to_s
から#freeze
されてないString
を返すようにする。#hash
を同等にする必要がある。Symbol#hash
計算が 2〜3 倍速いから、String#hash
計算もSymbol#hash
に合わせたい。
Fixnum
Bignum
捨てたし、Symbol
も捨てれるのでは?と。
Ruby Rogues の Charles Max Wood 先生主催の Ruby Dev Summit 分散型カンファレンス(物理的開催地はなく、参加者はみんな動画配信やチャットで交流・登壇)。
get_schwifty: Render Portions of Rails Views in a Background Job Queue
重い partial を ActiveJob で render、ActionCable でブラウザー上非同期描画する gem。
株式会社デジカの Chris Salzberg 氏が RubyKaigi でトークを発表した話。たまたま Matz のキーノートと同じく、モジュールを題にしてた。しかし「モジュールはクラスではない」と言わんばかりの Matz 発言が Salzberg 氏のトークと矛盾してたのでちょっと困った。Module
は Class
だからこそ Ruby ならではの Module Builder パターンが可能。
-rubygems
に対応するための ubygems.rb
が削除された、というちょっと面白いコミット。
Gusto 社の給与システムが関数型 Ruby になるようにリファクターした話。
- PFaaO パターンで純粋関数オブジェクトを実装した。給料計算関数オブジェクトを例として挙げた。
- 純粋関数オブジェクトなので、メモ化していても参照透過性が維持されてる。
- 給料計算関数オブジェクトの中の税金計算メソッドを税金計算関数オブジェクトに抽出した。
- ActiveRecord モデルそれぞれに対して immutable な Value Object を切って、純粋関数オブジェクトにValue Object のほうを渡すようにした。
News
Hanami v1.1.0.beta2 リリース翌日に、バグ解消で v1.1.0.beta3 リリース。
Tutorial
Surrealist: A Gem to Serialize Ruby Objects According to a Defined Schema
シリアライズ用スキーマ定義 surrealist gem の紹介。データ型定義やキー camelize 機能など込み。
- Angular プロジェクトの該当 directive ファイルを開く関数
Ruby コアの delegate.rb をコードリーディングした話。
Delegator
が継承しているのは、不要なメソッドを省略されたKernel
。#initialize
#method_missing
メソッドはDelegator
にて実装されている。- デリゲート先オブジェクトの accessor は
SimpleDelegator
など子クラスで実装されている。 #method_missing
がチェックするのはデリゲート先オブジェクトと一部省略したKernel
。
Hash#fetch
でデフォ値を返すようにする。ブロック渡せば遅延評価もできる。
筆者著作の Domain-Driven Rails 本の抜粋。メソッドを 2 つのメソッドに分解することで Event Sourcing するというルールの解説。2 つのメソッドとは:
- イベントを発行するメソッド
- イベントの効果を適用するメソッド
Ruby 配列いろいろ
#initialize
方法いろいろ#slice
方法いろいろ#insert
方法いろいろ<=>
挙動|
挙動&
挙動
Ruby 2.4 では Enumerable#min
Enumerable#max
Enumerable#minmax
が速くなった!
validate uniqueness:
使用時の高速化案。
筆者作品の UniqueValidationInspector gem では、インデックスのない validate uniqueness:
を検知できる。
Ruby バージョン確認方法まとめ
環境 | 確認方法 |
---|---|
irb | RUBY_VERSION |
rvm | rvm current |
rbenv | rbenv version |
コマンドライン | ruby -v |
コマンドライン | which ruby |
コマンドライン | gem env |
Story
A Reddit AMA with the Authors of 'Effective Testing with RSpec 3'
Effective Testing with RSpec 3 著者たちの質疑応答 Reddit スレ。
Python コードのパフォーマンスを最適化した Richard Schneeman 先生。
Ruby との共通ルール:
- ダブってるロジックを省けば軽くなる。
- オブジェクトのインスタンス化を省けば軽くなる。
- オブジェクトのシリアライズを省けば軽くなる。例:シリアライズした配列を引数として渡すよりも、要素を渡したほうが軽い。
- ループ内のリテラルを省けば軽くなる。リテラル=オブジェクトのインスタンス化なので。
- 不要なロジックを省けば軽くなる。あり得ない
if
文の分岐点など。 - メソッドを省けば軽くなる。効果はそんなに大きくないので、このルールに関しては無理しなくて良し。
- ベンチマーク必須。
- キャッシュするなら、オブジェクトのインスタンス化ルールは破って良し。
レガシー Rails アプリに呆れて、18 ヶ月も Rails を避けていた経験で得た知見。
- 悪いのは Rails 自体ではなく、Rails の用途に合わないアプリ
- 何でも gem に依存させるのも良くない
- Rails はドキュメンテーションが充実してる
Opinion
default_scope
ではなく明示的に scope
使おうという主張。
new
したモデル属性はdefault_scope
で設定されちゃうのが予期せぬバグの元。default_scope
を外すことは辛い。unscoped
だとアソシエーションのスコープまで外れちゃったりするから。
Tools
Ruby 上級者向け書籍。
- オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方
- Rubyのしくみ -Ruby Under a Microscope-
- Effective Ruby
- Ruby Way 第2版 (Professional Ruby Series)
- Mastering Ruby Closures: A Guide to Blocks, Procs, and Lambdas
- Rails, Angular, Postgres, and Bootstrap: Powerful, Effective, Efficient, Full-Stack Web Development
- Service-Oriented Design with Ruby and Rails (Addison-Wesley Professional Ruby Series)
Code
render_async 1.0: Render View Partials Asynchronously via Ajax
Rails ビューの partial を AJAX で非同期ロードする gem。
Bing Maps API クライアント用 gem。
Ruby Weekly #368: 日本語サマリー
職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なあらすじを書くようにしています。そのあらすじをここでまとまさせていただきます。くだけた日本語で失礼いたします。
Highlights
Aaron Patterson 先生が Ruby ヒープを可視化した話。ObjectSpace
でヒープを JSON で取得し、ChunkyPNG
で PNG 画像に落とした。
Ruby 2.5 の Object#yield_self
登場。Elixir の |>
演算子相当。筆者見解では、コードのフロー的には読みやすくなるが、ボイラープレートが多い。
@schneems 先生の外国人として RubyKaigi に参加する豆知識。
- 内容はテクニカルもの重視。スライドはコード大量。
- 日本語トークはイヤホンで同時通訳あり。
- トーク後の質疑応答は、司会が頑張って通訳。
- 英語トークよりも日本語トーク聞いたほうがいい。あとからアップロードされる動画には字幕・吹替がないから。
- 英語圏のいわゆる hallway track (参加者同士の交流)は基本ない。日本人は真っ赤の他人に話しかけたり質問したりするのに抵抗があるから。
- 日本のレストランが狭くて大人数で食事するのが難しい。10 人座れるのは居酒屋ぐらい。そして居酒屋はあまり美味くない。
- 食事の相手は日本語が喋れる人がいれば非常に助かる。美味い店は英語のできない店が多いから。
- Yelp はあるが、tabelog 使いましょう。
- コンビニ飯は意外と美味い。
日本人参加者へのお願い:外国人参加者に積極的に話しかけてください!
Thoughtbot 社員がテスト高速化のためにデバッグした話。
- spec_helper.rb 部分的コメントアウトで下記犯人が判明:
- 全テスト用の
config.before(:each)
に feature テストのセットアップが入ってた。type: :feature
などのメタタグで用途別に分けた。 - 全テスト
DatabaseCleaner.strategy = :truncation
になってた。メタタグで:truncation
:transaction
適用した。
- 全テスト用の
- FactoryGirl 部分的コメントアウトで
after(:create)
のレコード大量作成が判明。trait
に移し、再発防止として ActiveSupport Instrumentation でレコード作成数を見える化した。
Ruby 3x3 ベンチマークとして作られた NES エミュレーター OptCarrot の紹介。
Using Python's scikit-learn Machine Learning Library via PyCall
PyCall gem 経由で Python の scikit-learn 機械学習ライブラリーを Ruby から呼ぶ手順。
News
サポート終了済みの Rails 4.2 は、デグレ対応のため 4.2.10 リリース。
macOS High Sierra の fork 挙動が変わったため、Puma ワーカーが失敗する現象発覚。
未解消!
Tutorial
#eql?
#hash
のモンキーパッチで
- 異なるキーで同一値のハッシュ
- 同一キーで異なる値のハッシュ
- 時間限定キーのハッシュ
をインスタンス化した話。Fixnum
、String
、Symbol
は C レベルで塞がれているが、それ以外のオブジェクトはモンキーパッチできた。
良い子は真似しないでね。
Object#try
が有害だという主張。オブジェクトがヌルな場合でも、メソッドが定義されていない場合でも、エラー投げずにヌルを返し、正当なエラーまで隠滅してしまうから。
代替案:
- ヌルチェックを明示的な
if
文で。 - デメテル法則厳守。
- DB レベル
NOT NULL
でヌルを防ぐ。 - 暗黙の
to_s
などに頼らず、明示的に該当データ型に変換。 - ダックタイピング。
- ヌルオブジェクトパターン。
&.
は OK。ヌル以外のオブジェクトでメソッドが定義されていない場合はNoMethodError
を投げるから。
crontab + whenever gem で Sidekiq ジョブを定期的に起動する手順。
graphql gem で Rails アプリの GraphQL API を実装した話。
How To GraphQL チュートリアルも参考に。
Rails 5.1 で React のアイデア付箋 CRUD アプリの実装手順。
- Rails API 実装。
- Facebook 社の Create React App で新規 React アプリ生成。
IdeasContainer
IdeaForm
などコンポーネント実装。- NPM の axios ライブラリで API を叩く。
- rack-cors gem で CORS 制限解消。
- NPM の immutability-helper ライブラリで React 上データのイミュタブル性を保証しながら更新。
- React Developer Tools ブラウザー拡張で状態監視。
link_to
などにパスを指定する方法いろいろ。
edit_admin_exercise_path
edit_admin_exercise_path
ヘルパー[:edit, :admin, exercise]
配列{action: :edit, controller: "admin/exercises", id: exercise.id }
ハッシュ/admin/exercise/5/edit
文字列ハードコード
PDF 非同期生成の生成完了通知を ActionCable で実装した話。Michael Hartl 先生の Learn Enough Action Cable to Be Dangerous を参考にしていた。
Ruby 感情分析ツールまとめ。
- sentimental gem: 辞書ベース
- sentimentalizer gem: 機械学習ベース
- Ankusa gem: ベイズ分類器ベース
- Hoatzin gem: SVM 分類器ベース
- Classifier gem: SVM 分類器ベース
- Eluka gem: SVM 分類器ベース
- Tensorflow Ruby API
Ruby Weekly #367: 日本語サマリー
職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。
Highlights
Ruby ツールまとめ。
mutant gem のミュテーションテストでモジュールの設計を見直した話。mutant が @unpublished_events = []
を @unpublished_events = nil
に変えたのに、テストがそのまま通った。原因は getter がメモ化していたから。getter が必要なののは、#initialize
で設定していないから。#initialize
を prepend してみたが、無理矢理すぎて結局何も変えないことにした。
Crystal はシンタックスが Ruby に非常に似ていてかつ速い。筆者のスクリプトも Crystal が 80 倍速かった。
Crystal の特徴:
- Type Union: 1 つの変数で複数データ型を許容できる
- Type Inference & Checking: コンパイル時にデータ型チェック・推論
- Concurrency: Fiber に対応しているが、マルチスレッドはこれから
- マクロでメタプロ
- Ruby からも呼べる
Google 社員の Aja Hammerly 先生がアヤメのデータセットで k 近傍法を紹介。アヤメのデータセットを散布図でプロット。品種の不明なアヤメの花もプロットしたら、図上距離の最も近いものが同一品種だと推測できる。図上距離はピタゴラスの定理で計算。
News
Tutorial
Rails で Webhook を実装する手順。
- 送信先 URL と該当イベントのマッピングを保存する
Webhook::Endpoint
モデルとwebhook_endpoints
テーブル。 - イベントとペイロードデートをラッピングする
Webhook::Event
モデル。 - 各モデルに include する
Webhook::Delivery
モジュール。モデルのコールバックでWebhook::Delivery#deliver_webhook
を呼ぶ。 - 非同期送信用
Webhook::DeliveryWorker
をWebhook::Endpoint#deliver
から呼ぶ。
Build Your Own Daily Fantasy Football Salary Tracker with Ruby and Twilio
Ruby でファンタジーフットボール用選手給料トラッカーを作った話。 ファンタジーフットボールとは米国大人気のアメフトのドラフト会議シミュレーションゲーム。 リアル選手のリアル給料に大きく影響されるので、 2 時間ごとに最新給料 CSV を DraftKings.com からダウンロードして DB に保存。 変動のあった給料を ImageMagick で画像に描画し、Imgur にアップロード。 Twilio で Imgur リンクを MMS として携帯に送信。
TTY::Command gem でシェルコマンドを細かく制御。system
、...
だけでは、下記よくあるニーズが満たせない。
- exit ステータスが 0 以外の場合は例外を投げる
- stdout、stderr 抑えて、文字列に格納して返して欲しい
Open3#popen3
なら細かく操作できるが、低レベルで使いづらくてミスりやすい。
- HTML エスケープを止める
raw
、html_safe
や ERB の<%== %>
。 - HTML 属性の
"
漏れ。 link_to
の URL。- テンプレート内 JSON。Rails は
json_encode
推奨。 - コントローラで
render inline:
。サーバ上シェルコマンド実行までできちゃう!
DateTime#to_time and Time#to_time Preserve Timezone in Ruby 2.4+
Ruby 2.4 以降の DateTime#to_time
Time#to_time
がタイムゾーンを維持するようになった。2.3 以前はシステムタイムゾーンに変更していた。
カスタム matcher BeEvent
に RSpec::Matchers::Composable
を include
することで
expect([FooEvent.new, BarEvent.new]).to include(an_event(BarEvent)) expect(domain_event).to be_an_event(OrderPlaced).with_data(order_id: kind_of(Integer))
のような expectation を実現した話。
metrics_tracker
ローカル変数の定義までトランザクションのブロックに囲ってしまったら、ブロック外で metrics_tracker
の呼び出しでバグを起こした話。
メールで送るパスワードリセット用リンクなどのトークンを生成・検証してくれる ActiveSupport::MessageVerifier
の実用例。トークンは DB に保存しないためセキュリティ抜群。
Tools
ezpaas-cli: A Miniature Docker-Powered Heroku Clone for In-House Deployments
Heroku の OSS クローン。動的インスタンスは Docker で。
Python → Ruby 変換用 Python スクリプト。
Code
Sequel ORM 生みの親 Jeremy Evans 先生の routes 用 gem Roda 3.0 がリリースされた。
Ruby Weekly #363: 日本語サマリー
職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。
Highlights
Ruby 並行処理まとめ
- プロセス。多数コア使えるが、fork が重い。
- スレッド。プロセスより軽量だが、管理が複雑。競合状態防止とかの。
- EventMachine gem。スレッド管理してくれるが、コールバックが複雑。
- Fiber。EventMachine のコールバックを隠してくれる。
並行処理方式 | サーバ例 | バックグラウンドジョブ例 |
---|---|---|
プロセス | Unicorn | Resque |
スレッド | Puma | Sidekiq |
EventMachine | Goliath | AMQP |
この 5 メソッド活かそうぜ!
Object#tap
Array#bsearch
Enumerable#flat_map
- ブロック付き
Array.new
<=>
Ruby の紛らわしい 6 機能
[]
メソッド。Array にも Hash にも String にも Proc・lambda にも付いてて諸悪の根源だと筆者が主張。%
演算子。剰余演算子にもなれば、文字列のフォーマット演算子にもなる。Integer#zero?
メソッド。== 0
のほうが無難。$数字
グローバル変数。Time.parse
。不正な文字列渡しても、不正な部分だけTime.now
で埋め込んじゃうという時限爆弾。Delegator
OSS の EC サイト用 Rails アプリ Spree 3.3 リリース
Using ActionCable and RethinkDB to Build a Reactive WebSocket App
ActionCable + RethinkDB でスプレッドシート実装。 RethinkDB の ORM として NoBrainer gem 採用。
- 各ユーザの選択中セルの枠に違う色を付けて Publish
- セルの中身を永続化して Publish
- 編集中セルにロックをかけて Publish
ActiveRecord トリック 5 点
join
の条件はscope
をmerge
しようjoin
は普段INNER JOIN
になるんだが、ネストするとLEFT OUTER JOIN
になることもあるので要注意EXISTS
、NOT EXISTS
は便利メソッドで- サブクエリは
pluck
悪用せずに ActiveRecord に任せよう to_sql
、explain
活かそう
News
Passenger 5.1.8 Released: Nginx 1.12.1, Webpacker, and Fixes
Passenger 5.1.8 リリース
- apt-get パッケージがやっとバージョンアップ(1.10.3 以降はできてなかった)
- webpacker 対応
- 冗長なログが見やすく
Tutorial
Factory と Fixture の力を合わせて外部 API を擬似化。eBay の巨大 XML レスポンスを例に挙げた。XML の Fixture を Factory に読み込み、Hash に変換。
Ruby コアのスレッド間データ通信クラスまとめ。Queue#push
でデータを積むと、別スレッドの Queue#pop
でそのデータが取得できる。上限付きキューは SizedQueue
で。
Adding Token Based Auth to a Rails API with Devise Token Auth
Devise Token Auth gem で Rails API のトークンベース認証を実装する手順。
Hanami のレビュー。
- Generator 完備
- Migration 完備
- Shotgun gem で code reloading 完備
- モデル層が Entity と Repository に分かれてる
- コントローラ層は 1 アクション = 1 クラス
- ビュー層は Template と View に分かれてる
感想
- 😄 アーキテクチャ構造が整理整頓
- 😢 ドキュメンテーション不足
- 😢
db:seeds
がない - 😢
belongs_to
has_one
がない(先週発表したように v1.1.0β1 ではリリース済み)
Rails 5.1 で AJAX を使う方法 3 通りとそれぞれの導入手順。
===
いろいろ
- クラス・モジュールを被演算子にした場合は
kind_of?
- 正規表現を被演算子にした場合は
=~
Range
を被演算子にした場合はその範囲内Proc
を被演算子にした場合はcall
- それ以外のオブジェクトを被演算子にした場合は
==
Tools
Ruby Tests Profiling Toolbox: Tools to Analyze Test Suite Performance
先週にも紹介された TestProf メトリックス計測ツール群。
Code
clone、カスタマイズ用の Sinatra + GraphQL 骨組みアプリ。Trailblazer、Apollo、React も込み。
ファジーマッチング用 gem。類似比較で使えるハッシュ値を生成してくれる。
ActiveRecord ログの SQL にコントローラやアクションなどのコメントを添える gem。Basecamp 作品。
ジオコーディング用 gem。住所で経度・緯度を算出し、その逆の照合も可能。
Ruby Weekly #362: 日本語サマリー
職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。
Highlights
メトリックス計測ツール群 TestProf でテスト最適化。
- TagProf で重いテスト特定
- RubyProf、StackProf と併用して重いスタック特定
- EventProf で DB 処理の重いテスト特定
- EventProf で重いバックグラウンドジョブ特定
- FactoryGirl の不要なデータ作成を FactoryDoctor で特定
- RSpecStamp で動的に不合格テストにタグを張る
N+1 クエリ撲滅方法比較
preload
- 2
SELECT
eager_load
- 1
LEFT OUTER JOIN
joins
- 1
INNER JOIN
includes
- Rails 4 以前は、魔術で
preload
eager_load
joins
の中からベストを選択してくれた - Rails 5 以降は、
includes
=preload
。references
でJOIN
を強制させる(魔術の保守を諦めたコアチーム)
Q 学習アルゴリズムを Ruby で実装して、ゲームの AI を学習させた話。
synvert gem で
flash[:notice] = "Hoge" redirect_to root_path
の古い表記をよりなうい
redirect_to root_path, notice: "Hoge"
に書き換えた話。
好きな OSS リポから Issue を割り振ってくれるサービス CodeTriage。@schneems さんのバグでユーザに巨大メール送っちゃった話。
SendGrid の上限を超えちゃったある日。冪等になってなかった割り振るジョブが落ち、一時間ごとにリトライを繰り返した。SendGrid に追加課金した途端に、各ユーザの溜まった 400 以上もの Issue をメールで飛ばしちゃった。
Evented Rails: Decoupling Complex Domains in Rails with Events
イベント駆動 Rails で DDD の Bounded Context を疎結合に。
配車サービスを例に挙げ、密結合した 配車依頼 → 自動車マッチング → 依頼主・運転手通知
機能を Wisper gem の pub/sub で 依頼主
コンテキストと マッチング
コンテキストを分離した。
News
Rails コアチーム新メンバー
Tutorial
N+1 クエリ解消策には eager loading、preloading のほかに バッチング策
もあった。筆者が Facebook の Haskell 制 Haxl ライブラリに倣って BatchLoader gem を作った。並列処理、GraphQL を活用例として挙げた。スレッドセーフでキャッシング完備。
イベントのチケット販売アプリのリマインダー通知を再起計算でスケジューリングした話。チケット購入直後とイベント開始直前のリマインダーは頻繁に、その間はもっと永い間隔で。
RSpec のブートを 50 倍速くした話。答えは spring。rvm のローカル gemset を最低限に減らしても大差はなかった。
ポリモーフィック関連付けの解説。レストランのレビューとイベントのレビューを表す Review モデルで例を挙げた。
Builder デザインパターンを Ruby で実装。ここであらすじ書かなくても原文のコードは読みやすくて分かりやすい! ★★★
Rails 5.1 の暗号化 Secret。
bin/rails secrets:setup
で下記ファイル生成:
- config/secrets.yml.key(キーファイル。コミットするな!絶対に)
- config/secrets.yml.enc(暗号化 Secret ファイル)
bin/rails secrets:edit
で修正。
キーファイルをサーバに置く方法:
- scp/sftp
RAILS_MASTER_KEY
環境変数
Story
Heroku CLI の進化。
v1〜v3
v4
- Go + Node
- Go だけでは動的ライブラリに対応できなかったので、プラグイン機能は Node で
- CLI コアまでプラグインに抽出
- 初回実行で Node + コアプラグインをダウンロード
- 2 年間じっくりかけた
v5
- Go + Node
- Node + コアプラグインを tarball に同梱
v6
- Node のみ
- Go を捨てた理由
- OS アップデートで Go 周りぶっ壊れる
- Go は比較的低レベルで、機能追加がしんどい
- プラグイン参照するたびに新規 Node プロセスを切るのに数百ミリ秒もかかった
- CLI フレームワーク cli-engine 抽出、OSS 化
- プラグインのインタフェースを ES6 に
- Node 7 の
async
/await
活用 - コア・プラグイン開発は
Tools
Fabrication vs FactoryGirl ベンチマーク。ネストしているモデルの場合は、Fabrication のほうが速い。create
は特に。
Code
新機能
belongs_to
、has_one
、has_many :through
アソシエーション- thor 捨てて hanami-cli gem 新規作成
- Entity のマニュアルスキーマ定義(ActiveModel の属性定義に相当)
- CLI からブートするアプリ指定
- ログの機密情報マスク(Rails の
filter_parameters
に相当)
DDOS 防止 Rack::Attack
gem
システムステータス告知用 Rails アプリ
bettercap: A Modular, Portable and Extensible MITM Framework
中間者攻撃用 gem。脆弱性検証でも使えるらしい。
k 近傍法による分類用 gem(機械学習)
Ruby Weekly #361: 日本語サマリー
職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。
Highlights
dependabot(依存 gem チェッカー as a Service)のバグ改修で Bundler を 2 倍速くした話。
バグは Bundler の依存関係解決ロジック(Molinillo gem に抽出されてる)にあった。バックトラッキングアルゴリズムが複雑すぎて、リファクターすることに。そこで閃いて、グルーピングで 10 倍高速化。
次バグ改修したが、今度激重くなった。フィルタリングしてみたら今のスピードになった。
YAML から巨大 Hash を読み込む Rails アプリのメモリが気になり、Ruby メモリ計測方法調べてみた話。
String#bytesize
で文字列単位計測- memory_profiler gem でブロック単位(
Total retained
値) - derailed_benchmarks gem の
derailed exec perf:mem_over_time
で多数リクエストを投げてメモリ計測
結論:3 の数値が横ばいになっていくから Hash 巨大化してもメモリへの影響はさほどない。
Rails の CSRF 対策の内部実装をコードリーディングした話。
Enumeration 上級者編
- Enumeration とは
Enumerator
の最低条件- Lazy vs Not Lazy
- 上級者活用例
- グループ分け
- フォールディング
- Struct
「Rails 終わったなんてデタラメ」ブラジル RubyConf 元オーガナイザー Fabio Akita 氏。 Rails 経歴を振り返りながら、先々週の Coding Dojo ブートキャンプ騒ぎに反論。
2003 年。SNS 元年。
2004 年。Gmail 誕生。FB 急上昇。常識を覆す Rails がブラジルの無名カンファレンスで登場。
2006 年。Twitter、Groupon、Engine Yard 登場。AWS S3・EC2 リリース。インディーズでもスケーリングが可能に。
2007 年。Heroku 誕生。Git リリース。iPhone 発売。
2008 年。GitHub 誕生。DevOps 元年。Zed Shaw が Ruby から引退した騒ぎ。Rails + Merb 結合。
2009 年。Apple ネイティヴ SDK リリース。NoSQL 元年。Twitter が Scala に移行。
2010 年。Apple が Flash に対して宣戦布告。Rails 全盛期。
2011 年。Ruby、Objective-C が主流となった。
2012 年以降。Rails 屋さんから生まれた、なんでも作り直したがる不満げなエンジニアの時代。Go、Elixir、Scala などニッチ言語に流出。
結論:Rails 終わったなんて大げさ。常識を覆さなくなったのは、Rails が常識になったから。
- キー命名統一しろ
- ダブらせるな
- 文字列前後に
"
付けろ(YAML パース失敗 → Rails ブート失敗の原因。超デバッグし辛い) - ローカライズ外注先とのワークフロー決めろ
- 該当文章が見つからなかった場合は機械翻訳をフォールバックに(コードあり)
- YAML ファイル名とファイル内ロケールが一致しているかテスト書け
Tutorial
DynamoDB で has_many
アソシエーションをモデリングした話。1 テーブルでのモデリングと 2 テーブルでのモデリングを比較した。
社内 gem を Gemfury(有料)でホスティングしてた Showoff 社が、gemstash でセルフホスティングにした手順。
- EC2 インスタンス作成・設定
- gemstash 用 Rails アプリ作成
- Capistrano 設定
- gemstash 設定(認証有無)
- デプロイ
gemstash
コマンドでプッシュ用キー作成- 社内 gem を gemstash にプッシュ
gemstash
コマンドでフェッチ用キー作成、Gemfile に埋め込む
テストが不安定になる原因
N+1 クエリ撲滅方法
includes
- bullet gem
おまけ
- Semaphore CI では bullet.log もジョブ毎に表示できる!という執筆者のステマ
Bullet.raise = true
で CI ビルドをレッドにしよう- 既存 N+1 が多すぎる場合は、ホワイトリストに追加して、新規クエリのみ CI 対象にしよう
RSpec の --profile
オプションで重いテスト特定して潰していこう。
Create a State Machine with AASM, Sequel, SQLite, Rake, and RSpec
AASM gem + Sequel で state machine 実装、RSpec でテスト。
Shoryuken gem + Amazon SQS の FIFO キューでバックグラウンドジョブ処理。
FIFO キューの特徴
- ジョブのグループ分け(処理順を例えばユーザ別に固めたい場合)
- ジョブ重複実行防止(Amazon SQS に繰り返して投げた場合)
手順
shoryuken sqs create queue.fifo
コマンドで FIFO キュー初期化Shoryuken::Worker
を実装(ActiveJob
も OK!)Shoryuken::Worker.perform_async
やActiveJob.perform_later
でジョブをキューに積むshoryuken -q queue -r ./hello_worker.rb
コマンドでジョブ処理開始
rate limit にでも使える。
Using dry-container to Implement Inversion Of Control for Hanami::Events
Hanami::Events gem 作成者が dry-container の制御の逆転で DB バックエンドのアダプターをカスタムなものでも指定可能にした話。
極秘メソッドの作り方。
.
を含んだメソッド名を define_method('super.secret')
で定義したら、send('super.secret')
でしか呼べないメソッドができる。
考えられる用途:
- 外から使わせたくないメソッド(つまり
private
メソッド) - 名前空間汚染防止
執筆者の注意事項:これやらないほうがいいよ!
Rails 認証セキュリティ改善案 4 つ。
Bundler + GitHub の private リポ上の gem
git://
プロトコール使うな(中間者攻撃脆弱性あり)github:
使うな(裏でgit://
使ってるから)- SSH プロトコールを使う場合は、CI は Machine User の Deploy Key で
- HTTPS プロトコールを使う場合は、Gemfile に Basic 認証のアイパスを埋め込むな。下記のどれかにしろ:
Code
役に立つ awk ワンライナー集 を Ruby で実装してみた。
GraphQL 用認可 gem。CanCanCan、Pundit とも併用可能。