rastam on rails

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

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

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

rubyweekly.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 メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

rubyweekly.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 メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

rubyweekly.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 メルマガが毎週配信されます。その中から面白そうなものをピックアップして、日本語で簡単なサマリーを書くようにしています。そのサマリーをここでまとまさせていただきます。くだけた日本語で失礼いたします。

rubyweekly.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メタデータ追加

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

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

rubyweekly.com

Highlights

Ruby 2.5 Preview 1 Released

Ruby 2.5 Preview 1 リリース!

  • do; end ブロック内 rescue 対応。
  • yield_self 新規追加。
  • bundler 同梱。
  • 同一ネームスペース内で見つからなかった定数をルートネームスペースから探すのがなくなった。

Unsafe Object Deserialization Vulnerability in RubyGems

RubyGemsリアライゼーション脆弱性を解説した Aaron Patterson 先生。 gem のチェックサムYAML で保存されているのが原因。 RubyGems.org はこの脆弱性で攻撃された痕跡はない。 シリアライズ可能なオブジェクトをホワイトリストすることで解消済み。

ReportsKit: Add Reporting to Your Rails App in Minutes

レポート用 Rails engine。

Introducing hanami-cli: A New Framework for Command Line Tools

hanami-cli を紹介した、Hanami 作成者 Luca Guidi 先生。 thor では実装しづらい下記機能がある:

  • サブコマンド。例えば $ hanami generate actiongenerate action
  • 拡張性。外部 gem が Hanami にサブコマンドを追加できるようになった。

Hanami じゃなくても使えるので、thor の代替案として考えれば良い。

Top-Level Constant Lookup Removed in Ruby 2.5

同一ネームスペース内で見つからなかった定数をルートネームスペースから探すのが Ruby 2.5 からなくなった。その経緯を語る Redmine チケット。

Monkey Patching in Ruby: A Real World Example

Surrealist gem に対応するように、ArrayActiveRecord::Relation のモンキーパッチを検討した話。 下記条件全部満たせなければ、モンキーパッチやめたほうがいいと。

  • これ以上のモンキーパッチはない。
  • モンキーパッチしたコードに依存しているものが壊れない。
  • モンキーパッチ以外の選択肢がない。
  • 新しいインタフェースが作れない。

Organizing My First Conference: Southeast Ruby

カンファレンスを初めて主催した経験談。地方カンファレンスがなくなってきたのがきっかけ。

  1. 昔あったナッシュビル市の Ruby Hoedown カンファレンス主催者から許可を得た。
  2. ドメイン取得(自腹)。
  3. 会社設立(自腹)。
  4. ロゴ発注(自腹)。
  5. キーノート登壇者を招待した。
  6. CFP を 1.5 ヶ月開催。もうちょっと長くすればよかった。
  7. 予算計算。$199 のチケットを 175 枚売れば黒字。
  8. 会場探し。
  9. スポンサー探し。大変だったため、プランはもうちょっと安くすればよかった。
  10. 登壇者宿泊 + 交通費負担することにした。
  11. チケット発売。SNS + Ruby Flow + Reddit で宣伝。87 枚売れた。
  12. カンファレンス 3 日間開催。

赤字だったが、Ruby コミュニティに貢献できた充実感で、来年も開催予定!

News

Rails 5.2 Adds Options for Signed and Encrypted Cookies

Rails 5.2 では、暗号化・署名付きクッキーの有効期限が設定可能に。

RubyElixirConf Taiwan 2018 Call For Papers Open

台北の RubyElixirConf Taiwan 2018、CFP 開始。

New Book Released, 'Mastering Ruby Strings and Encodings'

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 でメールを受信・パースする手順。

  1. ngrok で手元マシンへの URL を用意。
  2. Mailgun で受信したメールを ngrok URL に転送するように Mailgun を設定。
  3. Griddler gem を Rails アプリにマウント。
  4. EmailProcessor オブジェクトでパース・処理を実装。

HTTP2 Early Hints in Rails 5.2+

Rails 5.2 の HTTP2 Early Hints を発表した Eileen Uchitelle 先生。Rails がレスポンスを 2 つ返すようになる:

  1. Early Hints(HTTP ステータス 103)
  2. 通常のレスポンス(HTTP ステータス 200、404、500 など)

