週刊Railsウォッチ(20170630)Rails 5.1.2/4.2.9リリース、高機能なRailsキャッシュcounter_culture、Vue.jsの公式SSRガイドほか

こんにちは、hachi8833です。最近RubyWeeklyより先にウォッチで紹介している記事がちょくちょくあることに気づきました。

6月最後のRailsウォッチ、いってみましょう。

Rails 5.1.2と4.2.9が正式リリース(Rails公式ニュースより)

5.1.2の修正は、これまでにもRailsウォッチで取り上げてきたものが多いので何だか親しみが持てます。ActionMailer、ActiveJob、ActionCable以外で修正が行われています。

4.2.9は重大なセキュリティ関連の修正のみとなっています。Changelogに追記されているのはActiveSupportActiveRecordActionPackのみです。

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

パフォーマンス改善: fixtureの挿入にバルクINSERTを使用

# https://github.com/rails/rails/pull/29504/files#diff-694eb08d69d73b367d06242dd0aba454R354
+        table = Arel::Table.new(table_name)
+        manager = Arel::InsertManager.new
+        manager.into(table)
+        columns.each_key { |column| manager.columns << table[column] }
+        manager.values = manager.create_values_list(values)
+        execute manager.to_sql, "Fixtures Insert"

つっつきボイス:
「このArel::InsertManagerを使ってbulk insertできるのか」「こんなのあったとは」
「自分だったらこういう場合activerecord-import使うかなー、バリデーションもできるし: ただRailsのcoreにこれを入れたくないのはわかる」

そこからデータベースへのバルクインポートの話題になりました。

つっつきボイス:
「速度出したいときは生SQL書くことになる」「SQL力を試されますね」
「1日1000万レコードぐらいのデータをTSV(タブ区切りテキスト)作ってCOPY FROMでインポートしたり」
「やった中ではMySQLのLOAD DATA INFILEが速かった」

修正: #current_page?ヘルパーがRailsエンジンのルートパスを正しく処理しないことがあった

パスの末尾の/の有無で比較に失敗することがあったのが修正されました。

# https://github.com/rails/rails/pull/29503/files#diff-26e33d6e883deb07332ac9c1922eadc0L555
-        url_string.chomp!("/") if url_string.start_with?("/") && url_string != "/"
+        if url_string.start_with?("/") && url_string != "/"
+          url_string.chomp!("/")
+          request_uri.chomp!("/")
+        end

リレーションのmergeINNER JOINを維持するよう修正

修正前のAuthor.joins(:posts).merge(Post.joins(:comments))の結果

  • 期待: SELECT ... INNER JOIN posts ON... INNER JOIN comments ON....
  • 実際: SELECT ... INNER JOIN posts ON... LEFT OUTER JOIN comments ON...

morimorihogeさんが「これ挙動が変わる可能性あるからArel使いは注意した方がいいかも」と指摘しました。

# https://github.com/rails/rails/pull/27063/files#diff-06059df8d3dee3101718fb2c01151ad0L107
-      def join_constraints(outer_joins, join_type)
+      def join_constraints(joins_to_add, join_type)
         joins = join_root.children.flat_map { |child|
           make_join_constraints(join_root, child, join_type)
         }

-        joins.concat outer_joins.flat_map { |oj|
+        joins.concat joins_to_add.flat_map { |oj|
           if join_root.match? oj.join_root
             walk join_root, oj.join_root
           else
             oj.join_root.children.flat_map { |child|
-              make_outer_joins oj.join_root, child
+              make_join_constraints(oj.join_root, child, join_type)
             }
           end
         }

pixeltrix先生も「ぼくmerge使ったことないけどね: 自分ならクエリビルダーメソッド使う」「誰かにとってはバグでも別の人には機能だったりすることだってあるから注意したい」

元の挙動が仕様かどうか誰もわからなかったので、テストが頼りということのようです。

つっつきボイス:JOINかー」「JOINを使うメソッドをどこまで信用できるかという気持ちはある」「Arelで複雑なクエリ書きたくないですね」

最近のRuby trunkから

いずれも卜部さんが立てた無言のissueです。

/000000000000000000000000000000000000000000000000000000000000000000000
begin raise ensure return end; self
/#{break}/o

つっつきボイス: つっつきボイス: 「#13687、これどういう構文だろ」「正規表現の端?」「割り算?」

$ ruby -ve '/000000000000000000000000000000000000000000000000000000000000000000000'
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]
-e:1: unterminated regexp meets end of file
-e:1: warning: possibly useless use of a literal in void context

