rastam’s blog

東京在住のマレーシア人 Rubyist

Ruby Weekly #377: 日本語サマリー

職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

http://rubyweekly.com/issues/377rubyweekly.com

Highlights

Rails 5.2.0 Beta Released

Rails 5.2.0 βリリース。

  • ActiveStorage でファイルアップロード
  • Redis Cache Store
  • HTTP/2 Early Hints 対応
  • Bootsnap でブート時間半減
  • Content Security Policy 定義用 DSL
  • secrets を deprecate、Credentials 新規追加
  • Webpacker 3.0

Talking to ActionCable without Rails

Rails ヘルパー使わずに素 JavaScript でクライアント側 ActionCable を実装してみた Thoughtbot 社。

'String#delete_prefix' and 'delete_suffix' Methods in Ruby 2.5

文末文字削除用 String#chompRuby 2.5 から #delete_suffix アライアス追加。さらに文頭の文字削除用 #delete_prefix が新規追加。

Zero Downtime Rebranding with Heroku

Heroku 上 Rails アプリをゼロダウンタイムでドメイン移行。

  1. 複数ドメイン
    • DNS ホストで ALIAS 設定
    • heroku domain:add
  2. 複数 SSL 証明書
    • Heroku SSL Endpoint を使ってる場合、Heroku SSL にアップグレード
  3. SAN 証明書発行
    • heroku certs:add
  4. rack-rewrite gem のミドルウェア
  5. 外部 API コールバック用エンドポイント
    • callbacks サブドメに移行
    • 旧コールバックを rewrite
  6. Evil Martians 自家製 RackRewriteConfig で環境別設定(原文コード参照)

Removing Business Logic From Controllers

コントローラテストを deprecate した Rails 5 に備えて、ロジックをモデルなどのオブジェクトに抽出するメリット。例に挙げたのは、パラメータ有無で挙動が変わったコントローラのビジネスロジック

A Written Retrospective of RubyConf 2017

RubyConf 2017 1 日目の振り返り。

  • Matz のキーノート
    • 初回参加者が意外と多くて Ruby の未来が有望的
    • なるべく互換性を保ちながらリリースしていく
    • コミュニティを交えて相談していきたい
  • There Are No Rules in Ruby (Max Jacobson)
    • Ruby の柔軟性のデメリット
  • Finding Beauty in the Mundane (Megan Tiu)
    • しんどい仕事でも接し方によって楽しめる方法
  • Augmenting Human Decision Making with Data Science (Kelsey Pedersen)
  • Growing Old (Chad Fowler)
    • レガシーだからって悪いとは限らない

News

RubyGems 2.7.3 Released

RubyGems 2.7.3 リリース。

The 10 All-Time Most Downloaded Ruby Gems

最もダウンロードされてる gem トップ 10。

  1. bundler
  2. multi_json
  3. rake
  4. rack
  5. json
  6. mime-types
  7. activesupport
  8. thor
  9. i18n
  10. diff-lcs

Rails は 22 位。

Tutorial

How to Run Sidekiq on a Heroku Free Dyno with Puma

Heroku の無料 Dyno で Sidekiq を動かすための Puma 設定。

Clean HTTP OPTIONS Handling in Rails

Rails API に OPTIONS の HTTP メソッド対応を追加した Kollegorna 社。結果的に rails_http_options gem も作った。

Instrumenting Ruby Methods

NewRelic などのメソッド計測コードが散らばらないように prepend する方法。

How to Add Comments to Database Columns from ActiveRecord

Choosing UUIDs for Model IDs in Rails with Postgres

PostgreSQL の UUID を Rails アプリで採用する手順。

Rails on Docker: Using Yarn to Manage Frontend Assets

Rails アプリの Docker イメージに Yarn を追加する手順。

How Does Bitcoin Force Consensus Among Byzantine Generals?

Bitcoin を解説した Fabio Akita 先生。

Code

ComfortableMexicanSofa 2.0: A Rails 5.2+ CMS Engine

CMSRails 5.2 エンジン。

ElasticNotifier: Send Error Notifications to an Elasticsearch Server

エラー通知を ElasticSearch サーバに送ってくれる ElasticNotifier gem。

Ruby Weekly #376: 日本語サマリー

職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

http://rubyweekly.com/issues/376rubyweekly.com

Highlights

Improving Ruby Performance with Rust

Pathname を Rust で書き換えて 3 割高速化した FasterPath gem 作成者が Rust に挑んだのを振り返った。

  • 最初は FFI 経由で実装してみたが、メモリを解放するコストなどあって、結局ピュア Rust 実装のほうが効果的だった。
  • Rust の Ruby 言語拡張 ruru と Helix はあるが、より安定な ruru にした。
  • Rust はまだ日が浅くて、ruru も Helix も 1.0 になってないので要注意。

Amazon API Gateway Can Now Generate Ruby SDKs

Amazon API Gateway では Ruby SDKAPI クライアント gem)を生成できるようになった!AWS IAM 認証込み(カスタム認証も可)。

Session-Only Cookie Corruption in Ruby Web Apps

Rails のセッションデータをクッキーで保存している場合、ブラウザのサイズ上限を超えたら

  • モダンなブラウザではクッキーがまるごと破棄され、ログイン状態を維持できないバグ発生。
  • IEiOSSafari では Secure、HttpOnly、SameSite などのディレクティブが切り捨てられ、XSS 脆弱性にもなりかねない。

Rails、Rack はサイズをチェックしてくれるが、ディレクティブまでは考慮できてない。筆者が暫定対応として Rack::Protection::MaximumCookie gem 作成。

