週刊Railsウォッチ(20170602)チームが喜ぶ19のgem、Bundler 1.15が高速化&機能追加、Deviseに挑戦する新認証gem「Rodauth」ほか

こんにちは、hachi8833です。週刊Railsウォッチ末尾の「関連記事」がだいぶ多くなったので今回から昨年分を削りました。すっかり夏日ですね。

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

新機能: スレッド独立な属性シングルトンActiveSupport::CurrentAttributes

DHHがactivesupport/lib/active_support/current_attributes.rbをまるまる書き下ろしています。

たとえば「現在のユーザー」をコントローラでもモデルでもルーティングでもビューでも同じように取れるようにした、と理解しました。グローバル変数のような凶悪なものではないにしても、このシングルトンはかなりそれに近い位置づけのようです。DHHも「使いすぎに注意」と警告しています。

ChangeLogより:

主なユースケースは、リクエストごとの属性を全部まとめてシステムのどこでも読み書き可能にすること。

コードが長いので引用しづらいですが、結合テストから短めのものを見つけました。

## https://github.com/rails/rails/blob/156a506875889748f382ddd2946e480fe5389a29/railties/test/application/current_attributes_integration_test.rb#L12
      class Current < ActiveSupport::CurrentAttributes
        attribute :customer
        resets { Time.zone = "UTC" }
        def customer=(customer)
          super
          Time.zone = customer.try(:time_zone)
        end
      end

後はCurrent.customer.なんちゃらで読んだり書いたりする、という感じでしょうか。

つっつきボイス: 「DHH、毎度のことながら大胆だなー」「『嫌なら使うな』ってことなんでしょうね」「railtieto_runto_completeはそれぞれ実行前、実行後なのか」


ついでながら、以前から疑問だったことをつっつきの場で聞いてみました。「Railsのrailtieって何でこういう名前なんでしょうか?railsのutilityだから?」

「railtieって、『仲間』『つなげる』みたいなニュアンスですかね。Rails::Railtie を継承したクラスではRails起動時の処理を書けるようになったり、Rails::Engineの場合は /app の下がアプリとほぼ同等の扱いになったりするんです。」

おー、「rail」と「tie(結びつける)」の合成ということなのでしょうか。今までcookieみたいな語尾かと思っていました(違ってたらすみません)。railtiesと複数形になっていることが多いですね。

そして先ほど画像でググってみてやっと納得できました。線路と枕木をつなぎとめるものを指すんですね。「レイルティー」じゃなくて「レイル・タイ」と。

参考: Gem、Railtieプラグイン、Engine(full/mountable)の違いとそれぞれの基礎情報

新機能: cookieとセッションの暗号化

cookieの暗号化方式を段階的にAEAD(認証付き暗号)のAES-256-GCMに移行するそうです。暗号化方式が古いcookieをコンバートするコードまで入っています。

        @encrypted ||=
           if upgrade_legacy_signed_cookies?
             UpgradeLegacyEncryptedCookieJar.new(self)
+          elsif upgrade_legacy_hmac_aes_cbc_cookies?
+            UpgradeLegacyHmacAesCbcCookieJar.new(self)
           else
             EncryptedCookieJar.new(self)
           end

ガイドも更新されました

移行の理由: GCMなら認証と暗号化が一括処理できるし、SHA1衝突問題の対応も始めておきたい。AEADは一般にシンプルでエラーが起きにくいし。

つっつきボイス: 「古いcookieまで面倒見るのかー」

修正: secrets:editsecrets:setupも実行

rails secrets:setupしてなくてもrails secrets:editを実行できるようになりました。

# https://github.com/rails/rails/pull/29195/files#diff-39e92f58049d45463507199343fe3ba1L39
-        unless File.exist?("config/secrets.yml.enc")
+        unless (defined?(@@skip_secrets_file) && @@skip_secrets_file) || File.exist?("config/secrets.yml.enc")

なお、rails secrets:setupすると以下が追加されます。

# config/environments/production.rb
config.read_encrypted_secrets = true

つっつきボイス: 「これでちょっと親切になったかも」「今まではsetupしないとeditできなかったのか」


そこからRailsの標準プリローダーであるspringの話に発展しました。

つっつきボイス:
「こういう親切がありなら、rails db:migrateのときとかに自動でspring stopしてくれてもいいのにー。忘れた頃にマイグレーション邪魔される」
「spring邪魔、意義わからんw」
spring stopじゃぬるい、私なんかspring killしてますよ」
「気になる人は↓こうしてみてはどう?」

DISABLE_SPRING=1 rails db:migrate

( ・∀・)イイ!!こと教わった。

修正: 数値バリデーターのリグレッションエラーを修正