「正規表現か!」「でも落ちないな」「開発版での現象だって」「よく見たら2.5devって書いてあった」

オンライン書籍: Demystifying Rails(Ruby Weeklyより)


launchschool.comより

無料で全ページ読めます。demystifyはmystifyの反対語で「神秘のベールを剥がす」のような感じです。

つっつきボイス: 「ほむほむ、No Magic Railsとか割りといいかも」「Railsの背後の挙動がわからなくて怖いとか、背後の挙動がわかるまで使いたくない!みたいな人とかにいいのかな: PHPやってた頃は自分もその傾向がちょっとあった気がする」「少なくともRailsガイドを見て書いたレベルではなさそうですね」

そこから、数年前BPSの勉強会で取り上げた「Crafting Rails 4 Applications」という書籍の話題になりました。

つっつきボイス: 「あの本はものすごい深掘りしているところはいいんだけど、網羅性が足りない点が残念」 「そういう意味ではDemystifying Railsは役に立つかも」

SQLとビジネスロジック

SQL、ORM、アプリケーションコード、ビジネスロジックの関係について論じています。

ブログ主のDimitri Fontaine氏はオープンソース、特にPostgreSQL界隈では著名なエンジニアで、PostgreSQLの機能と便利技トップ10Craig Kerstiensも一目置いているようです。

つっつきボイス: 「SQLって本来ビジネスロジックやトランザクションなどをすべて記述できる能力があるから、ORMやアプリケーションコードとどう共存するかというのは一度は考える話だなー」「ストアドプロシージャは使いたくない」「特に名を秘すけど、ORMなど絶対認めん!みたいな過激な主張をたまに見かけますね」「それネットのどこにありますか?」「それはね…」

メタプログラミングの隠れたコスト(RubyFlowより)

「速度」「読みやすさ」「検索性」の3つを挙げています。Rubyのstatic analysisについても言及しています。

以下のコードはcreate_post_tags以外のドキュメントが生成されません。

# http://www.blackbytes.info/2017/06/costs-of-metaprogramming/ より
class RubyBlog
  def create_post_tags
    types = ['computer_science', 'tools', 'advanced_ruby']

    types.each do |type|
      define_singleton_method(type + "_tag") { puts "This post is about #{type}" }
    end
  end
end

rb = RubyBlog.new

rb.create_post_tags
rb.computer_science_tag

以下のようにしてyardドキュメントを生成する手もありますがいつも使えるとは限らず、結局grep頼みになってしまったりします。

class Thing
  # @method build_report
  define_method(:build_report)
end

つっつきボイス: 「メタプロに速度を求めちゃいけないw」「検索性の低さは確かにある: IDEでインデックス化できないし」

複雑な正規表現をシンプルなパーサーで置き換える(RubyFlowより)


blog.honeybadger.ioより

こんな感じに変換してくれるパーサーを書いてみたそうです。