GitHub Introduces Security Alerts for Ruby Projects

依存 gem と JavaScript ライブラリの脆弱性をアラートしてくれるようになった GitHub

DuckRails: Quickly and Dynamically Mock API Endpoints

API のモックを作るための Rails アプリ。

News

Rubyhack Conference (Salt Lake City, May 3-4, 2018)

Rubyhack カンファレンスの CFP 開始。

Tutorial

Ruby 2.5's Dir.children and Dir.each_child

. .. を除外した ls -a の結果を返してくれる Ruby 2.5 の Dir.children Dir.each_child

Using ActiveStorage Today (Prior to the Rails 5.2 Release)

リリース前の ActiveStorage で画像アップロード機能を実装する手順。

Better Rails Performance with JSON Patch

カスタムフォーム作成用 FormAPI は不特定多数のフィールドを PostgreSQL の jsonb カラムで保存。フィールド数が多いと重くなってたが、JSON Patch 標準で差分だけサーバに送るようにした。差分を当てるには hana gem 採用。

How to Receive & Respond to Text Messages with Hanami & Twilio

Hanami + Twilio で SMS 送受信アプリ実装手順。

Migrating 'has_and_belongs_to_many' Associations to Rails 4+

Rails 4 HABTM 移行した話。HABTM テーブルのデフォ命名が変わったため、join_table: オプションで指定する必要があったりする。新規命名に従ってないテーブルを検知してくれるスクリプトも作った。

Docker + Rails + System Tests with Headless Chrome

Docker + Rails + Headless Chrome システムテストを実装した話。

google_translate_diff: Using Google's Translate API More Efficiently

Google 翻訳 API 料金節約施策を google_translate_diff gem としてリリースした Evil Martians 社。原文をテキストと HTML マークアップに分解して、翻訳済みテキストをキャッシュすることで、Google 翻訳 API の二重呼び出しを塞ぐ。自社費用は 6 割減。

Story

Some Thoughts and Feelings on RubyConf 2017

RubyTapas 売上低迷と健康保険の負担で RubyConf 2017 に参加できなくなるところだった Avdi Grimm 先生。結局コミュニティからの寄付で参加した。感動と感謝の気持を記事で書き落とした。

Tools

dbmgr: CLI Tool to Back Up, Restore, and Provision Dev Databases

開発環境 DB バックアップ・復元用 CLI ツール。

Code

ModelProbe: Schema Introspection for ActiveModel

ActiveRecord スキーマ取得用 gem。

Ruby Weekly #375: 日本語サマリー

職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

http://rubyweekly.com/issues/375rubyweekly.com

Highlights

Sniffer: Log and Analyze Outgoing HTTP Requests

Net::HTTP、Typhoeus などの HTTP リクエストを JSON でロギングしてくれる gem。

How David Heinemeier Hansson, Creator of Rails, Works

DHH いろいろ。

  • 元々はプログラミングに興味がなかった。
  • 高校で運営していたゲームレビューサイトが数千もの読者がいた。
  • サイトの機能追加で PHP 覚えた。
  • ブログ上の PHP 相談で Jason Fried と知り合い、37Signals 入社。
  • 好きなエディターは TextMate
  • 趣味は写真、機械式腕時計、自動車競技、旅行。
  • 時間節約の裏技は、依頼をほとんど断ること。
  • 仕事は 4〜5 時間集中して、それ以上仕事しない。

Implementing a Worker Pool in Ruby

Celluloid、Concurrent Ruby のような Worker Pool パターンを TDD で一から実装してみた話。

  • ワーカー数上限が指定できる WorkerPool
  • メモリパンク防止用のジョブ数上限が指定できる SizedQueue
  • WorkerPool に注入できるスケジューリングアルゴリズム

How We Trick Bundler and Cause Interesting Bugs

Gemfile 内 gem の定期アップグレードを SaaS として提供してる depfu。各 gem のバージョンを上げる試行錯誤を繰り返し、互換性を検証する仕組み。ある日 ActiveSupport のバージョンアップでメモリパンクしちゃった。原因は bundler が依存関係を Array#combination で掛け合わせてるところ。配列の重複してる様子を排除する PR 出して緩和。

Clear Up Controllers and Models with the Waterfall Gem

Waterfall gem でコントローラのサービスオブジェクトをロールバック可能なチェーンで連携する活用例 2つ。

Are Comments A Code Smell? It Depends

コメントは必ずしもコードスメルだとは限らない、という主張。コメントは2種類ある:

  1. コードが何をしてるかの説明
  2. コードが何で必要かの説明
    • 書くべき

Tutorial

The Proxy Pattern in Ruby

プロキシパターン(別名サロゲートパターン)解説。

  • 重い処理をラッピングして遅延評価などで時間稼いでくれる活用例。
  • 認可層の活用例。
  • RPC での活用例。
  • メモ化用の活用例。

Using Vue.js with Rails

Rails アプリへの Vue.js 導入手順。

Postgres Primary/Replica Replication on Heroku with Rails

Octopus gem で Heroku の PostgreSQLレプリケーション実装手順。

Using Postgres's Advisory Locks from Ruby

PostgreSQL の Advisory Lock 解説。テーブルロック・行ロックと違って、DB 層ではなくアプリ層で管理。例えば、バックグラウンドジョブのワーカーだけでロックをかけても、UI からの CRUD 操作ではロックがかからない。

  • ロック作成、確保、解除
  • トランザクションロック vs セッションロック
  • ロック管理用 Ruby モジュール実装例