# https://github.com/rails/rails/commit/d83b8e65102d625c9024cd9a2727a10b0ef83b79#diff-58f66170fe2bce77e8a8b3c69b77a0d6L39
-        unless raw_value.is_a?(Numeric)
+        if raw_value.is_a?(Numeric)
+          value = raw_value
+        else
           value = parse_raw_value_as_a_number(raw_value)
         end

つっつきボイス:
「ところで、こういう『過去に修正したエラーの再発』を何て呼んでます?」
「先祖返り」
「デグレ」
「リグレッションとかリグレスって、日本じゃ言わないかなー」

改良: ActiveRecord初期化の最適化を改善

ActiveModelの初期化は、実はRails 4.2からRails 5にアップデートしたときにかなり遅くなってしまっていたのだそうです。今回の改修では、STIで倍以上、非STIで1.3倍の高速化を達成しています。

================ Instantiate STI base class without attributes =================

 v5.1.1 patched:    20641.2 i/s
          v5.1.1:     9916.0 i/s - 2.08x  slower

================= Instantiate Non-STI class without attributes =================

 v5.1.1 patched:    27071.0 i/s
         v5.1.1:    20723.3 i/s - 1.31x  slower

つっつきボイス: 「STIってうまくはまるとすごくコードがコンパクトになるんですよ」「使いどころが思いつかないなー」「STI、気をつけないと危なっかしそうですね」

参考

Bundler 1.15がリリース、高速化を果たす(Ruby Weeklyより)


bundler.io/より

起動時の読み込みが高速化されたそうです。Ruby/Rails開発者が最も頻繁に使うgemだけに助かります。gem install bundlerでアップグレードできます。

また、以下の新しいコマンドを追加し、manページもがっつり改訂したそうです。

  • bundle info
  • bundle issue
  • bundle add
  • bundle pristine

Bundler 1.15については別記事でお伝えいたします。

inflector.me: Railsのinflection(活用形)を確認できるWebサイト


http://inflector.me/より

個人的にありがたいかも。まだ★1個だったので押しときました。

当初入力がサニタイズされていなかったらしく、<>などを含む文字列を入力すると無残に崩れることをakioさんが発見しましたが、私がissueを送ったらすぐ直してくれました。

なお、#ordinal#ordinalizeは序数(1stとか2ndなど)の接尾語のメソッドなので、レシーバーがIntegerのときのみ有効です。

Ruby 2.5で導入されるKernel#yield_selfRuby Weeklyより)

Object#tapと似ているが戻り値は異なるそうです。

# https://bogdanvlviv.github.io/posts/ruby/new-method-kernel-yield_self-since-ruby-2_5_0.html より
User = Struct.new(:name, :sex) do
  def male?
    sex == "male"
  end
end

user = User.new("Bogdan", "male")

user.yield_self { |u| u.male? ? "Mr. #{u.name}" : "Ms. #{u.name}" } 
# => "Mr. Bogdan"
user.yield_self { |u| "Hi, #{u.name.upcase!}" } 
# => "Hi, BOGDAN"
user.name 
# => "BOGDAN"

つっつきボイス:instance_evalと何が違うんだろう?」「名前が重要ってことなのかなぁ」


関係ありませんが、Rubyでは#nextの反対は#predなんですよね。理由は知りませんが、#prevじゃないのが以前からとても気になってます。

補足

Railsウォッチをまとめていて、ちょうどこんなissueを見つけました

#instance_evalあるから#yield_selfいらねーじゃん」
「いや、同じじゃないし↓」

42.instance_eval { abs2 } #=> 1764 (Kernel#yield_selfでは動かん)

42.yield_self #=> #<Enumerator: 42:yield_self> (BasicObject#instance_evalとかでは動かん)

RubyモジュールとBuilderパターン(Ruby Weeklyより)

かなり長いですが、モジュールとBuilderパターンに絞り込んでいるので読みやすいと思います。

チームが喜ぶ19のgem(RubyWeeklyより)

TechRachoで取り上げていないものはないかと思って探すと、こんなのがありました。

VCR

VCRは、テスト中のブラウザ画面の遷移を記録・再生するgemです。テストのたびに保存しておけば重要な証拠になりますね。非常に人気が高いらしく、JavaScriptを中心にいろんな言語に移植されています。gemspecを見た限りではseleniumを使っていませんね。

なお、英語圏では昔のカセット式のビデオデッキのことをVCR(video cassette recorderの略)と呼ぶのが普通です。

wicked_PDF

wicked_PDFは、コントローラに以下のように書くとビューテンプレートのHTMLをPDFに変換してくれます。

