週刊Railsウォッチ(20180119)derailed_benchmarks gem、PostgreSQLをGraphQL API化するPostGraphile、機械学習でモック画像をHTML化ほか

こんにちは、hachi8833です。Nintendo Laboにいろいろ持ってかれそうで気になってます。


つっつきボイス: 「任天堂のものづくりセンス、パないなー」

それでは今週のウォッチ、いってみましょう。

Rails: 今週の改修

今回はCommit差分から見繕いました。

left_outer_joinsをunscopeできるようになった

# activerecord/lib/active_record/relation/query_methods.rb#351
     VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock,
                                      :limit, :offset, :joins, :includes, :from,
-                                     :readonly, :having])
+                                     :readonly, :having, :left_outer_joins])

つっつきボイス: 「scopeでleft_outer_joinsできるならunscopeもできないと、ってことかな」

重要度の低いダイジェストにデフォルトでSHA-1を使用するようになった

# railties/lib/rails/application/configuration.rb#103
           if respond_to?(:active_support)
             active_support.use_authenticated_message_encryption = true
+            active_support.use_sha1_digests = true
           end

ETagヘッダーなどの重要でないダイジェストにはMD5ではなくSHA-1を使う。
Rails.application.config.active_support.use_sha1_digests = true
new_framework_defaults_5_2.rb.ttより大意

pg-1.0 gemに対応

pgが0.21から1.0にメジャーバージョンアップしたそうです。

# Gemfile.lock#343
-    pg (0.19.0)
-    pg (0.19.0-x64-mingw32)
-    pg (0.19.0-x86-mingw32)
+    pg (1.0.0)
+    pg (1.0.0-x64-mingw32)
+    pg (1.0.0-x86-mingw32)

つっつきボイス: 「へー、pgはもう永遠に1.0にならないんじゃないかと思ってた」「queue_classicってメンテナ代わったのかな?↓」

# Gemfile#65
-  gem "queue_classic", github: "QueueClassic/queue_classic", branch: "master", require: false, platforms: :ruby
+  gem "queue_classic", github: "Kjarrigan/queue_classic", branch: "update-pg", require: false, platforms: :ruby

savesave!の後でオブジェクトがunfreezeされていたのを修正

破棄したオブジェクトがsave後に変更される可能性があったので修正されました。

# activerecord/lib/active_record/persistence.rb#65
     def create_or_update(*args, &block)
       _raise_readonly_record_error if readonly?
+      return false if destroyed?
       result = new_record? ? _create_record(&block) : _update_record(*args, &block)
       result != false
     end

つっつきボイス: 「これ本当ならエラーをraiseしたいところだろうな: 互換性とかの問題でfalseを返してるのかも」

MySQL: create_databasecollationが指定されている場合にデフォルトのcharsetを追加しないように修正

# activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb#250
       def create_database(name, options = {})
         if options[:collation]
-          execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET #{quote_table_name(options[:charset] || 'utf8')} COLLATE #{quote_table_name(options[:collation])}"
+          execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT COLLATE #{quote_table_name(options[:collation])}"
         else
           execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET #{quote_table_name(options[:charset] || 'utf8')}"
         end

つっつきボイス: 「そうそう、知らずに|| 'utf8'が効いちゃうとハマるんだよなー」「修正後のテストでは寿司ビール対策でおなじみのutf8mb4_bin使ってますね」

MySQLのencodingをutf8からutfmb4に変更して寿司ビール問題に対応する

リファクタリング: Browserクラスを新設

システムテストのactionpack/lib/action_dispatch/system_testing/driver.rbのオプションがBrowserクラスに引っ越しました。

# actionpack/lib/action_dispatch/system_testing/browser.rb
+module ActionDispatch
+  module SystemTesting
+    class Browser # :nodoc:
+      attr_reader :name
+
+      def initialize(name)
+        @name = name
+      end
...

DHHによる修正2件

# rails/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt#9
   policy.font_src    :self, :https, :data
   policy.img_src     :self, :https, :data
   policy.object_src  :none
-  policy.script_src  :self, :https
+  policy.script_src  :self, :https, :unsafe_inline
   policy.style_src   :self, :https, :unsafe_inline

   # Specify URI for violation reports

つっつきボイス: 「CSP=コンテンツセキュリティポリシー」「unsafe_inlineはW3Cのこれですね↓」