Flippin' Features at Runtime

フィーチャーフラグ用 Flipper gem の新機能。

  • 初期設定のデフォ
  • Flipper クラスメソッドからシングルトンのインスタンスへデリゲート
  • get_all preload_all で全フィーチャーフラグ取得
  • フィーチャーフラグ import 機能
  • redis、ActiveSupport キャッシュ用アダプター追加
  • flipper-api gem でフィーチャーフラグを HTTP API

Refactoring with Hash Defaults

Hash の デフォ値設定方法。

  • Hash.new
  • Hash#default
  • Hash#default_proc

case 文を Hash でリファクターすることも提案してる。

Atom Tricks, Plugins and Shortcuts for Ruby Developers

Rubyist 向け Atom パッケージ、キーボードショートカット、スニペットなど。

Getting Started with Faktory

3 週間前にリリースされた Faktory バックグラウンドジョブシステムのインストール手順。

Opinion

On Sustainable Testing

ちゃんと書かれた describe 文を推薦する RSpec コアチーム方針への反論。メンテされなくなると。なぜならプログラマーがメンテしたいのは書くのが楽しい、カスタムマッチャーを活かした、テストコードを読むだけでもわかる spec。

出力が読みづらいという指摘を覆す例も挙げた。

Code

Rackula: Generate A Static Site from any Rack Middleware

RailsSinatra などから静的コピーを生成してくれる Rack ミドルウェア

frappe_charts: Generate Frappé Charts from Your Rails Apps

SVG チャート生成ライブラリー Frappé Charts をラップした gem。

Karafka 1.1: Work with the Kafka Streaming Platform from Ruby

Kafka + Ruby アプリ用 MVC フレームワーク Karafka 1.1.0 リリース。

Ruby Weekly #374: 日本語サマリー

職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

http://rubyweekly.com/issues/374rubyweekly.com

Highlights

How We Switched From Sprockets to Webpack

下記理由で Sprockets から Webpack に移行した LearnZillion 社。

  • Sprockets が重い。
  • ES6 欲しさ(Sprockets にもあるが、未だに experimental)。
  • Sprockets が提供してくれない機能欲しさ。
  • Webpack が Rails Way となった。

移行計画

  1. 準備フェーズ
    • Webpacker 追加
    • 環境構築
    • Nginx、capistrano 設定
    • デプロイ
  2. 移行フェーズ
    • Rails asset 用 gem を NPM パッケージで置換
    • アピリコードを Webpack に移行
    • 必要に応じて Webpack 設定修正
  3. クリーンアップフェーズ
    • Rails asset 用 gem 削除
    • Sprockets 設定削除
    • Webpack バンドル最適化

問題点

コード豊富なので原文参照。

Upgrading Kickstarter to Rails 5

9 年ものレガシー Rails アプリを Rails 5 にバージョンアップした Kickstarter 社。

  1. 段階的アップグレード
    • Rails 4.2.8 → 4.2.9 などのマイナーパッチ
    • Ruby 2.25 → 2.4.x
  2. リリースノートに従った修正
  3. gem を v5 にアップグレード
  4. Rails 4.2 にマージできる修正を master ブランチにマージ
  5. Rails 5 専用ブランチを CI グリーンに
  6. Rails 5 専用ブランチの deprecation 忠告撲滅
  7. Rails 5 専用ブランチを手動で動かす
    • テストでカバーできてない問題特定のため
  8. master ブランチで今までの修正をバックポート
  9. 各機能の開発チームに自分の機能をテストしてもらう
  10. staging 環境にデプロイ
  11. 本番デプロイ
    • カスタマーサポートからのバグチケ消化
  12. 振り返り

結果

  • 見積もりどおりの 3 ヶ月で完了
  • 大規模ダウンタイムなし
  • カスタマーサポートのバグチケ対応計画たてとけばよかった
  • いろいろ学習できた
  • 影響範囲の最も広かった変更点は HashWithIndifferentAccess を継承しなくなった ActionController::ParametersHash を継承していることを前提にしたコードがいっぱいあったから。
  • モバイルアプリへの影響は少なかったが、予想しなかった。ネイティヴチームのエンジニア巻き込んどけばよかった。

Ruby Performance Profiling: An Unorthodox Approach

API の重いリクエストで悩まされた Kollegorna 社は、フレイムグラフ見てもネックが特定できなかった。そこでクラス単位でメソッドをベンチマークしてくれる ClassProfiler gem を作ることに。%の最も高いメソッドの中で呼ばれるクラスを次々とベンチマークすることで、やっと犯人に辿り着いた。

Why Aren't We Using More Service Objects Already

先週サービスオブジェクトの使いすぎを否定した Avdi Grimm 先生への反論。

  • モジュールメソッドだとどんどん増えていき、結局 junk drawer になる。
  • 筆者の経験では、サービスオブジェクトが統一したコードへと繋がった。
  • サービスオブジェクトを支える ActiveInteraction gem まで作った。

Multiverse: Manage Multiple Databases in Rails Apps

Rails アプリの多数データベース用 gem。

News

Ruby Versions Used in Commercial Projects in 2017

Semaphore CI ユーザが採用している Ruby バージョン別分布。

  • 85% は Ruby 2.0 以上。
  • 最新バージョン (2.4) の採用は例年に比べて低い。
  • Ruby 2.1 は EOL 済みなので早めにバージョンアップするように推奨。

JRuby 9.1.14.0 Released

