週刊Railsウォッチ(20170804)Rails 5.1.3と5.0.5が正式リリース、GitHubでローカライズ基盤サービス、正規表現で迷路を解くほか

こんにちは、hachi8833です。4年使ったMacbook Proのバッテリーがそろそろ天に召されそうです。

8月最初のウォッチ、行ってみましょう。

お知らせ: 来週は週刊Railsウォッチをお休みいたします。次回は8/18(金曜日)の予定です。

Rails 5.0.5と5.1.3が立て続けに正式リリース(Rails公式ニュースより)

月曜に先に5.0.5がリリースされ、今朝がた5.1.3もリリースされました。とりあえず5.1.3で記念写真↓。

Changelog

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

修正: クエリに巨大な数値がある場合に結果が正しくなかった問題を修正

PRキリ番ゲットはkamipoさんでした。

# activerecord/test/cases/finder_test.rb より
+  def test_exists_with_large_number
+    assert_equal true, Topic.where(id: [1, 9223372036854775808]).exists?
+    assert_equal true, Topic.where(id: 1..9223372036854775808).exists?
+    assert_equal true, Topic.where(id: 1).or(Topic.where(id: 9223372036854775808)).exists?
+    assert_equal true, Topic.where.not(id: 9223372036854775808).exists?
+  end

つっつきボイス: 「DBMSの限界値をこんなふうに超えるケースは扱ったことなかったけど、挙動は確かにバグ」「idをすごい勢いで消費するシステムとかだと踏むかも: そういうシステムではid生成そのものがボトルネックになるので自前でid発番することが多そう」
「TwitterのSnowFlakeを思い出したでござる」
「id生成がボトルネックというのは?」「id生成はアトミックだから必ずロックがかかるでしょ」

そこからサーバー間の同期の話題になりました。

「システムによっては、複数サーバー間でデータ生成や順序処理を一意にするなどの目的で、サーバーごとに原子時計持たせることがある」「おー、サーバー間の同期や通信のコストを下げられるのか」

おまけ

2014年に製造された世界初の原子腕時計は、60万円投資すると10個限定でもらえるそうですが、あっというまにはけたそうです。手作り感溢れてます。

リファクタリング: Arelでbindのparamsを扱えるよう修正

かなり大規模にリファクタリングしてます。

# activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
       def case_sensitive_comparison(table, attribute, column, value) # :nodoc:
-        table[attribute].eq(value)
+        table[attribute].eq(Arel::Nodes::BindParam.new(value))
       end

       def case_insensitive_comparison(table, attribute, column, value) # :nodoc:
         if can_perform_case_insensitive_comparison_for?(column)
-          table[attribute].lower.eq(table.lower(value))
+          table[attribute].lower.eq(table.lower(Arel::Nodes::BindParam.new(value)))
         else
-          table[attribute].eq(value)
+          table[attribute].eq(Arel::Nodes::BindParam.new(value))
         end
       end

つっつきボイス: 「変更量ハンパない」「テスト通ればOKとはいっても、コアにこれだけ手を入れるってスゴイナー」
「ASTってやっぱり抽象構文木(abstruct syntax tree)か」「parserとかprepared statementのSQL生成部分とかの設計し直しまでやってるのかな」「記事数多いので次いきましょう」

ActiveSupport::Durationの除算関連の変更

「除算の余り」と「除算」の2つのコミットをまとめました。moduloといえば数学用語の「剰余とか法」ですね。

# activesupport/CHANGELOG.md より
# 変更前
5.minutes % 2.minutes #=> 60
# 変更後
5.minutes % 2.minutes #=> 1 minute

テストコードを見ると、分母と分子の単位(単位なしを含む)に応じて余りの単位をよしなに設定してくれるようです。

# activesupport/test/core_ext/duration_test.rb より抜粋
+  def test_modulo
+    assert_equal 1.minute, 5.minutes % 120
+    assert_equal 1.minute, 5.minutes % 2.minutes
+    assert_equal 1.minute, 5.minutes % 120.seconds
+    assert_equal 5.minutes, 5.minutes % 1.hour
+    assert_equal 1.day, 36.days % 604800
+    assert_equal 1.day, 36.days % 7.days
+    assert_equal 800.seconds, 8000 % 1.hour
+    assert_equal 1.month, 13.months % 1.year
   end