; Keywords:
keyword-source = “‘self'” / “‘unsafe-inline'” / “‘unsafe-eval'” / “‘strict-dynamic'” / “‘unsafe-hashed-attributes'”
CSP3より

-Rails.application.config.content_security_policy do |p|
-  p.default_src :self, :https
-  p.font_src    :self, :https, :data
-  p.img_src     :self, :https, :data
-  p.object_src  :none
-  p.script_src  :self, :https
-  p.style_src   :self, :https, :unsafe_inline
+Rails.application.config.content_security_policy do |policy|
+  policy.default_src :self, :https
+  policy.font_src    :self, :https, :data
+  policy.img_src     :self, :https, :data
+  policy.object_src  :none
+  policy.script_src  :self, :https
+  policy.style_src   :self, :https, :unsafe_inline

つっつきボイス: 「少なくともpはないなー: Kernel.#pがあるから」「そういえば1文字のローカル変数で他にも使えないものがあったような…」

その後思い出しましたが、pryではcなどをローカル変数に使うと怒られるのでした。

[1] pry(main)> c=1
=> 1
[2] pry(main)> c
Error: Cannot find local context. Did you use `binding.pry`?

参考: Pryのコンソールで使えない変数

Rails

Railsチュートリアルが5.1.4に対応


つっつきボイス: 「安川さんたちが継続的翻訳システムを構築しているおかげでRailsチュートリアルもガイドもオープンな差分翻訳ができるようになっててうれしいです: 自分はバッチで翻訳する方が好きですが」

プロセスマネージャ再び

Dogfooding Process Managerの続きだそうです。


つっつきボイス: 「自前でプロセスマネージャをこしらえた話のようなんですが、このプロセスって何だろうと思って」「ざっとしか見てないけど、Unixのプロセスのことではなさそうに見える」「ところで、何とかmanagerってネーミングはたいていアンチパターンですね」「あー確かに」

そういえば野球の世界では監督はmanagerですが、日本だとマネージャーは違う意味に横滑りしてますね。

マイグレーションをpendingしたままRailsを本番で実行しないようにする方法

短い記事です。ActiveRecord::Migration.check_pending!でやれるそうです。

# 同記事より
if ($PROGRAM_NAME.include?('puma') || $PROGRAM_NAME.include?('sidekiq')) && Rails.env.production?
  ActiveRecord::Migration.check_pending!
end

RailsのForm Objectとルーティング(RubyFlowより)

# 同記事より
class NewQuestionnaireForm
   include ActiveModel::Model

  def to_model
    Questionnaire.new(title: title, questions: questions)
  end

  def save
    to_model.save
  end
end

Railsのメモリ容量を減らしてHeroku課金を節約(Awesome Rubyより)


同記事より

以下の記事に出てきたjemallocyajl-rubyなどを動員して節約に励んでいます。

Ruby: mallocでマルチスレッドプログラムのメモリが倍増する理由(翻訳)

⭐derailed_benchmarks: Railsアプリのさまざまなベンチマークを取れるgem⭐

上の記事にも使われていたgemで、★1800超えです。ヒープダンプ/メモリリーク調査/stackprofなどさまざまな静的/動的情報を取れます。

# READMEより
$ bundle exec derailed exec perf:stackprof
==================================
  Mode: cpu(1000)
  Samples: 16067 (1.07% miss rate)
  GC: 2651 (16.50%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
      1293   (8.0%)        1293   (8.0%)     block in ActionDispatch::Journey::Formatter#missing_keys
       872   (5.4%)         872   (5.4%)     block in ActiveSupport::Inflector#apply_inflections
       935   (5.8%)         802   (5.0%)     ActiveSupport::SafeBuffer#safe_concat
       688   (4.3%)         688   (4.3%)     Temple::Utils#escape_html
       578   (3.6%)         578   (3.6%)     ActiveRecord::Attribute#initialize
...

つっつきボイス: 「derailed_benchmarksは結構使われている印象っすね」「作者はRichard Schneemanさんでした」

ベテランRubyistがPythonコードを5倍速くした話(翻訳)

今週の⭐を進呈いたします。おめでとうございます。

Stimulus: Turbolinksと相性のよい控えめなJSフレームワーク(Ruby Weeklyより)


stimulusjs/stimulusより

// hello_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  greet() {
    console.log(`Hello, ${this.name}!`)
  }

  get name() {
    return this.targets.find("name").value
  }
}

つっつきボイス: 「Stimulusって、確かDHHのBasecampがやってるやつですよね」「Turbolinksって最近オフにすること多いけど」