# https://github.com/mileszs/wicked_pdfより
class ThingsController < ApplicationController
  def show
    respond_to do |format|
      format.html
      format.pdf do
        render pdf: "file_name"   # Excluding ".pdf" extension.
      end
    end
  end
end

つっつきボイス:wicked_pdf、イイデスヨーイイデスヨー」

参考: Railsでwicked_pdfを使って画像入りのPDFを生成する

retryable

retryableは、応答の遅いのろまな外部レガシーAPIがテストの足を引っ張らないよう、応答なしで例外が発生したときにリトライしてくれます。RubyWeelkyの別エントリにあるsemianというgemもretryableと似た感じですが、こちらは本番運用向けでしょうか。


https://github.com/Shopify/semianより

つっつきボイス:
「リトライ処理って結構面倒なんですよね」
「そうそう、インターバルをだんだん伸ばしていって、ある程度のところで諦めるとか、そのへんをちゃんと作りはじめると、メインの処理より豪勢になってたりして」
「メインの処理なんてたった1行なのに、だんだん何がしたかったのかわかんなくなってくる」
「これからはこの gem 使わせてもらいましょう!」

AWS Tokyo Summitに参加していたmorimorihogeさんも、

「指数backoffタイマ的なものを今さら実装するのはめんどいすね(固定値ならいいけど引数で色々制御したりとか考えると車輪の再発明感ある)」

参考: 指数backoffタイマ

roadie

roadieはHTMLメールをRubyらしく書けるgemです。HTMLを少しでも書かずに済ませたい方に。

# https://github.com/Mange/roadieより
document = Roadie::Document.new "<html><body></body></html>"
document.add_css "body { color: green; }"
document.transform
    # => "<html><body style=\"color:green;\"></body></html>"

つっつきボイス: 「roadie、よさそう!」

groupdate

groupdateは、ActiveRecordモデルで年/月/週/日/時/分/秒などさまざまな単位のグループ化を支援します。MySQL/PostgreSQL/RedShiftでハッシュと配列の両方をサポートしています。ActiveSupportの手が届いてないさまざまな時間の区切りを使いたいときによさそうです。

# https://github.com/ankane/groupdate より
User.group_by_week(:created_at, time_zone: "Pacific Time (US & Canada)").count
# {
#   Sun, 06 Mar 2016 => 70,
#   Sun, 13 Mar 2016 => 54,
#   Sun, 20 Mar 2016 => 80
# }

Groupdate.week_start = :mon # 週頭は月曜

Groupdate.day_start = 2 # 一日の区切りは朝2時

つっつきボイス: 「groupdateを知ってたらもっと楽できた気がする」

apartment

apartmentは、Railsアプリを間貸しする機能を提供します。テナントごとにデータを隔離しつつ、共通の機能も与えられるそうです。リソース管理の一種という感じですが、間貸しに特化しているところがよさそうですね。テナントごとにRailsアプリのインスタンスを立ち上げたくない/立ち上げられない事情がある場合などに使えそうです。

つっつきボイス: 「apartment、小規模案件なら使えることがあるかも」「めぞん一刻思い出した」「あれって間仕切り破綻してますからw」

Red Arrow: Apache ArrowのRubyバインディングgem(RubyWeeklyより)

Apache Arrowはカラム指向のインメモリデータ処理システムです。

公式サイトで目についた箇条書きだけひとまずメモします。

  • 全システムが同じメモりフォーマットを利用する
  • システム間通信のオーバーヘッドがない
  • プロジェクト間で機能を共有できる(Parquet-to-Arrow readerなど)


https://arrow.apache.org/より

DiscourseのRailsはRuby 2.4.0でどれだけ速くなったか(RubyWeeklyより)

DiscourseはRailsで書かれたSNSアプリです。Besides GC, Has Ruby 2.3 Helped Rails Performance?も同じ著者の関連記事です。

Railsの認証システムをセキュアにする4つの方法

TechRachoの翻訳記事「そのパッチをRailsに当てるべきかを考える」や「Ruby on Rails のhas_many 関連付けのフィルタテクニック4種」のducktypelabs.comさんの新着記事です。

認証関連のセキュリティに関心のある方向け。

Rodauth: 認証システムのニューフェイス

Railsで認証といえばすっかりDeviseですが、上のductypelabsの記事ではDevise以外にRodauthについての言及が多かったので、気になって少しだけ追ってみました。

Rack対応アプリならRailsに限らず広く使えるようです。Why Rodauth?には「DeviseやAuthlogicやSorceryと違ってRailsに限定されない」とあります。

Rodauthのドキュメントの中心はREADME_rdoc.htmlで、それ以外はAPIドキュメントレベルのようです。OmniAuth連携はまだやってないようで、むしろOmniAuthのライバル扱いされてたりします。