Early Hints はブラウザーが優先的にダウンロードするファイル(JavaScriptCSS など)の指定。Rails での検証手順も記載されてる。

A Look at Ruby 2.5's Improved Stacktraces

Ruby 2.5 スタックトレースの見た目改善。エラー発生行番号が一番下になった。長いスタックトレースの上までスクロールすることがなくなって便利。しかし RailsRSpec では効かない。

Extracting a Class from a Method

巨大メソッドをクラスに抽出した話。

7 Little-Known Ruby Methods To Help You Write Better Code

Ruby のよく知られてないメソッド。

  1. Integer#digits (Ruby 2.4 以降)
  2. #tap
  3. Array#values_at
  4. Hash#transform_values (Ruby 2.4 以降)
  5. Kernel#itself (Ruby 2.2 以降)
  6. Array#count
  7. Enumerable#cycle

Upload Images to S3 in GraphQL Using Rails and Paperclip

PaperclipRails GraphQL API から画像を S3 にアップロードした話。REST アプリならドキュメンテーションはいっぱいあるが、GraphQL アプリは一切ない。画像を Base64 文字列に変換してから mutation の引数として Paperclip に渡した。

PDF Filter Implementation in HexaPDF Using Fibers

HexaPDF gem の PDF ファイル読み込み処理解説。

  • PDF ファイルは不特定多数のストリームで構成されてる
  • 各ストリームには不特定多数のフィルターが指定されてる
  • フィルターはストリームデータの解読方法を定義している(例:JPEG 画像は DCTDecode フィルター、ASCII 文字列は ASCIIHexDecode フィルター)
  • フィルターはそれぞれ HexaPDF::Filter::ASCIIHexDecode のようなモジュールで実装されてる
  • ストリームは HexaPDF::StreamData オブジェクトでカプセル化
  • ストリームのデータは非同期で読み込むため、Ruby の Fiber 採用

A Guide to Understanding the Rails Directory Structure

Rails フォルダー構造まとめ。

Updating Deeply Nested Attributes with RSpec

RSpec で深階層の nested attributes を指定した話。手で組み立てるのが大変だった。先輩に相談したら、ログからコピペすることになった。

Tools

nullalign: Generate Warnings for Missing Not-Null Constraints

NOT NULL 制限のない validates presence: true を検知してくれる nullalign gem。

Code

PgParty: PostgreSQL 10 Partitioning for ActiveRecord

ActiveRecord + PostgreSQL 10 パーティション管理用 gem.

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

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

rubyweekly.com

Highlights

Could We Drop Symbols From Ruby?

SymbolString の不一致がバグの根源なので、Ruby から Symbol を捨てないかという提案。

  • 下位互換性を維持するには、Symbol#freeze した String にすれば良い。
  • Symbol#to_s から #freeze されてない String を返すようにする。
  • #hash を同等にする必要がある。Symbol#hash 計算が 2〜3 倍速いから、String#hash 計算も Symbol#hash に合わせたい。

Fixnum Bignum 捨てたし、Symbol も捨てれるのでは?と。

Ruby Dev Summit: A Free Online Event for Rubyists

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。

Rediscovering Modularity in Ruby

株式会社デジカの Chris Salzberg 氏が RubyKaigi でトークを発表した話。たまたま Matz のキーノートと同じく、モジュールを題にしてた。しかし「モジュールはクラスではない」と言わんばかりの Matz 発言が Salzberg 氏のトークと矛盾してたのでちょっと困った。ModuleClass だからこそ Ruby ならではの Module Builder パターンが可能。

'ubygems.rb' Removed from Ruby Core

-rubygems に対応するための ubygems.rb が削除された、というちょっと面白いコミット。

Embracing Functional Programming in Ruby

Gusto 社の給与システムが関数型 Ruby になるようにリファクターした話。

  • PFaaO パターンで純粋関数オブジェクトを実装した。給料計算関数オブジェクトを例として挙げた。
  • 純粋関数オブジェクトなので、メモ化していても参照透過性が維持されてる。
  • 給料計算関数オブジェクトの中の税金計算メソッドを税金計算関数オブジェクトに抽出した。
  • ActiveRecord モデルそれぞれに対して immutable な Value Object を切って、純粋関数オブジェクトにValue Object のほうを渡すようにした。