Railsを順を追ってアップグレードする(Awesome Rubyより)


つっつきボイス: 「冒頭の1. Stop the world、2. Long-lived upgrade branchとかまさに定番のアプローチ」「こうやって本番を二本立てにして↓リバースプロキシで振り分けながら少しずつ移行するというのもあるある: 検証が不十分なまま切り替えるとえらいことになったりするけど」


同記事より

ActiveRecordに欲しくなるEctoの機能(Awesome Rubyより)


infinum.coより

def registration_changeset(struct, params) do
  struct
  |> cast(params, [:email, :password])
  |> validate_required([:email, :password])
  |> unique_constraint(:email)
  |> put_password_hash()
end

def update_profile_changeset(struct, params) do
  struct
  |> cast(params, [:first_name, :last_name, :age])
  |> validate_required([:first_name, :last_name])
end

|>はElixirの「パイプライン演算子」だそうです。


つっつきボイス: 「Ectoって、ElixirのPhoenixフレームワークで使うやつか」「EctoはORMではない、って書いてますね」「この種のフレームワークを業務で使う動機は今のところ見えないなー」

参考: Rails使いがElixirのEctoを勉強した時のまとめ

Railsアプリの災害復旧プラン


engineyard.comより


つっつきボイス: 「disaster recovery planはRailsアプリに限らず重要っすね」「そういえば最近Engine Yardってひと頃ほど見かけない気がしてきた」

あるRails請負開発者の一日(Hacklinesより)

Planet Argonさん(@planetargon)がシェアした投稿


つっつきボイス: 「相当昔ですが、Oracle日本支社では犬飼ってるって話を思い出しました」「今のオフィス事情だと難しそう」

その他Rails小粒記事


つっつきボイス: 「JavaScriptのテスティングフレームワークというとmocha以外にJestもあるのね」
「最後のパーシャルレンダリング記事、でかいデータで素朴にeach回したら確かに遅い↓」

<% @users.each do |user| %>
    <%= render 'erb_partials/post', user: user %>
<% end %>

「こうやってcollection使う方が確実に速いけど、油断するとつい上みたいに書いちゃうことはあるな」「社内でもたまに見ますね」

<%= render partial: 'erb_partials/post', collection: @users, as: :user %>

参考: Railsガイド 3.4 パーシャルを使用する

Ruby trunkより

提案: Hash#transform_keys!recursive: trueオプション(継続)

config = MyAwesomeFormat.load(file); config.transform_keys!(recursive: true, &:to_sym)みたいに書きたいという主旨です。

def transform_keys!(recursive: false, &block)
  # do original transform_keys! here
  values.each do |v|
    if v.respond_to?(:each)
      v.each{|i| i.transform_keys!(recursive: true, &block) if i.respond_to?(:transform_keys!) }
    else v.respond_to?(:transform_keys!)
      v.transform_keys!(recursive: true, &block)
    end
  end if recursive
end

提案: GC速度と少々引き換えにメモリを削減(継続)


#14370より

Aaron Pattersonさんからのissueです。


つっつきボイス: 「最初にレス付けてるnormalpersonさんは昨年のRubyKaigiのあちこちで名前が出てきてた、普通じゃない人」「凄い名前w」

週刊Railsウォッチ(20170922)特集: RubyKaigi 2017セッションを振り返る(1)、Rails 4.2.10.rc1リリースほか

入れ違いで修正

Ruby

Ruby 2.5の陽の当たっていない新機能(Hacklinesより)

行カバレッジやブランチカバレッジ機能などを紹介しています。

Y -> 1: def hello(number)
Y -> 2:   if number == 1
Y -> 3:    'world'
Y -> 4:   else
N -> 5:     'mars'
Y -> 6:   end
Y -> 7: end
Y -> 8: 
Y -> 9: hello(1)

つっつきボイス: 「この機能がRubyMineみたいなIDEと連携したらすごくうれしい」「名前忘れたけどこういうカバレッジのgemあった: 絶対に通過しないコードをあぶり出したりとかできる」

なお2.5のカバレッジについては以下でChangelogをざっくり訳してあります。

Ruby 2.5.0リリース!NEWSを読んでみた

Rubyの継承で動的に引数を渡す(RubyFlowより)

# 同記事より
class Render
  def self.engine; end

  def self.inherited(subclass)
    puts subclass        #=> Memo::Render
    puts subclass.engine #=> nil !!!
  end
end

