週刊Railsウォッチ(20170407)N+1問題解決のトレードオフ、Capybaraのテスト効率を上げる5つのコツほか

こんにちは、hachi8833です。HackerNewsにあがってたHOW BANK OF AMERICA GAVE AWAY MY MONEYをつい読んでしまいました。いかにもコントやショートショートにありそうな話ですが、実際に起きるとめちゃ怖いですね。たぶんそのうちどこかの海外ネタサイトに載ると思います。

Ruby 2.1のサポート終了(Ruby公式ニュースより)

発表日が4/1だったので、すわエイプリルフールかと思いきや、1年前の予告どおりのスケジュールでの発表でした。

昨年 3 月末の Ruby 2.1.10 のリリース後、Ruby 2.1 系列はセキュリティメンテナンス期間に入っていましたが、予定の 1 年が経過しましたので、2017 年 3 月 31 日をもって、公式サポートを終了します。 以後、単なるバグの修正はもちろん、セキュリティ上の問題が発見された場合も、Ruby 2.1 系列については新たなリリースは行われません。 現在、Ruby 2.1 系列を使用中のユーザーは、速やかに、より新しいバージョン系列へと移行されるようお願いします。
Ruby 2.1 公式サポート終了より

メンテナンスポリシーはソフトウェアによってさまざまですが、Rubyの場合、ライフサイクルをどのように決定するかというはっきりした原則が今のところ見当たらないようです。一同でチェックしながら、現在のバージョンのライフサイクルをいつ終了させるかはコミュニティ任せなのかもしれない、という話題になりました。

Railsのアップグレードはそれなりに手がかかりますが、Railsで使われるRubyのアップグレードはスムーズにできるので、古いRailsでもRubyだけは最新にしている方も多いと思います。私も先日オレオレRails4アプリでRubyだけは2.4.1にアップグレードしましたが、Rubyが新しくなるたびにじわじわと速くなっているのを実感できます。

rails newから--javascriptオプションが削除される(Rails公式ニュースより)

JavaScript周りの変更にともない、Rails 5.1で--javascriptオプションが削除されます。

削除されたコード


railties/lib/rails/generators/app_base.rbより

従来Railsで使われていたJS系gemには「xxx-rails」といった名前のものがよく目につきますが、Rails 5.1でyarn管理に移行した後、「xxx-rails」系gemの多くがdeprecatedになるのかもしれないといった話題になりました。

driven_byがオーバーライド可能に(Rails公式ニュースより)

Rails 5.1への導入が決まっているCapybaraを活用した新しいブラウザ表示テスト用クラスであるSystemTestCaseで、テスト中に動的にseleniumやrack_testといったドライバを#driven_byで切り替えられるようになりました。

# https://github.com/rails/rails/pull/28586より
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :chrome, screen_size: [1400, 1400], options: {url: "http://chrome:4444/wd/hub"}
end

class WithJavascriptTest < ApplicationSystemTestCase
end

class WithoutJavascriptTest < ApplicationSystemTestCase
  driven_by :rack_test  # ドライバの切り替え
end

複数ブラウザの表示とJavaScriptのテストはどうしても面倒になりがちですが、ブラウザ間の挙動の違いをSystemTestCaseでテストするのが少し楽になりそうです。

reverse_mergeのエイリアスwith_defaultが追加(Rails公式ニュースより)