JRuby 9.1.14.0 リリース。

RubyGems 2.7.2 Released: A Bugfix Release

RubyGems 2.7.2 リリース。

  • bundle gem コマンドで新規 gem 生成できなくなっていたバグ解消。
  • git がインストールされていない環境でエラっていたバグ解消。

Tutorial

Interactors in Ruby: Easy As Cake, Simple As Pie

インタラクターデザパタinteractor gem の紹介。

  • Fat Controller の各工程をそれぞれサービスオブジェクトに抽出して、 Interactor モジュールを include
  • Interactor::Organizerinclude したオブジェクトでサービスオブジェクトの呼び出し順番を定義。
  • Interactor が提供してくれる before around after フックでトランザクションを張ったりする。
  • gem は非常に計量(ソースが小さい)。
  • Interactor::Organizer に並べたサービスオブジェクトは Context オブジェクトを共有するのがちょっとグローバル変数っぽくて要注意。
  • gem は validation 仕組みを提供してくれないので、筆者が validation 用 Interactor を提案した。

How 'require' Loads A Gem

$LOAD_PATH に載っていないのに gem を require できるようにしてくれる RubyGems コードリーディング。Kernel#require のモンキーパッチで、LoadError 発生時の rescue ブロックで、インストール済み gem の中から探す。見つけた場合、$LOAD_PATH に追加し、require 再挑戦。

Get 80% Smaller Rails Page Sizes with Rack Deflate

Rack::Deflate ミドルウェアRails レスポンスを gzip 圧縮してサイズを 80% 減らした Richard Schneeman 先生。

Quick Tip: A Pitfall of The &. Operator

&. 演算子の罠。< などの評価順番が変わっちゃうから要注意。(原文コード参照)

How to Partition and Conquer a Large Postgres Table

数百万行もの PostgreSQL テーブルをパーティション分割した Evil Martians 社。

  1. 親テーブルをクローン。
  2. 子テーブル + 親テーブルの PK をマッピングするビュー作成。
  3. 子テーブルを作成・更新するストアドプロシージャ作成。
  4. ストアドプロシージャを呼ぶトリガーをビューに張る。
  5. ActiveRecord モデルがビューを見るように設定。
  6. 既存データはビューに INSERT することで移行。

Turn Rows Into Columns With The Array#transpose Method

Array#transpose いろいろ。

  • 二次元配列で行と列を入れ替えてくれる。
  • 三目並べゲームの勝利判定ロジックを例に挙げた。

Upgrading a Rails App from 3.2 to 4.0

Rails 3.2 アプリを 4.0 にアップグレードするための豆知識。移行してない人がまだまだいるから。

  • Ruby 1.8.7 を使っていれば、1.9.3 にアップグレード。
  • rails4_upgrade gem を Gemfile に追加して、アップグレードの必要な gem を特定。
  • rails:update Rake タスクで不要な設定・モンキーパッチを削除。
  • RailsDiff で予想された差分を確認。
  • activerecord-deprecated_finders gem で .find_by_hoge メソッドを洗い出し・撲滅。
  • scope は全部 lambda 表記に。
  • protected_attributes 撲滅。あるいは protected_attributes gem 導入。Strong Parameters に移行することがベスト。
  • ActiveRecord::Observer 撲滅。あるいは rails-observers gem 導入。wisper gem または Rails Concerns に移行するのがベスト。
  • ActiveResourceactive_resource gem に移行。
  • caches_page caches_actionactionpack-action_caching gem に移行。
  • Test::Unittest-unit gem に移行。
  • match 式 route は HTTP メソッド要指定。
  • プラグインを使っていれば gem に移行。

Code

Arbolito: A Minimalist Currency Conversion Library

Alpha Vantage API を叩く両替 gem。Alpha Vantage 以外でも拡張可能。キャッシュ期限設定可能。他 gem への依存が一切ない。

wsdirector: A Command Line Tool for Testing WebSockets

ActionCable など WebSocket サーバテスト用 CLI ツール gem。データ送受信スクリプトYAML で定義してから wsdirector コマンドで実行。ApplicationCable::Channel単体テストと思えば良さそう。(RSpec・MiniTest・Test::Unit とは別物)

Ruby Weekly #373: 日本語サマリー

職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

http://rubyweekly.com/issues/373rubyweekly.com

Highlights

Enough With the Service Objects Already

どんな Fat Controller でもサービスオブジェクト抽出で片付けちゃうのを否定する Avdi Grimm 先生。

  • 多くの場合はプロシージャー型モジュールメソッドのほうが適切だと
  • 間違ったオブジェクトを抽出よりも、オブジェクトを抽出しないほうがマシ
  • サービスオブジェクトは依存し合いがち
  • サービスオブジェクトはビジネスドメインよりも、インフラ層に相応しい(DDD 本もこう書いてある)
  • ビジネスドメインのサービスオブジェクトがあったとしても、インフラ層のサービスオブジェクトから分離すべき

Bundler 1.16 Released (But 2.0 Is Close)

Bundler 1.16 リリース。

  • 依存関係解決の新規アルゴリズムに切り替えたことでパフォーマンス向上・バグ解消。
  • bundle installeval 回数を減らしたことでパフォーマンス向上。

次のリリースは Bundler 2!

  • master がすでに Bundler 2 となった。
  • Bundler 2 機能は 1.16 にも入ってて、feature flag で無効となっている。Bundler 2 を試したい方は、ぜひ有効化を。

Implementing OCR using a Random Forest Classifier in Ruby