つっつきボイス: 「Rubyってここまでエグいコードも書けるんだなって思いますね」「何でもアタッチできちゃうとか、ここまでくるともうオブジェクト指向言語というよりオブジェクト指向スクリプトみたいw」

Ruby 2.5のFrozenErrorクラス

2.5.0 :001 > NAME = 'Atul'.freeze
 => "Atul" 
2.5.0 :002 > NAME << 'Joy'
Traceback (most recent call last):
        2: from /home/atul/.rvm/rubies/ruby-2.5.0/bin/irb:11:in `<main>'
        1: from (irb):2
FrozenError (can't modify frozen String)

つっつきボイス: 「今までRuntimeErrorだったのがFrozenErrorに変わるのはありがたい」「frozen_string_literalが完了するまでの混乱を少しでも軽くするためでもあるんでしょうね」

参考: frozen_string_literalが入って気づいた、メソッド設計の原則

Kernel.method_added


つっつきボイス:Kernel.method_addedなんてのがあるのか: 特定のメソッド追加にフックかける」「実体はModuleにあった↓」

# docs.ruby-lang.org/ja/2.5.0/method/Module/i/method_added.html
class Foo
  def Foo.method_added(name)
    puts "method \"#{name}\" was added"
  end

  def foo
  end
  define_method :bar, instance_method(:foo)
end

=> method "foo" was added
   method "bar" was added

参考: Module#method_added

aruba: CLIアプリをRSpecやMiniTestでテストするgem(Awesome Rubyより)


つっつきボイス: 「あのCucumberがやってるんですね」「バッチ処理のテストをRSpecとかで書けるし、Ruby以外に任意のCLIに使えるのがいいな」


app.cucumber.pro

Rubyのシンボル話その後

#14347はちょうど前回のウォッチで取り上げました。


つっつきボイス: 「あちこちで話題になってるやつですね」「途中まで読んでた」「やっとシンボルは文字列ではないということになったと」

Rubyのシンボルをなくせるか考えてみた(翻訳)

Rubyはやっぱり死んでない(Ruby Weeklyより)

こちらもEngine Yardのブログです。

ネストしたハッシュをlambdaでリファクタリング

同記事より
pub.doc[‘programs’].each &remove_icons(‘grades’, &remove_icons(‘units’))
def remove_icons value_key=nil, &block
  lambda do |key, value|
    next if key == ‘_order’
    value.delete ‘icons’
    if value_key
      value[value_key].each(&block) if block_given?
      value[value_key].each(&remove_icons) unless block_given?
    end
  end
end

つっつきボイス: 「うんうんよくあるやつ:再帰で書きましょう!みたいな」「Hashの再帰って何かと面倒ですよね」「せいぜい3階層ぐらいしか潜らないことをわかって書いてるのに、RuboCopに怒られたりとか」

高木さん

SQL

PostgreSQLにはmeltdownパッチは不要だが少し遅くなる(Postgres Weeklyより)


つっつきボイス: 「meltdownは基本的にカーネルの問題だからアプリにパッチが必要になることはそうないかと」「パッチで遅くなるのはもうしゃーない」「AWSもいろいろ言ってるけど対策すれば遅くなるっしょ」

参考: CPU脆弱性Meltdownのパッチ適用でベンチマークスコアが25%低下した

PostGraphile: PostgreSQLをGraphQL API化するJSライブラリ(Postgres Weeklyより)


graphile.orgより

以下を実行してhttp://localhost:5000/graphiqlをブラウザで開くといきなりGraphiqlが動きました。N+1クエリも克服しているそうです。これ凄いかも。

npm install -g postgraphile
postgraphile -c postgres://user:pass@host/dbname --schema schema_name

PGLogicalがアップデート(Postgres Weeklyより)

PostgreSQLの動作を知る(Postgres Weeklyより)

Pythonのツールを使います。


つっつきボイス: 「お、Internalとか書いてるけどこれはむしろ入門向け記事ですね: 量は多いけど相当やさしい内容」

JavaScript

(a ==1 && a== 2 && a==3)trueにする知見が続々

BPS社内で盛り上がりました。

// Stackoverflowより
var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
    console.log("Why hello there!")
}

ifに半角のハングル文字を使うという荒業を繰り出したり、C++などでやってみたりしています。

JavaScriptの二進木、再帰、末尾呼び出し最適化

nullとundefinedとは

CSS/HTML/フロントエンド

Web Componentsの秘密

参考: MDN Web Components

フロントエンドのエラー表示を再考する


logrocket.comより

blog.jxck.ioの新着記事


つっつきボイス: 「これは読んでおきたい記事」「そういえばこれと少し似た感じの、ネコのアイコンのブログ記事が話題になってましたね」「ネコのアイコン…?」「あったこれ↓」「あこの人か: アイコンとか全然気にしてなかったw」

参考: ソフトウェアの互換性と僕らのUser-Agent文字列問題

Screenshot-to-code-in-Keras: ニューラルネットワークでモック画像から静的HTMLページを生成(GitHub Trendingより)

アニメーションGIFが巨大すぎるのでここには貼りませんでした。


つっつきボイス: 「すげっ」「Bootstrapにも対応してるみたいですね」「一回こっきりの案件とかならかなりイケそう」「HTMLコーダー界に激震走るか」

その他

YAGNIを実践する


dev.to/gonedarkより


つっつきボイス: 「社内にもYAGNIを愛して止まない人がいるから彼を観察してるとだいたいわかりますよ」

参考: Wikipedia-ja YAGNI

Slackにprivate shared channel機能が追加


つっつきボイス: 「これありがたい: shared channelは前からあるけどpublicにしかできなかったんで」

Windows CLIの改善

WSLのchmod/chownの改良とtar/curlの追加です。

なお、こんなのもありました。

DOS窓の|は大丈夫だそうです。

Docker for macで/etc/localtimeがマウントできない問題

minio: Amazon S3 API互換のオブジェクトストレージサーバー


minio.ioより


つっつきボイス: 「S3互換のこういうのは他にもありますけどね」「GCPやAzureとかいろんなクラウドで使えるのはよさそう」「今さらですがオブジェクトストレージサーバーって何でしたっけ?」「AWS S3みたいなサービスがそれです: WebDAVみたいにRESTfulにオブジェクトにアクセスできるサービス」

HighwayHash: Go言語の爆速ハッシュ生成ライブラリ


つっつきボイス: 「10G/secとか確かに超速い」「ハッシュは速度だけあってもいかんので、ちゃんと分散してるかとかも大事ですね」

データがあれば使えるCloud AutoML VisionをGoogleが発表

一般のニュースにもなってますが一応。


つっつきボイス: 「今はデータサイエンティストやAIエンジニアが明らかに不足してるからどこもカスタマイズとかチューニングに手が回らなくて、こうやってそこそこのものを公開して好きに使ってくれ、みたいな方向に向かってる感じですね」「ユーザーに丸投げですか」

参考: Googleが「Cloud AutoML Vision」を発表、独自のデータセットを使ったカスタム機械学習モデルが簡単に構築できるように

番外

暗算術

a% of b = b% of aは初めて知りました。「25の16%=16の25%」みたいに使うそうです。


つっつきボイス: 「計算すると確かにそうなってるな: 式で見ると一瞬でわかるけど言われるまで気づきにくい」「英語圏なんで単位のフィート換算とかいらなさそうなのも多いです」「ひと頃入社試験でよく出されたフェルミ推定なんかやるときは、こういうのを何となくでも知っておかないと手も足も出なかったりしますね」

参考: 暗記しておくとなにかと便利なプチ公式まとめ

これは欲しい


つっつきボイス: 「Nintendo Laboとどっちが子どもにウケるかなと思って」「今ならポプテピピックっしょw」「あれはもう子どもの反応が面白すぎますね」

学習/プログラミング不要の産業ロボット


つっつきボイス: 「荷物の積み下ろしとかまでやってます」「人間雇う方がまだまだ安いな、今のところは」

Switchエミュレータ(GitHub Trendingより)


つっつきボイス: 「ソフトはともかくハードウェアはそうもいかないか」

その後、GPL V2というライセンスの厳しさや、パチンコの当たり判定システムの話題で盛り上がりました。

ルーシーさん

自己修復コンクリート


今週は以上です。

バックナンバー(2017年後半)

週刊Railsウォッチ(20180112)update_attributeが修正、ぼっち演算子`&.`は`Object#try`より高速、今年のRubyカンファレンス情報ほか

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

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

Rails公式ニュース

Ruby Weekly

Awesome Ruby

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines

Postgres Weekly

postgres_weekly_banner

Frontend Weekly

frontendweekly_banner_captured

JSer.info

jser.info_logo_captured

Github Trending

160928_1701_Q9dJIU

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! 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ウォッチ

インフラ

ActiveSupport探訪シリーズ