Deviseのように手順を集めたWikiはまだ見当たりませんでしたが、GoogleグループのフォーラムやIRCがあり、筋もよさそうなのでREADMEとAPIでやれるかもしれません。もちろん使ってみないことにはわかりませんが。

まだ★300個台ですが、後発らしく気合が入っています。GitHubのIssueも全部つぶされています。


http://rodauth.jeremyevans.net/より

豊富な実績と引き換えに煮込みすぎたカレーのようになってしまったDeviseを果たして追い上げられるかどうか。気になる方は以下のスライドをどうぞ。

Rubygems.orgがElasticsearchを採用して高速化(RubyWeeklyより)

どっかで見たなと思ったら、昨年のRailsウォッチでもrubygems.orgがCDNで倍速になった↓ことを報じたときと構図がまんま同じでした。間違い探しみたいですね。

Railsのアップグレード代行します(RubyWeeklyより)

宣伝なのですが思わず目を留めてしまいました。Railsのアップグレードに特化した請負サービスですね。「寝ている間にやっときます」だそうです。


https://www.upgraderails.com/より

別に張り合うわけではありませんが、もちろんBPSでもRailsアップグレードのご相談をお受けしておりますので、お気軽にお問い合わせフォームにてお尋ねください。

Webpacker 3題

Rails 5.1のWebpackerに関連する記事です。

Webpackerが2.0にアップグレード(RubyWeeklyより)

Elmサポート追加とバグ修正です。ElmはいわゆるAltJSのひとつで、コンパイルするとHTML/CSS/JSまで生成するうえ、関数型言語なんだそうです。

参考: Elmというミニマムでフレームワークにもなる関数型altJS言語を触ってみよう!!!

WebpackerからWebpacker-liteが分離した理由(RubyFlowより)

React on Railsというgemのメンテナが、RailsとWebpackerのポリシーと合わなかったらしく、forkしたそうです。

React on RailsはWebpackerのほんの一部の機能しか使わないのに、Railsで公式採用されたWebpackerはAsset Pipelineなど多くの機能を統合しているのでWebpackerに手を入れるのにRailsコミッターとやりとりしなければならず、つらかったようです。

ReactをRailsで使う(RubyFlowより)

React on Railsの導入手順記事を参考までに。

PostgreSQLの優れた資料「篠田の虎の巻」

PostgreSQL 10の新機能を追っていて見つけました。日本ヒューレット・パッカードの日本語技術ブログですが、ここからダウンロードできる「篠田の虎の巻」は日本語版と英語版があります。

新機能や検証結果がよくまとまっていて、とても参考になります。

今年2月更新のPostgreSQL 9.6向けの「篠田の虎の巻」が現行の9.x系では最新の資料のようです。こちらも大力作です。

RailsでPostgreSQLのJSONカラムを使う(RubyWeeklyより)

つっつきボイス: 「MySQLでもJSONカラムできますよ、一応」「知らなかった!」

Rubyに恋してしまう理由

Quoraの記事ですが、身も蓋もなくて思わず吹き出してしまいました。Why do people fall in love with Python?なんてのもあります。

Whyで始まる質問は、よほど具体的な問いでないと無意味なものになりやすい傾向がある気がします。どんなふうに回答しようと、「ではそれはなぜ?」といくらでも無限後退できてしまうので。無限後退を止めるには神を持ち出すぐらいしか思いつきません。

さらに、好き嫌いは理屈では決定されないことが脳科学周りでだんだん明らかになってきています。好き嫌いは出会いの瞬間に脳の原始的な層で決まり、その後は大脳皮質が全力でその好き嫌いを正当化するんだそうです。

動きの遅い生物が動きの速い餌を捕まえる動画

赤玉が足の速いエサ、青玉が足の遅い捕食者です。閲覧にはFlashプレイヤーが必要です。

番外: エントロピック重力理論の解説


https://arstechnica.comより

昨年末のRailsウォッチで報じた「エントロピック重力理論」の当事者へのインタビューを含む解説記事です。ちびちび読んでますが、宇宙全体を熱力学的に捉えて一般相対論の重力方程式に変換するみたいな部分に勝手に興奮しています。

熱力学はこれ以上ないくらい地味で目立たなくて婦女子にモテない学問と思われているっぽいですが、アインシュタインはニュートン力学やマクスウェル電磁気学より熱力学を信頼していたそうです。


今週は以上です。

関連記事(2017年分)

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

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

Rails公式ニュース

Ruby Weekly

OpenRuby

RubyFlow

160928_1638_XvIP4h

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

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833

コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。
これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。
かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。
実は最近Go言語が好き。
仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

BPSアドベントカレンダー

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