Railsウォッチ(20170317)でお伝えしたreverse_mergereverse_merge!の追加(#28355)の続きです。

メソッド名にエイリアスを追加しただけというシンプルな内容ですが、reverse_mergeという生々しすぎて挙動を推測しづらいメソッド名に、strong_parametersにデフォルト値を追加できることがはっきりわかるwith_defaultsというエイリアスを追加したことで使いやすくなりました。

alias_method :with_defaults, :reverse_merge
...
alias_method :with_defaults!, :reverse_merge!

「こういう改修って大事だよね!」という声多数でした。名前は大事。

rails-ujs.jsのUMDモジュールサポートを修正(Rails公式ニュースより)

従来のjquery-ujsがjQuery依存脱却にともないrails-ujsと名称が変更されましたが、それに伴いUMDが使えなくなっていた問題が修正されました。今回知りましたが、UMD(Universal Module Definition)はクライアントとサーバーの両方で動作するJavaScriptモジュール定義のことでした。

jquery-ujsはRuby on Rails用に開発されたjQueryライブラリですが、jquery-railsと違い最新のjQueryを取ってくることまではしません。今に始まった話ではありませんが、JavaScript周りはgem名もいろいろあってわかりにくいですね。

参考

N+1問題とメモリの問題を同時に解決できない理由(RubyWeeklyより)

N+1問題についての解説記事です。よい感じです。

記事をチェックしていて、「bullet gemに怒られそうだけど、確かにN+1問題はどんな場合にもバッドプラクティスというわけではないよね」という話題になりました。元記事でも、N+1問題を解決したために、使いもしないオブジェクトが大量に生成されてメモリを逆に圧迫してしまう問題と、対処の方法について触れられています。

たとえば巨大なデータを扱うバッチ処理を小分けにするといった状況では、N+1問題を修正することが必ずしも善とは限らないことを教わりました。

Rubyの一部のコードにシンボル処理を追加して高速化(RubyWeeklyより)

Rubyのパフォーマンス測定とパッチ当ての話なのでC言語が中心です。一同でチェックしていて「よく見つけたなこれ」と驚きの声が上がりました。


Making Ruby’s Array.include? faster for symbolsより

最終的に、vm_insnhelper.cでシンボルがまったく処理されていないことを突き止め、以下のように修正しています。


Making Ruby’s Array.include? faster for symbolsより

その後修正は一発でmergeされました。殊勲賞あげたくなっちゃいました。

同記事で参照しているRuby C APIガイドもよい資料ですね。

ポルトガルのRubyカンファレンスは今年は休み(RubyWeeklyより)

「今年で終わりではないが、ポルトガルでのコミュニティが今ひとつ盛り上がってないから」だそうです。ざっとググってみたところ、Rubyはポルトガル語圏ではそれほど盛り上がっていないようです。

Rubyのサブクラスをregistryに変更してリファクタリング(RubyWeeklyより)

これもよい感じですね。一同でチェックしていて「継承より委譲」という言葉が出てきました。

その後、「学校や教科書でオブジェクト指向を教えるときに、最初に継承を教えるのはあまりよくないかも」「実際に使うのはコンポジションとかの方が多いし」「他の項目との関連もあるから、継承を先に教えるのはある程度仕方がないけどね」などと話題が広がりました。

Mobility: 多言語の訳文をクラスの属性として利用できるgem(RubyWeeklyより)

Railsウォッチ(20170217)でご紹介したsvenfuchs/i18n-active_recordと同様の、多言語対応gemです。

# https://github.com/shioyama/mobility より
class Word < ApplicationRecord
  include Mobility
  translates :name,    type: :string
  translates :meaning, type: :text
end

こんなふうに多言語をActiveRecordの属性として扱えるようになります。脱yamlの多言語化の流れが加速していることを実感します。

word = Word.first
I18n.locale = :en
word.name
#=> "mobility"
word.meaning
#=> "(noun): quality of being changeable, adaptable or versatile"
I18n.locale = :ja
word.name
#=> "モビリティ"
word.meaning
#=> "(名詞):動きやすさ、可動性"

Mobilityのチェック中に、Webチームリーダーのmorimorihogeさんが「これ、同じようなのを随分前にbabaさんと作ったことある!」と、その場で社内GitLabのコードを見せてくれました。

BPSが長年運営している漫画翻訳サイト「MANGA REBORN」はRuby on Railsで構築されていますが、当初から2人によってがっつりと多言語化を意識した設計がなされていることを、私たちもその場で初めて知りました、マジで。

MANGA REBORNのマスコットキャラクター「マリちゃん」です

見せてもらったコードでは、漫画の日本語/英語タイトルといった属性を多言語コンシャスでモデル設計に盛り込み、かつ#__send__などのメタプログラミングを駆使したコードになっていて、予想より遥かにシンプルでした。

morimorihogeさんいわく「当時ActiveRecordを知って『Railsってこんなことできるんだー!』と感激した勢いで作ったのを思い出した」そうです。

5年以上も前にRailsアプリでここまで多言語化を追求していたとは…自称多言語厨の私も脱帽でした。

deep_pluck: ネストした関連付けでもeager loadingせずに#pluckを使えるgem

Railsのカラムを配列で取るのに多用される#pluckを、ネストした関連付けでeager-loadingせずに行えます。パフォーマンスもいいですね。

# https://github.com/khiav223577/deep_pluck より
User.where(:name => %w(Pearl Kathenrie)).deep_pluck(
  :name, 
  :email, 
  'posts' => [:name, 'post_comments' => :comment], 
  'contact' => :address,
)

これは知っていて損はないgemですね。今さらですがpluckは「むしる、つまみ取る」という動詞です。

LittleBoxes: 依存性注入gem


https://github.com/manuelmorales/little-boxesより

Rubyで依存性注入を行うフレームワークだそうです。

# https://github.com/manuelmorales/little-boxes より
module MyApp
  class MainBox
    include LittleBoxes::Box

    let(:port) { 80 }            # 注入
    letc(:server) { Server.new } # 依存関係を指定して注入
  end

  class Server
    include LittleBoxes::Configurable

    dependency :port
  end
end

box = MyApp::MainBox.new
# => #<MyApp::MainBox :port, :server>

box.server.port
# => 80

「JavaならわかるけどRubyで使うところあるかな?」という意見もありました。Javaではロガーを書くときなどにこうした依存性注入がよく使われるそうです。ご興味のある方はどうぞ。

geared_pagination: ページに応じて項目数が可変になるページネーションgem

1ページ目は30件、2ページ目は50件というふうにページによって件数を変えるgemだそうです。ネーミングからして、自動車などの変速ギヤのイメージですね。

「こういうのより、下までスクロールしたら件数が追加される方がいいと思う」「でもスマホだと一番下の [PC版に切り替える] がどんどん逃げて押せないサイトあるよねw」といった話題になりました。

ご興味のある方はどうぞ。

Capybaraのテスト効率を上げる5つのコツ(RubyFlowより)

短いですが良い記事です。CapybaraやRSpecはチートシートが無味乾燥だったりマッチャを覚えるのが面倒だったりするので、こういう具体的なノウハウ集は助かりますね。

ただ、JavaScriptのイベント完了を待つ手法は「それはちょっとなー」と一斉に声が上がりました。

Pluto: RSSフィードから静的Webサイトを生成するgem(RubyFlowより)


http://feedreader.github.io/より

少々変わり種のgemです。RSSフィードから静的なWebページを生成します。ERBを書いてmiddlemanばりのカスタマイズもできます。

# http://feedreader.github.io/ より
<% site.feeds.each do |feed| %>
  <%= feed.url %>  or  <%= feed.link %>
  <%= feed.title %>  or  <%= feed.name %>
  <%= feed.title2 %>
  <%= feed.feed_url %>  or  <%= feed.feed %>
<% end %>

どこかでちょっとした使いみちがありそうな気がします。過去ブログのアーカイブ化やデジタルサイネージなどに使いみちあるかもという意見がありました。

tty-progressbar: CLIプログレスバーgem(RubyFlowより)

RubyでCLIのプログレスバーを作るgemです。今どきらしく色をつけるなどのカスタマイズがいろいろできます。

Piotrrrrr
downloading [======================= ]

MathJaxのCDNが今月いっぱいで閉鎖


https://en.wikipedia.org/wiki/MathJaxより

たまたま見つけました。数式表示用JavaScriptライブラリMathJaxのCDNが閉鎖されます。代替としてcdnjs.comを推奨しています。

数式表示にMathJax CDNを使っている有名ブログサイトはあちこちにあった気がするので要注意ですね。

Jupyter 5.0リリース(HackerNewsより)

ブラウザ上でコードを実行・記録可能なドキュメントシステムとして、機械学習系を中心に急速に人気が高まっているJupyterのバージョン5.0がリリースされました。もともとPython用でしたが、あっという間にRubyを始めさまざまな言語に対応しました。

  • ファイルリストを画面上でソート
  • キーボードショートカットのカスタマイズ
  • Cell tag機能で、コード中のプレースホルダに画面から値を入力・実行できる↓


Jupyter Notebook 5.0より

研究以外にも、社内研修、教育、プレゼンなどに役に立つツールだと思います。

C言語1000行足らずでシンタックスハイライト付きのテキストエディタ書いたった(HackerNewsより)

手元でgit cloneしてmakeしたらちゃんと動きました。終了はCtrl-Q連打で。

それだけならよくあるサイトなのですが、本人によるソースコード解説がものすごく詳細なのに驚きました。コード量より文章量の方が明らかに多いですね。凄い。

Twitter Lite発表(HackerNewsより)

https://lite.twitter.com/でPCでもモバイルでも使えます。
確かに従来より軽快です。これいいですね。

教師なし感情ニューロンを開発(HackerNewsより)

これはマジで驚きです。Amazonレビューの文章をサンプルに用いて、次にどんな文字が来るかを感情ニューロンに予測させる研究中に、レビューに含まれる書き手の感情(ポジティブまたはネガティブ)を高い精度で検出できたのだそうです。教師なし(unsupervised)なので、人間が手取り足取り指示しなくてもデータを食わせるだけで違いを学習したということですね。


https://blog.openai.com/unsupervised-sentiment-neuron/より

以下のように、好意的な文を緑、否定的な文を赤でハイライトするアニメーションGIFも掲載されています。


https://blog.openai.com/unsupervised-sentiment-neuron/より

機械学習系の成果でよくあることですが、これも原理はまだよくわかっていないようです。
こういう機能が近々Rubygemなどで利用できるようになるかもしれません。

小ネタ: forty_twoドキュメントの引用が間違っていた(Rails公式ニュースより)

Silly method gets a silly doc fix,

「アホなメソッド名でアホなドキュメント修正」だそうです。fourty twoというメソッド名については以下をどうぞ。

参考: RailsのArray拡張にforty_twoがいる謎

今週は以上です。

関連記事

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

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

Ruby 公式ニュース

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Hacker News

160928_1654_q6srdR

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833 コボラー、ITコンサル、ローカライズ業界を経てなぜかWeb開発者志願。 これまでにRuby on Rails チュートリアルの大半、Railsガイドのほぼすべてを翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