ランダムフォレストアルゴリズムで手書き数字の OCR を実装する手順。PyCall gem で Pythonscikit-learn ライブラリーに投げてる。

Memory Conscious Programming in Ruby

メモリを意識した Ruby

  • nil true false はメモリを確保しないため、考慮しなくてもいい。
  • -2^622^62-1 の整数もメモリを確保しないため、考慮しなくてもいい。
  • Array Struct は要素 3 つまでは最低メモリの 40 バイトで収まる。
  • 空っぽの Hash は最低メモリの 40 バイトで収まる。
  • String は 23 バイトまで最低メモリの 40 バイトで収まる。
  • オブジェクトはインスタンス変数 3 つまでは最低メモリの 40 バイトで収まる。

メモリ最適化の工夫:

  • 上記ルールと ObjectSpace.memsize_of でメモリ計測していき、最も効率の良いデータ構造を選択。
  • オブジェクトをできるだけ再利用する。
  • Array#map! など破壊的メソッドでオブジェクトのインスタンス化を避ける。
  • allocation_tracermemory_profiler などの gem でメモリ計測。

Transactions in Rails and Atomic Bugs

Rails トランザクションの罠いろいろ。全文日本語訳あり!

RubyGems 2.7.0 Released

gem update --system でバージョンアップしようぜ!

  • 同梱 bundler を 1.16.0 にバージョンアップ。
  • Bundler が Gem.use_gemdeps を使うように。
  • gem CLIsignin コマンド追加。
  • gem CLI にログアウト機能追加。

News

5 Performance Improvements in Ruby 2.5

Ruby 2.5 パフォーマンス向上。

  • 文字列 interpolation が 72% 速く!
  • String#prepend が 42% 速く!
  • Enumerable#sort_by Enumerable#min_by Enumerable#max_by が 50% 速く!
  • String#scan の文字列パターンは 50%、正規表現パターンは 10% 速く!
  • Range#min Range#max が 60% 速く!

Tutorial

Cleanly Scaling Sidekiq

AWS 上の Sidekiq を自動スケーリングしている Honeybadger.io 社。

実行中ジョブが完了するまで、インスタンスを殺すのを遅らせる、という要件を、原文のスクリプトで実装した。

The Case Against Exotic Usage of :before_validate Callbacks

よくある before_validate コールバック悪用パターンと代替案。

  • データフォーマット・正規化。
    • attr_writer をオーバーライドしよう。
  • データ設定。
    • 例えばアソシエーションから取得した値をカラムに設定して非正規化。
    • コールバックなしで普通に設定しよう。

Make Your JSON API Tests Clean with a Linter

linter で JSON APIRSpec テストを綺麗に。リクエストとレスポンスの

JsonApiLint オブジェクトに抽出して、 request spec の #app を置き換えることで、 spec に残るのは

  • HTTP ステータスチェック
  • JSON 内容チェック

のみになった。

A Useful RSpec Trick for Testing Methods with Arguments

1 it 1 expect ルールを厳守する Victor Shepelev さんの、引数パターン別メソッドの戻り値をテストする裏技。

  1. subjectObject#method で取得した Method オブジェクト。
  2. its([引数]) で引数パターンを指定。

WEBrick, Rack, and Sinatra's Responsibilities Visualized

WEBrick・Rack・Sinatra のそれぞれの役割を分かりやすく描いた図。

Testing Stripe with Rails and RSpec

Stripe で決済処理を行っている Rails アプリのテストを支える stripe-ruby-mock gem。StripeEvent gem で実装した Stripe Webhook の受信までテストできちゃう。

Use Simplecov in Your Rails Test Suite

simplecov gem でテストのカバー率を測る手順。

Story

Splitting Strings in Ruby vs. Python

"".split("-")RubyPython で挙動が異なっている。

Python

Ruby

  • [] を返す。
  • PerlAWK に倣った。

A Bug That Only Appears Once A Year

25.hours.from_now で日付が変わることを期待していたテストが落ちた話。実行したのは夏時間に切り替えた日。

Code

RequestVia: A Functional HTTP Client That Wraps Net::HTTP

関数型 HTTP クライアント gem。

Rack::Session::SmartCookie: Smarter Session Cookies for Rack 2 Apps

Rack 2 セッションクッキーの問題点を解消してデフォにした gem。

Kaminari: A Powerful, Customizable Paginator for Ruby Webapps

松田明先生のアノ有名なページング用 gem。

Postwill: Post to Popular Social Media Networks from Ruby

SNS 投稿を一本化した gem。

Ruby Weekly #372: 日本語サマリー

職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

http://rubyweekly.com/issues/372rubyweekly.com

Highlights

10 New Features in Ruby 2.5

Ruby 2.5 新機能まとめ。

  • begin 明示しなくても do/end ブロックの rescue else ensure ができるようになった。
  • 同一ネームスペース内で見つからなかった定数をルートネームスペースから探すのがなくなった。
  • bundler 同梱。
  • バックとレースのエラー発生行番号を一番下に出力するようになった。
  • yield_self 新規追加。
  • String#delete_prefix String#delete_suffix 新規追加。
  • Array#unshift の alias として Array#prepend 新規追加。
  • Array#push の alias として Array#append 新規追加。
  • Hash#transform_keys Hash#transform_keys! 新規追加。
  • . .. を除外した Dir.children Dir.each_child 新規追加。
  • ERB に binding を渡す手間を省いた ERB#result_with_hash 新規追加。

Introducing Faktory: A New Background Job System