# activesupport/test/core_ext/duration_test.rb より
+  def test_division
+    assert_equal 1.hour, 1.day / 24
+    assert_instance_of ActiveSupport::Duration, 1.day / 24
+
+    assert_equal 24, 86400 / 1.hour
+    assert_kind_of Integer, 86400 / 1.hour
+
+    assert_equal 24, 1.day / 1.hour
+    assert_kind_of Integer, 1.day / 1.hour
+  end

つっつきボイス: 「(1つ目のa54e13を見ながら)ええー、分で分を割ったら単位がキャンセルされると思ってたけど、余りって単位を付けていいものなの?」「数学科出身のkazzさん、いかがでしょうw」「数学だと単位ってそもそもほとんど俎上に載らないんですよ」「むしろ物理学の方が単位にうるさいかも」「でも物理だと余りを出さないですね」「代わりに精度重視: 除算は最後に回すとか」
「単位付きの余りは少しぎょっとするけどこれはこれで便利そうだし、原理上そんなにおかしいものでもなさそうですね」

Durationって、ActiveSupportに限らず考えないといけないことが多くて大変ー」

Ruby-trunkより

バグ: 継承されたメソッドでRefinementのスコープが無視される

module Test
  refine String do
    def sleep; end
  end
end

puts "start"
"".sleep 3
puts "end"

つっつきボイス: 「RailsだとRefinementってまず見かけないけどねw」「Refinementって志高いし実装もすごく大変だったらしいのに、まだそれほど使われてない気がしました」

activerecord-import: ActiveRecordでデータを一括読込するgem(Random Rubyより)


revs.runtime-revolution.comより

★2000に迫る勢いです。

# https://github.com/zdennis/activerecord-import/wiki/Examples#import-using-columns-and-arrays より
columns = [ :title, :author ]
values = [ ['Book1', 'FooManChu'], ['Book2', 'Bob Jones'] ]

# Importing without model validations
Book.import columns, values, :validate => false

# Import with model validations
Book.import columns, values, :validate => true

# when not specified :validate defaults to true
Book.import columns, values

つっつきボイス:以前のウォッチでも少し話したけど、activerecord-importは昔からある定番gemですね: 案件でも使ったことあるし、CSVインポート10000件とかは余裕」「要するにvalidationかけてからINSERT複文でINSERTを実行するヤツ」

「いい点はRailsのvalidationがかかるので割りと自然な使い方ができる」
「悪い点があるとすれば、Rubyコードである以上カリカリに速くはならないことか: 案件でも速度を出すために結局生SQL書いたこともあったし」

jb gemでRailsのJSONを高速にしたった(RubyFlowより)


medium.com/companydevより

gemは★500に迫る勢いです。関係ありませんが、最近medium.comの技術ブログを見かけることが妙に増えました。


つっつきボイス: 「jbって知らなかったけど、amatsudaさんのgemか」「新しいgemですね」
「うん、Rails標準のJBuilderよりこっちの方が自然に書けそう: JBuilderのインターフェースはあまり直感的でないところがあって、書き足していくうちにだんだん居心地が悪くなってきたり」
「jbでよくないのは名前ぐらいかなw」「こんなに短いとねー」

ちょうど対照的なコードサンプルがあったので貼ってみました。

# jbの場合(https://github.com/amatsuda/jb)
json = {
  content: format_content(@message.content),
  created_at: @message.created_at,
  updated_at: @message.updated_at,

  author: {
    name: @message.creator.name.familiar,
    email_address: @message.creator.email_address_with_name,
    url: url_for(@message.creator, format: :json)
  }
}

if current_user.admin?
  json[:visitors] = calculate_visitors(@message)
end

json
# JBuilderの場合(https://github.com/rails/jbuilder)
json.content format_content(@message.content)
json.(@message, :created_at, :updated_at)

json.author do
  json.name @message.creator.name.familiar
  json.email_address @message.creator.email_address_with_name
  json.url url_for(@message.creator, format: :json)