/
  (                          # Capture group is so split will include matching and non-matching strings
    (?:                      # The first character of the key, which is
      (?!\s)[^:\s"'\[]{1}    # ..any valid "key" char not preceeded by whitespace
      |^[^:\s"'\[]{0,1}      # ..or any valid "key" char at beginning of line
    )
    [^:\s"'\[]*              # The rest of the "key" chars
    :                        # a colon
    (?:                      # The "value" chars, which are
      '[^']+'                # ..anything surrounded by single quotes
      | "[^"]+"              # ..or anything surrounded by double quotes
      | \[\S+\sTO\s\S+\]     # ..or anything like [x TO y]
      | [^\s"'\[]+           # ..or any string not containing whitespace or special chars
    )
  )
/xi 

つっつきボイス: 「Parser書きたくなる気持わかる: 神正規表現使われるとレビュー意欲そがれるw」「キャプチャグループとか名前付きグループみたいなのって最近知った」「コメントのない神正規表現はマジ勘弁」「正規表現書くのは好きだけど確かに人のは読みたくないw」

「何でしたっけ、(?=)とか(?!)みたいなのっていつも覚えられなくてこんなスニペット作りました↓」

"foobar".match(/foo(?=bar)/)    # => #<MatchData "foo">  # 直後に bar がある foo
"fooxxx".match(/foo(?!bar)/)    # => #<MatchData "foo">  # 直後に bar がない foo
"foobar".match(/(?<=foo)bar/)   # => #<MatchData "bar">  # 直前に foo がある bar
"xxxbar".match(/(?<!foo)bar/)   # => #<MatchData "bar">  # 直前に foo がない bar

「私もオレオレアプリの管理画面にlook aheadとlook behindのカンペ付けてます↓」

⭐Vue.js公式のサーバーサイドレンダリング(SSR)ガイド⭐

当初Build your first server-side rendered React app with Railsにしようかと思ったのですが、最近公開されたらしいVue.jsの公式SSRガイドを見つけたのでこっちにしちゃいました。

これ、すごくありがたいと思います。

hydrationはVue.jsの用語のようです。化学用語だと「水和物」ですね。
今週の⭐を進呈いたします。おめでとうございます。

ActionMailerとSidekiqでメールを非同期送信

Making a Rails App Move Faster: A Tale of Lessons Learnedで紹介されていました。

手順が具体的なのですぐ使えそうです。

つっつきボイス:mail.deliver_laterだなやっぱり↓」

user = User.find(1)

mail = UsersMailer.welcome_email(user.id)
#mail.deliver_now
mail.deliver_later

Anyway Config: さまざまなソースから設定を読み込めるgem(Ruby Weeklyより)

今のところ★50個超えです。

つっつきボイス: 「なまじいろんな書き方ができると、コード全体でconfig parameterへのアクセス方法がバラバラになって後でつらくなりそう」「設定をいろんなところから読み込めると便利なのはわかるけど」

ChromeでヘッドレスなCapybara feature specを動かす(Ruby Weeklyより)


robots.thoughtbot.comより

capybara-webkitChromeDriverでヘッドレスにテストする解説記事です。

このサイトでは他にORMを使ってないRailsでFactoryGirlを使うコツなども面白そうです。Rails以外にiOSやAndroid記事もたくさんあるようです。

counter_culture: Railsアプリのカウンタキャッシュ(Awesome Rubyより)

ActiveRecordでさまざまなカウンタキャッシュオプションが使えるようになるgemです。

# magnusvk/counter_culture より抜粋
counter_culture :category, touch: true

counter_culture :category, column_name: 'product_weight_ounces', delta_column: 'weight_ounces'

counter_culture :category, foreign_key_values:
      proc {|category_id| [category_id, Category.find_by_id(category_id).try(:parent_category).try(:id)] }

つっつきボイス: 「お、これいいかも!」「Rails標準のcounter_cacheって機能が超シンプルなんで、ちょっと凝ったことしようとするとすぐ物足りなくなる」「使ってみよう」「READMEにコード例もちゃんと書いてあるのはうれしい」

Rubyのこの辺もうちょい何とかなあれ11選(Awesome Rubyより)

タイトルだけ見て使いこなし系記事かと思いきや、毛色が少し違う感じです。走り書きっぽくてちょっと読みづらい…

  • p Integer("0123")で8進数出力するとか勘弁。今どきパーミッションぐらいでしか使わないような8進数はp 0o123使え。
  • Hashにもっとメソッド欲しい。
  • Hash#zipがイマイチ。
  • Enumerable#count_byが欲しい。
  • URInet/httpが古い
  • pryを標準ライブラリに加えて欲しい。
  • Pathname#globも使いにくい。
  • system "wget", "-w", wait_time.to_s, uri.to_sみたいにパラメータを#to_sしないといけないの勘弁。
  • シリアライズはいっそ素性のいいRuby Object Notation(RON)にしようよみんな: yamlとかJSONとかじゃなくて: JSON5も完全じゃないし。
irb(main):006:0> a = {x: 1, y: 2}
=> {:x=>1, :y=>2}
irb(main):007:0> b = {y: 3, z: 4}
=> {:y=>3, :z=>4}
irb(main):008:0> a.zip(b)
=> [[[:x, 1], [:y, 3]], [[:y, 2], [:z, 4]]]
irb(main):009:0> (a.keys|b.keys).map{|k| [k, [a[k], b[k]]]}.to_h
=> {:x=>[1, nil], :y=>[2, 3], :z=>[nil, 4]}

同じサイトの別記事「The Next Ruby」はもっと言いたい放題で「endやめてPythonみたくインデント表記になあれ」「モジュールのネスト、滅せよ」という感じです。
私もこういうこと考えがちなのでいい年して頬を赤らめてしまいました。

つっつきボイス:p Integer("0123")はちょっと気をつけたいかなと思ったけどRubyistなら#to_iじゃね?」「Hash#compactActiveSupportにあった気がする」「Rubyにもあるな?」「system "wget", "-w", wait_time.to_s, uri.to_sは確かに事故りそう」「ないはずなのにcount_byってありそうな気がしてくるのが不思議↓」

User.all.count_by(&:name) rescue $! 
# => #<NoMethodError: undefined method `count_by' for #<User::ActiveRecord_Relation:0x007f99d63135e0>

そこからyaml/JSON話に広がりました。

つっつきボイス: 「yaml嫌い!」「RONはともかくとしても」「JSONのケツカンマとかコメントできないとか本当残念」「JSON5はもっと普及してもよさそうなものなのに」「JSONといえばPostgreSQL(キリッ」「MySQLもJSONがんばってるし」

Ruby on Rails Security Project


rorsecurity.infoより

Ruby on Rails Security Projectの最新のニュースレター #25が配信されたので、ざざっとリストアップします。

つっつきボイス: 「RoRのセキュリティ記事、新人の勉強会向け資料によさそう」「こういうのを1つ選んでスライドにして発表するとか」「発表ネタを探してる新人君はこのあたりからどうぞ」

オピニオン: RailsのCurrentAttributesは有害

mail gemにヘッダーインジェクションの脆弱性

新しいApacheでは認証バイパスやDoS脆弱性を修正

日本語でも情報が出ています: JVNVU#98416507 Apache HTTP Web Server における複数の脆弱性に対するアップデート

ハッカーよ、汝自身をハックせよ

つっつきボイス: 「thyはyourの古英語表現、シェークスピアぐらいの頃ですね」「汝の、みたいなニュアンス」「厨二病感出まくってそうw」「ファンタジー小説とかには欠かせない感じですね」

thouやthyは神様や皇帝の上から目線なセリフとかで使われる印象です。

フリーのAWSアカウントセキュリティ監査ツール


summitroute.comより

つっつきボイス: 「お、これ後で読も!」

認証方法ごとのセキュリティや使い勝手を比較


  • 昔ながらのusername/password
  • パスフレーズ
  • 2要素認証
  • SNSサインイン
  • パスワードレス
  • バイオメトリック認証
  • ドングル認証

Webトラフィック傍受の広がりを理解する

GPG署名でGitHub commitのセキュリティを高める

RabbitMQの管理UIにXSS脆弱性

git-cop: git commitメッセージのスタイル違反をチェック

configuration.ymlでスタイルを設定できるようです。

Running Git Cop...

d0f9bf40a09d10618bcf8a38a5ddd3bcf12fd550 (Brooke Kuhlmann, 3 seconds ago): This is a bogus commit message that is also terribly long and will word wrap
  Commit Subject Length: Invalid length. Use 72 characters or less.
  Commit Subject Prefix: Invalid prefix. Use: "Fixed", "Added", "Updated", "Removed", "Refactored".
  Commit Subject Suffix: Invalid suffix. Use: ".".

3 issues detected.

つっつきボイス: 「プロジェクトで使うにはちょっと固すぎるかも」「オープンソースの方が向いているかも?」「Changelogを自動生成できるのがうらやましい」「そのためには相当気をつけてメッセージ書かないとなー」

そこからcommitメッセージの話題になりました。

つっつきボイス: 「いつのことだったか、commitメッセージにことごとく「◯◯修正」しか書いてないのを見たことあります」「commitメッセージにcommitした時間をがんばって手書きで入力しているのとかも」「…」「…」

vue-table: Vue.jsベースでテーブルを扱えるコンポーネント

Vue.jsベースでテーブルを作れます。★4,000超えの快挙です。
Bootstrapと併用したサンプルもWikiに掲載されています。


github.com/ratiw/vue-tableより

つっつきボイス: 「これもいい!」「管理画面でこれを使うくらいの所からVue.jsをはじめてみたい」
「Vue.jsとBootstrapといえばVueStrapもすごくいいですよ↓」


yuche.github.io/vue-strapより

Vue.jsで書かれたBootstrapコンポーネントで、jQueryやBootstrap.jsを一掃できるそうです。
Railsに取り込まれそうな予感がちょっとしてきました。

Magic Wormhole: 他のPCから任意のサイズのファイル/ディレクトリを取得(HackerNewsより)

PyCon 2016で発表されたようです。詳しくはスライド(PDF)や動画↓をどうぞ。

# 送信側
% wormhole send README.md
Sending 7924 byte file named 'README.md'
On the other computer, please run: wormhole receive
Wormhole code is: 7-crossover-clockwork

Sending (<-10.0.1.43:58988)..
100%|=========================| 7.92K/7.92K [00:00<00:00, 6.02MB/s]
File sent.. waiting for confirmation
Confirmation received. Transfer complete.
# 受信側
% wormhole receive
Enter receive wormhole code: 7-crossover-clockwork
Receiving file (7924 bytes) into: README.md
ok? (y/n): y
Receiving (->tcp:10.0.1.43:58986)..
100%|===========================| 7.92K/7.92K [00:00<00:00, 120KB/s]
Received file written to README.md

つっつきボイス: 「ざざっと見た感じ、相手のIPとかわからなくてもこの7-crossover-clockworkみたいなコードを送るだけでファイル送受信できるってことか」「リンクを知っている人だけ見られるGoogleドキュメントのURL、みたいな感覚?」「さすがに受信側でもMagic Wormholeは起動しないといけないか」

CLIでささっとファイル交換したい人向けのようです。

Open Source Friday: 金曜日はオープンソースに貢献しよう(GitHub Trendingより)

最初何のソフトウェアだろうと思ってリポジトリを追ってしまいましたが、これは一種のキャンペーンで、リポジトリは単なる公式サイトのアプリみたいです。


opensourcefriday.comより

「オープンソースソフトウェアはみんなでつくるものです」「金曜日には、普段愛用しているオープンソフトウェアに数時間でも貢献しましょう」

Peatio: Rails製の仮想通貨交換プラットフォーム(GitHub Trendingより)


github.com/peatio/peatioより

↑これがPeatio(貔貅)だそうです。日本語読みは「ひきゅう」。やはりというか中国発です。

Dexter: PostgreSQLのインデックスを自動作成(GitHub Trendingより)

つっつきボイス: 「インデックス化のヒントくれるならいいけど、自動作成まではちょっとな~」「そこまで全自動ではないみたいですヨ」「SQLログから解析するのか」「PerconaのPostgreSQL版みたいな感じなのかな」


記事をまとめているときに気づきましたが、DexterではHypoPGというhypothetical indexをPostgreSQLにインストールするよう指示しています。このhypothetical indexという用語はまだ日本語になっていないようですが、Microsoft SQL Serverには搭載されているようです。


dalibo.github.io/hypopgより

ついでに、Hypothetical Index Strategy Calculatorというサイトも見つけました。


presents.voya.comより

AirBnB製のJavaScriptスタイルガイド


github.com/airbnb/より

★54,000台という凄まじさです。スタイルの多くに理由が書かれているのがいいですね。こういうの大事だと思います。


github.com/airbnb/javascriptより

例:

3.2 参照を再代入する場合はletを使うこと(varやeslintのno-varやjscsのdisallowVarは使わない)
理由: letがブロックスコープだから(varのような関数スコープではない)

つっつきボイス: 「この★の数からいって、これがJavaScript界のスタンダードなのかな」

番外: Quick, Draw!の大量の画像データ

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

昨年11月のRailsウォッチでご紹介したQuick, Draw!の/dataディレクトリを開くと、これまでに登録されたおびただしい手書き画像データがずらりと並んでいます。50 millionだそうです。


Quick, Drawより(Quick, DrawはGoogleのサービスです)

書き順までしっかりデータ化されています。


今週は以上です。

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

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

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

Rails公式ニュース

Ruby Weekly

Awesome 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探訪シリーズ