Faktory バックグラウンドジョブ用サーバデーモンとそのワーカー用 faktory_worker_ruby gem リリース。Sidekiq 同様にウェブ UI とジョブ永続化(FacebookRocksDB)機能付き。

FactoryGirl Has Been Renamed to FactoryBot

FactoryGirl と FactoryGirlRails gem が FactoryBotFactoryBotRails に改名。ユーザに不快感を与えないように、ジェンダー的に中性なネーミングにした。その裏に、UberGoogle のセクハラ・差別スキャンダルで非難を浴びてきた近年のシリコンバレーの影響があると思われる。

Creating Configuration Objects in Ruby

Configuration オブジェクト戦略いろいろ。

  • Hash
  • YAML
  • OpenStruct
  • ActiveSupport::Configurable

知見

  • 環境変数が散らばらないように、YAML で集約。
  • Hash#merge Hash#dig で優先順位どおりに適用。
  • rom-rb でコンフィグの全種類を管理。

Relative Testing vs Absolute Testing

ミュテーションテストでより深く理解した絶対テストと相対テスト。

  • 絶対テスト: 定数・リテラルと比較した assert_equal
  • 相対テスト: < > <= >= や変数と比較した assert_equal

絶対テストは省略しがちだが、あったほうがミュテーションテストに強い。 例えば

  1. #hash をオーバーライドしたアルゴリズムは、assert_equal(object1, object2) だけだと、アルゴリズムの固定値が書き換えられても、テストが落ちなくなる。ハッシュ値を固定値と比較した絶対テストがあるべし。
  2. AUTOINCREMENT カラムでソートした scope は、assert_equal([record1, record2], records) だけだと、初期値が予期せぬ負の数値に書き換えられても落ちない。
  3. id カラムでソートした scope は、assert_equal([record1, record2], records) だけだと order(:id) が書き換えられても落ちない。欠番を再利用する DB では不具合が起き得る。SQL 文の固定値と比較した絶対テストがあるべし。

Replacing Mocks With Hand-Written Test Doubles

モックは下記問題点がある。

  • expectallowsetup) → 実行 順番が普段の setup実行expect と異なってて非直感的。
  • モックしたクラスと密結合。
  • 再利用性が低い。

お手製 double で全部解消。spy はなおよし。

News

Ruby 2.5 Allows 'rescue/else/ensure' Inside 'do/end' Blocks

Ruby 2.5 以降は begin 明示しなくても do/end ブロックの rescue else ensure ができるようになった。

RSpec 3.7 Released: Now Integrates with Rails 5.1 System Tests

RSpec 3.7 は Rails システムテストに対応してる。これからは Feature スペックよりもシステムテスト推奨。Feature スペックと違って

PhantomJS Replaced with Chrome Headless in Rails

Rails の PhantomJS がようやく廃止となった。代わりに Selenium/Chrome Headless 導入。

Tutorial

Replacing RVM/rbenv with ASDF

プログラミング言語バージョン管理ツール asdf のインストール手順を紹介した、ブラジル RubyConf 元主催者 Fabio Akita 先生。rvm・rbenv と違って Elixir、Go、Node.js など多岐にわたる言語も一括管理。

A Quick Guide to Rails System Tests in RSpec

Rails システムテストに移行した Table XI 社 Noel Rappin 先生。

  • システムテストは Capybara でブラウザーを操作したテスト。
  • Capybara の既存 RSpec テストも、システムテストに移行すれば、色々楽になる。Rails と同じプロセスで動くようになるから。
  • 移行手順
    1. 各テストに type: :system メタデータ追加。
    2. テストファイルを spec/system フォルダーに移す。
    3. 原文の configuration 設置。
  • Circle CI 2.0 用設定は原文参照。

DIY Google reCAPTCHA with Rails

Rails アプリに Google reCAPTCHA 2 を設置する手順。

  1. Google reCAPTCHA 2 取得サイトでアプリを登録。
  2. ビューで reCAPTCHA の JavaScript ライブラリをロード。
  3. <script> 要素の onload コールバックで reCAPTCHA ウィジェットをロード。
  4. コントローラの before_action で reCAPTCHA を承認。再利用できるように、concerns モジュールにて実装。
  5. RecaptchaVerifier サービスオブジェクト実装して、注入した GoogleRecaptcha クラスに承認させる。
  6. GoogleRecaptchaGoogle reCAPTCHA API を叩くように実装。

Bridging Rails and Node.js with gRPC

React + Rails アプリを開発した Reverb 社は、クラサバ二重実装を避けるべく、React コンポーネントを Node.js で生成することになった。Rails ⇔ Node.js 通信は元々パフォーマンスの良い Unix ソケットだったが、各アプリサーバに React Rendering Engine (RRE) をデプロイする必要はあった。その手間を省くように gRPC + protocol buffer に移行することにした。

  1. .proto ファイルでインタフェース定義。
  2. protoc コンパイラーをインストール。
  3. grpc-tools gem で Ruby クライアント生成。
  4. Node 用 grpc ライブラリをインストール。
  5. Node 側サービス実装(原文コード参照)。
  6. Unicorn・Puma を使っている場合は、after_fork フックでクライアントを生成するように設定。

A 7-Step Approach to Rails Upgrades

Rails バージョンアップ手順。

  1. 新規 Rails アプリ作成。
  2. 既存アプリで新規ブランチ切る。
  3. 新規 Rails アプリの gem を既存アプリの Gemfile にコピペ。既存 gem は必要に応じてバージョンアップ。
  4. rails app:update 実行で config・bin ファイル更新。
  5. テストのエラー修正。deprecation 忠告は無効にしておくこと。
  6. deprecation 忠告を有効にして、ひとつずつ解消。
  7. main ブランチにマージ。