end

if current_user.admin?
  json.visitors calculate_visitors(@message)
end

大文字でJBといえば:

Errbit: AirBrake API準拠のエラーログ収集gem


github.com/errbit/errbitより

BPSでも標準的に使われています。


つっつきボイス: 「Errbitシラナカッター」「シラナカッター」「マジでw TechRachoにもErrbitの記事ありますよ↓」「その頃ワタイらBPSにおりませんでした」
「タイトルにもあるようにAirBrakeのAPIと互換性あって、AirBrakeのgemをそのまま使うし:
置き場所がAirBrakeじゃないだけ」
「Rails以外にも使えるし、↑上の図でもわかるようにエラーをとりあえずグループ分けしてくれるところとかありがたい: 細かくは他の方法で見たりもするけど」
「結果をSlackに流しておくとさらに便利ですヨ~」
「以前はAirBrakeが定番だったけど、有料化したとたんにみんなすごい勢いでalternative探してErrbitが浮上してきた」

参考

Trailblazer: Rails MVCのビジネスロジックを分離するgemスイート


trailblazer.toより

JSON HALを調べていてTrailblazerにたどり着きました。Trailblazerについては昨年のRailsウォッチでごく簡単に触れたことがあり、★も多いのですが、日本語での情報をほとんど見かけないので、今回少しだけ一同で眺めてみました。

# http://trailblazer.to/gems/operation/2.0/index.html より
class Song::Create < Trailblazer::Operation
  extend Contract::DSL

  contract do
    property :title
    validates :title, presence: true
  end

  step     Model( Song, :new )
  step     :assign_current_user!
  step     Contract::Build()
  step     Contract::Validate( )
  failure  :log_error!
  step     Contract::Persist(  )

  def log_error!(options)
    # ..
  end

  def assign_current_user!(options)
    options["model"].created_by =
      options["current_user"]
  end
end

つっつきボイス: 「へーなるほど、コントローラの制御ロジックをstepOperationに切り出したり↑」「Contractでステートを記述したり↓」「SalesForceみたいに、大きなビジネスロジックを扱うアプリを開発するための基盤という感じ」「日本のSIer的な開発スタイルに向いているのかも」「昨今はどっちかというとマイクロサービスアーキテクチャ指向なんで、今後流行るのかなあ、どうなんだろう」

# app/concepts/song/contract/create.rb
module Song::Contract
  class Create < Reform::Form
    property :title
    property :length

    validates :title,  length: 2..33
    validates :length, numericality: true
  end
end

参考: Railsにおけるサービス層の導入と感触

trailblazer n. 先駆者, 草分け.

オピニオン: gemを追加する前にもうちょっと考えよう

短いながらも良記事です。


つっつきボイス: 「『車輪の再発明を避けようとしてgemだらけになる』ことのデメリットについて触れてるのがいい」「あまりにトリビアな機能を追加するgemとか『それ、書いた方が早くね?』って思うこと多いし」「たとえばどんなgemでしょうか?」「cts-as-taggable-onとかw」

compartmentalization: {名} : 区画化、区分化、区分け、棲み分け

米国Kite社がオープンソースツールに広告を仕込んで非難轟々


theoutline.comより

先の「We need better compartmentalization」の記事中のリンクで知りました。

仕込まれたとされるのはATOMエディタのプラグインであるMinimapautocomplete-pythonだそうです。

CIとCD(Continuous Deployment)とCD(Continuous Delivery)の違い(RubyFlowより)

semaphoreci.comより


つっつきボイス: 「この図↑が( ・∀・)イイ!!」「Continuous DeliveryとContinuous Deploymentの違いがひと目でわかりますね」
「CDとCDって、略語が完全一致しているのが向こうの人にとっても残念だろうな」「まあよくあることだし」

OWASPチートシートでRailsのセキュリティ問題を防止(Random Rubyより)

記事は普通な感じですが、OWASPの方が話題になりました。


つっつきボイス:OWASPは強制力こそ持たないけど、セキュリティ関係のガイドラインとかチェックシート的などを提案・啓蒙している団体ですね」「大手企業が実施するセキュリティチェックの品質監査ガイドラインなんかでもOWASPを参照していることがあったりするので、覚えておくとよいです」
「少なくともIPAよりは信頼されてるw」