News

Announcing Hanami V1.1.0.beta3

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 機能など込み。

How to Program Vim Using Ruby

RubyVim プログラミングした話。

  1. Angular プロジェクトの該当 directive ファイルを開く関数

Perusing delegate.rb from Ruby’s Standard Library

Ruby コアの delegate.rb をコードリーディングした話。

  • Delegator が継承しているのは、不要なメソッドを省略された Kernel
  • #initialize #method_missing メソッドは Delegator にて実装されている。
  • デリゲート先オブジェクトの accessor は SimpleDelegator など子クラスで実装されている。
  • #method_missing がチェックするのはデリゲート先オブジェクトと一部省略した Kernel

Accessing Hash Values with Fallbacks for Missing Data

Hash#fetch でデフォ値を返すようにする。ブロック渡せば遅延評価もできる。

One Simple Trick to Make Event Sourcing Click

筆者著作の Domain-Driven Rails 本の抜粋。メソッドを 2 つのメソッドに分解することで Event Sourcing するというルールの解説。2 つのメソッドとは:

  1. イベントを発行するメソッド
  2. イベントの効果を適用するメソッド

Some Interesting Methods and Behavior with Arrays in Ruby

Ruby 配列いろいろ

  • #initialize 方法いろいろ
  • #slice 方法いろいろ
  • #insert 方法いろいろ
  • <=> 挙動
  • | 挙動
  • & 挙動

Ruby 2.4 Has Optimized Enumerable 'min' and 'max' Methods

Ruby 2.4 では Enumerable#min Enumerable#max Enumerable#minmax が速くなった!

Considering Performance and Unique Validations in Rails

validate uniqueness: 使用時の高速化案。

  1. インデックスを張ること。Rails の validation を高速化するため。
  2. UNIQUE インデックスを張ること。Rails の validation を完全に省けるため。

筆者作品の UniqueValidationInspector gem では、インデックスのない validate uniqueness: を検知できる。

Ways to Check Which Ruby Version You're Using

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 スレ。

How A Lifelong Rubyist Made Some Python Code 5x Faster

Python コードのパフォーマンスを最適化した Richard Schneeman 先生。

Ruby との共通ルール:

  • ダブってるロジックを省けば軽くなる。
  • オブジェクトのインスタンス化を省けば軽くなる。
  • オブジェクトのシリアライズを省けば軽くなる。例:シリアライズした配列を引数として渡すよりも、要素を渡したほうが軽い。
  • ループ内のリテラルを省けば軽くなる。リテラル=オブジェクトのインスタンス化なので。
  • 不要なロジックを省けば軽くなる。あり得ない if 文の分岐点など。
  • メソッドを省けば軽くなる。効果はそんなに大きくないので、このルールに関しては無理しなくて良し。
  • ベンチマーク必須。
  • キャッシュするなら、オブジェクトのインスタンス化ルールは破って良し。

What I Learned After Going 18 Months Without Rails

レガシー Rails アプリに呆れて、18 ヶ月も Rails を避けていた経験で得た知見。

Opinion

Don't Use default_scope. Ever. Here's Why.

default_scope ではなく明示的に scope 使おうという主張。

  1. new したモデル属性は default_scope で設定されちゃうのが予期せぬバグの元。
  2. default_scope を外すことは辛い。 unscoped だとアソシエーションのスコープまで外れちゃったりするから。

Tools

Recommended Ruby and Rails Books for Experienced Developers

Ruby 上級者向け書籍。

  1. オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方
  2. Rubyのしくみ -Ruby Under a Microscope-
  3. Effective Ruby
  4. Ruby Way 第2版 (Professional Ruby Series)
  5. Mastering Ruby Closures: A Guide to Blocks, Procs, and Lambdas
  6. Rails, Angular, Postgres, and Bootstrap: Powerful, Effective, Efficient, Full-Stack Web Development
  7. 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。

Virtualearth: Bing Maps API Wrapper

Bing Maps API クライアント用 gem。