Trying Out Rails 5.1.x

Rails 5.1 アプリを作ってみた、ブラジル RubyConf 元主催者 Fabio Akita 先生。

  • 新規 Rails アプリ生成手順
  • webpack 採用手順

Rails 5.1 の大きな特徴はモダンな JavaScriptCSS への対応。

2 Ways to Test Eager Loading of ActiveRecord Associations in Rails

eager loading のテスト方法 2 つ。

  1. association(:name).loaded?
  2. ActiveSupport::Notifications で発行クエリ数取得

Story

Integrating React in a 6+ Year Old Rails App

6 年ものレガシー Rails アプリに React を導入した話。

  • モダンな JavaScript UI が必要となったのがきっかけ。
  • jQuery でもできたが、React のほうがメンテしやすいし、ES6・ES5 相互対応でブラウザ間互換性が魅力的。

戦略。

  • React 層をなるべく薄くし、routing は Rails に任せっきり(ページ間遷移は従来の HTTP)。
  • ActiveModel::Serializer フル活用。モデルのデータだけでなく、ActiveRecord メソッドまで呼べて便利。

Opinion

Please Stop Calling It 'Magic'

何でもかんでも「魔術」と呼ぶのをやめよう、という主張。コミュニティの創造力の妨げになるから。

  • 初心者には分からないからって「魔術」と呼んじゃダメ。
  • モンキーパッチは良くない場合もあるが、「魔術」とはいえない。
  • メタプロは「魔術」ではない。

これなら初めて「魔術」といえる。

class LandCruiserJ200Car
end

car = LandCruiserJ200Car.new
# => #<Car model="Land Cruiser J200">
car.drive! # "wroom! wrrroooom!"

何も継承してないのにどこかから挙動を継承してる。つまりソースの追いようがないコード。

Tools

Action Cable Testing Utilities

ActionCable テスト用 gem。Rails への PR としても出されてるが、Ruby Weekly 投稿時点では未マージ。

  • 継承用 ActionCable::TestCaseActionCable::Channel::TestCase
  • have_broadcasted_to broadcast_to RSpec マッチャー
  • Generator

7 Gems Which Will Make Your Rails Code Look Awesome

Rails コード可読性向上 gem 集。

  1. サービスオブジェクト用 interactor
  2. デコレーター用 draper
  3. フォームオブジェクト用 virtus
  4. ビューモデル用 cells
  5. 例外発生時リトライ用 retryable
  6. Controller ボイラープレート隠蔽用 decent_exposure
  7. 日時グルーピング scope 用 groupdate

Code

Hanami 1.1 Released

Hanami 1.1 リリース。

  • belongs_to has_one has_many through: アソシエーション
  • CLI は thor から hanami-cli に切り替えた
  • Hanami::Entity のカスタムスキーマ定義
  • ブートするアプリを HANAMI_APPS 環境変数で指定
  • パスワードなどがログに残らないようにフィルター

rom-factory: A Data Generator for Ruby Object Mapper (ROM)

rom-factory gem 新規リリース。FactoryBot(旧名 FactoryGirl)より 1.5 倍速く下記機能提供。

  • 動的 sequence
  • faker 同梱
  • アソシエーション対応
  • factory 継承

Ruby Weekly #371: 日本語サマリー

職場の Slack の #ruby 窓で Ruby Weekly メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

http://rubyweekly.com/issues/371rubyweekly.com

Highlights

Configuring Puma, Unicorn and Passenger for Maximum Efficiency

Puma、Unicorn、Passenger を効率よく設定する方法。

  • サーバ毎に 3 子プロセス以上。上限は (合計 RAM / (あなたのウェブアプリのプロセスの 12 時間経過後の RAM * 1.2)) で計算。
  • MRI はサーバ毎に 5 スレッドで良い。JRuby は子プロセス数同様に計算。
  • とりあえず preloading オンにしようぜ。
  • サーバは RAM 1GB 以上。正確には 5 スレッドの 1 ワーカの 12 時間経過後の RAM * 3 で計算。

時間経過とともに膨らんだ Puma ワーカー。

Why Ruby App Servers Break on macOS High Sierra

先月発表された macOS High Sierra 上の Puma 不具合解説。

  • macOS が許可している fork 後処理が変わった。
  • 許可されてない処理を踏んだアプリサーバが Objective-C エラーを起こす。Objective-C に一切依存していないのに。
  • Apple 社が High Sierra の fork 挙動を変えたのは、Objective-C の fork 対応をやりやすくするため。
  • Puma などアプリサーバ開発者は、Ruby 言語レベルで対応すべきだと主張してる。
  • ワークアラウンドを実装したのは Passenger のみ。
  • Puma、Unicorn、iodine ユーザは環境変数指定で一応対応できる。

Fastest Way to Profile a Method in Ruby

Ruby メソッドの最も軽量なプロファイリング方法。

  • 時間計測は Time.now ではなく Process.clock_gettime(Process::CLOCK_MONOTONIC)
  • メソッドのパッチは prepend ではなく alias_method
  • スレッドセーフにする必要がある場合は、Thread.current["hoge"] でデータ保存。

Passenger 5.1.11 Released: A Key Security Release