https://www.owasp.orgより

Elixirを学んだらRubyが上達したお(Ruby Weeklyより)

Elixirの特徴に触れることでRubyのコーディングに好影響があったという割りと短い記事です。

# https://www.amberbit.com/blog/2017/7/27/how-learning-elixir-made-me-better-ruby-developer/ より
class Counter
  attr_reader :value

  def initialize(payload)
    @value = payload.to_i
  end

  def increment
    Counter.new(@value + 1)
  end
end

SOLIDの「D」: 依存関係逆転法則(Ruby Weeklyより)

SOLIDの連載シリーズです。他の記事も読み応えありそうです。


つっつきボイス: 「この図も、独特だけど見せ方が面白い」「六角形ぇェ」「SOLIDってDDD(ドメイン駆動開発)関連の記事で見たことがあったような」

RubyをJavaScriptっぽくする(Ruby Weeklyより)


kevinkuchta.comより

これでもRubyです:

  var first = 3;
  var second = 4;

  var sum = function(a, b) {
    a + b;
  }

  console.log("Sum = ", sum(first, second));

つっつきボイス: 「(´д`)イヤァ-ン!!ww」「これはひどずw」「しかも古いJavaScriptでw」

Railsで時間を変えてテストする方法(RubyFlowより)


つっつきボイス: 「タイトルでtimecop使ってるの丸わかりw」「テストで時間を変えるのってタイムトラベルって呼ぶんですね」「タイムトラベルらしく、timecopは時間を移動する他に元の時間に戻ったりもしますよ」

Passenger 5.1.7リリース(RubyFlowより)

前回のメジャーアップデートでのChangelogが多すぎて追いきれませんでした。

Passenger Libraryというサポートサイトがやたら充実しています。

Cooper Pressの技術情報ニュースレター


cooperpress.comより

英語圏の技術情報サイトが過剰気味な中、Cooper Pressのニュースレターは編集が効いていて選別が割りとよい感じです。いくつかはWeb上で直接読めるものもあり、ニュースレターのみのものも最新版ならWeb上で読めます。RailsウォッチでもRuby Weeklyをよく参照しています。

みなドメインが違うので最初気づきませんでしたが、レイアウトが共通なので同じところで発行されていることがわかります。

Cocoon: jQueryで動的なフォームのネストをやりやすくするgem

Driftingruby.comのNested Forms with Cocoonで見つけました。★2400です。


つっつきボイス: 「管理画面みたいにUIの制約が少ない案件だとちょっと便利だったりするかな」「案件で添付ファイル機能とか要求されなければいけるかも」

オピニオン: あらゆる言語を学べ(Random Rubyより)

真ん中あたりで「早いうちにC言語をやっとけ」「アセンブラもやっとけ」と書いてあったのが目に止まりました。

  1. 自分にレッテルを貼るのをやめる(私はRails開発者です、など)
  2. メタなことをやる
  3. 他の言語の元となる言語(archetypal languages)をやる
  4. ひたすら書く


blog.bradfieldcs.comより


つっつきボイス: 「ひと目でbrainf*ckとわかる↑」「視覚的な知名度ハンパないw」「Array programmingってなんだろ?」「つ ↓」

Rubyで機械学習: k-meanクラスタリング(RubyFlowより)


www.practicalai.ioより

The Last API Wrapper: Web APIのラッパー作成用gem(RubyFlowより)

★はまだ100個に到達していません。


つっつきボイス:grapeというものが前からあるよん↓」


github.com/ruby-grape/grapeより

Southeast Ruby Conference: 米国ナッシュヴィルで10月に開催(RubyFlowより)

テネシー州ナッシュヴィルでの開催というのがちょっと珍しく感じたので取り上げてみました。

GitLocalize: GitHubベースのローカライズ基盤サービス

https://github.com/marketplace/gitlocalizeより

つい先ほど知りました。GitHub自ら始めたサービスかと思いきや、よく見るとmarketplaceなのでサードパーティでした。
まだ詳しくみていませんが、GitHubと統一的に使えるらしい点がインパクトありそうです。



docs.gitlocalize.com/about.htmlより

もしかしたらですが、ローカライズ業界に変化が訪れる予感がうっすらとしています。

Nginxのセキュリティ対策ベスト25

2010年と新しくはありませんが、そこそこまとまってるように見えたので。


つっつきボイス: 「早々に『SELinuxをオンにしろ』とか時代を感じる」「量は多いけど、ふつううううううううううううのことしか書いてないな、さすがにw」

そこから、Apacheの違いやSELinuxについて話題になりました。

「Apacheはhttpd.confでまとめて扱えるから楽といえばとても楽: その代わりそれがセキュリティ上の弱点にもなる」
「Nginxは一か所にまとまってないし、自力で設定する気になれないような設定ファイルもある」
「SELinuxは確かに固いけど、固すぎて不自由さがハンパない」

遅いと思っていたWEBRickが…

各所でバズっている記事です。

gosu: Ruby向け2Dゲーム開発ライブラリ(Awesome Rubyより)

CSS(Frontend Weeklyより)

CSS-Tricks: Shadow DOMで遊んでみたお

<iframe>タグの進化版ともいえるShadow DOMでTwitterのツイートを埋め込んでみつつ、Shadow DOMを解説しています。

CSSは90年代後半以来複雑になったか

npmjs.comでマルウェアが大量に発見される

これも各所で話題になっています。

Chrome 60 が正式リリース

7月末にChrome 60がアップデートされました。私も本記事を書きながらアップデートしたら思ったより時間がかかってしまい、ハマりました。

BPS社内では新機能のAudit Panelが話題になりました。

私はV8の正規表現の強化(Unicodeプロパティの扱いとか)が今後予定されている方に個人的に盛り上がってしまいました。

/\p{Number}/u.test('①');      // true
/\p{Alphabetic}/u.test('雪');  // true

正規表現で迷路解いたりしてみた

こういう遊び好きです。

Go言語ベースやってますが、この記事で使っているdlclark/regexp2というパッケージは実は.NET Frameworkの正規表現ライブラリをGoに移植したもので、Goの標準正規表現ライブラリよりずっと強力であり、実は私もこっそり愛用してたりします。

// https://github.com/dlclark/regexp2 より
if m, _ := re.FindStringMatch(`Something to match`); m != nil {
    // the whole match is always group 0
    fmt.Printf("Group 0: %v\n", m.String())

    // you can get all the groups too
    gps := m.Groups()

    // a group can be captured multiple times, so each cap is separately addressable
    fmt.Printf("Group 1, first capture", gps[1].Captures[0].String())
    fmt.Printf("Group 1, second capture", gps[1].Captures[1].String())
}

番外

JSONで取れるデータあらいざらい(GitHub Trendingより)

最初opendatajson/football.jsonにしようかと思いましたが、こっちの方が断然すごかったので。

音楽、ゲーム、映画、アニメ、金融、詐欺チェック、チャック・ノリスねた、Tumblr、飛行履歴、天気など、よくぞこれだけ集めたと思います。

TypeScriptの型システムはチューリング完全

// 止まらない再帰
type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
let f: Foo<"true", {}> = null!;

GitHub Issueでこれだけボタンが押されているのを自分は初めて見ました。

SNSはボキャブラリーの発達に好影響?ロシアの研究

最初に見たのは日本語記事「SNSばかりやっているとバカになる? ロシアの研究で意外な発見」でしたが、途中から有料のうえ、元記事の英語なら全文読めました。

香港のAIチャットが党を批判してサービス停止

各所で話題になっていますが、ソースは今のところこれ以外に見当たりません。QQ wheatgrass was banned, we talk about the chat robot “crime” Historyは、それを受けた評論記事です。


今週は以上です。

バックナンバー(2017年度)

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

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

Ruby 公式ニュース

Rails公式ニュース

Ruby Weekly

Awesome Ruby

Random Ruby

Ruby on Rails Security Project

RubyFlow

160928_1638_XvIP4h

Hacker News

160928_1654_q6srdR

Github Trending

160928_1701_Q9dJIU

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の書いた記事

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