Passenger 5.1.11 リリース。

  • システムフィアルが一覧表示できちゃう脆弱性対応
  • macOS High Sierra 対応
  • HTTP/2 対応
  • 遅延ポートバインディング用オプション追加
  • root 権限チェック・忠告追加

Visualizing Rails Logs With Jupyter Notebook

「重いよ!」と訴えるユーザに応じて、Jupyter NotebookRails ログ可視化手順。

  1. lograge logstash-event logstash-logger gem でログのフォーマットを JSON に。
  2. ユーザ ID をスレッドのローカル変数に持たせる。
  3. Jupyter Notebook の json_normalize() 関数で Pandas Dataframe にログをインポート。
  4. Dataframe.head で全体データをサニティーチェック。異常なし。
  5. Dataframe.describe で全体データを集計チェック。異常なし。
  6. 全体データのヒストグラム生成。異常なし。
  7. ユーザのデータに絞ったヒストグラム生成。異常なし。
  8. ユーザの 1 秒以上かかったコントローラ・アクションの棒グラフ生成。異常あり。

ROM 4.0.0 Released: The Ruby Object Mapper

ROM 4.0.0 リリース。

  • rom-repository gem のスキーマ自動マッピング(カラム情報を DB から読み込む機能)が ROM コアにて実装された。
  • rom-repository gem の auto_struct マッピング(データを Struct に設定する機能)が ROM コアにて実装された。
  • カスタム Struct が定義可能に。
  • changesetrom-changeset gem に抽出された。

News

Monitor, Debug and Log Your Ruby Apps with Stackdriver

GCP でも AWS でも使える stackdriver gem を紹介した Aja Hammerly 先生。

Tutorial

Rescue Specific Errors. Avoid Rescuing StandardError

rescue では例外をちゃんと指定しようぜ、という催促。

  • rescue Exception だと、SignalException::Interrupt まで rescue され、強制終了できなくなっちゃう。
  • rescue => e だと、予期せぬバグが隠蔽されちゃう。

Using JSON Web Tokens for Authentication in Distributed Systems

分散システム(マイクロサービスなど)の共通認証を JWT で実装する方法。Devisejwt gem を採用した例。

OOP and Rails System Tests

オブジェクト指向Rails システムテストを整理する方法。gem なしでページオブジェクトパターンを実装し、partial など共通 UI をモジュールに抽出している。

Migrating Data From MongoDB to Postgres with No Downtime

MongoDB が用途に合わなくなった Contractually 社がダウンタイムなしで PostgreSQL にデータを移行した 3 ステップ戦略。

  1. 第 1 デプロイ:稼働中のデータを MongoDB にも PostgreSQL にも WRITE。READ は MongoDB から。
    • Mongoid のコールバックで PostgreSQL に書き込むバックグラウンドジョブをキューに積む。
    • 12〜36 時間で移行完了の想定。
  2. 第 2 デプロイ:稼働中のデータの READ も WRITE も PostgreSQL から。
    • NewRelic でパフォーマンス・エラー発生率監視。
  3. 第 3 デプロイ:Mongoid、MongoDB 削除。
    • 予めバックアップ。

What Can You Do with The Array#zip Method?

Array#zip 活用案いろいろ。

  • 2 つの配列を比較する。
  • 2 つの配列の各インデックスの最大値を取得する。
  • キーの配列と値の配列を結合してハッシュを作る。
  • Enumerable#count とチェーンして同一要素を数える。
  • シーザー暗号を実装する。

The Command Pattern in Ruby

ホテルを例に挙げたコマンドパターン解説。

  1. 宿泊客がルームサービス、ランドリー、観光地パンフレットをコンシエルジュに注文。
  2. コンシエルジュが注文を厨房、クリーニング作業員、ベルボーイに依頼。

そのまま実装すると Concierge オブジェクトにキモい case 文ができてしまう。各注文をコマンドオブジェクトにすることで、Concierge がロジック分岐せずに実行できるようになる。おまけに

  • Concierge 以外のオブジェクトにも引数として渡せる。
  • 注文をキューに積むことができる。
  • 注文をログに残すことができる。
  • 注文を巻き戻すことができる。

Sanitize Attributes Through Your Form Object with Virtus

Virtus gem のフォームオブエクトでデータをサニタイズする例で、Virtus::Attribute#coerce でホワイトスペースを文字列から消してる。

A Practical Guide to Using ActionCable

プロジェクト管理ツールの UI をリアルタイムで更新するための ActionCable 実用ガイド。Build A SaaS App in Rails 5 本の抜粋。

Exploring Functional Programming with Ruby

関数型プログラミングをずっと警戒してた Rubyist をやっと説得できたリンク 3 つ。

  1. Rubyオブジェクト指向関数型プログラミングを融合した、dry-rb コアチームの Piotr Solnica 先生のトーク
  2. dry-rb コアチームの Tim Riley 先生のブログシリーズ
  3. Hanami 作成者 Luca Guidi 先生のトーク

Code

InvoicePrinter 1.0: PDF Invoice Generation from Ruby

請求書 PDF 生成用 InvoicePrinter gem。 見辛い Prawn コードをカプセル化したのが売り。

Karafka: A Ruby Framework for Working with Apache Kafka

Kafka + Ruby アプリ用 MVC フレームワーク

Hanami 1.1.0.rc1 Released

Hanami v1.1.0.rc1 リリース

  • アソシエーションの alias 定義可能に belongs_to :user, as: :author
  • カスタムスキーマのデータ型を任意 Entity で設定可能に
  • hanami generate model コマンドの新規オプション --relation (テーブル名)
  • RSpecメタデータ追加