週刊Railsウォッチ(20180925)Rails大規模支払サービス開発のノウハウ、RailsのMySQLがutf8mb4に移行、Rpush gemほか

こんにちは、hachi8833です。Linusが京都に隠遁し、RubyがGitへの移行を検討し、GuidoがPythonの意思決定から降りた今日この頃、皆さまいかがお過ごしでしょうか。私は先日自宅のAirMac TimeCapsuleが息を引き取りました。

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話です👄

9/25は予定を変えてウォッチを公開いたします🙇。


つっつきボイス:「AirMac、いつもチンチンに熱くなってた🍜ので熱死したっぽいです😭」「AirMacシリーズ自体がディスコンになっちゃいましたからね〜⛔」

「そうそう、RubyのリポジトリをGitHubに移行する話」「大江戸Ruby会議07でもちらっと話に出てました」「Subversionから移りたくない人もいるだろうし、時間はかかりそうですね」「GitのWindows対応が残念すぎるから移りたくないという理由を挙げていたのを以前どこかで見かけました」「それはある😅」「Rubyほどの規模ならSubversionでもいいのかなと思ったりもするけど、もしかするとGitそのものというよりGitHubの機能を使いたいからだったりして?🤔なんてね😆」「😆」

後で探すと、リポジトリは今年の3月からできているようです↓。


git.ruby-lang.orgより

参考: git.ruby-lang.org を作った - HsbtDiary(2018-03-24)
参考: Feature #11741: Migrate Ruby to Git from Subversion - Ruby trunk - Ruby Issue Tracking System

訂正(2018/09/26)

直接フィードバックをいただきました。訂正いたします🙇。

【お知らせ】週刊Railsウォッチ「公開つっつき会」#3開催

ご好評にお応えして「週刊Railsウォッチ 公開つっつき会 第3回」を10月4日(木)19:30〜より開催いたします。詳しくは上のリンクをどうぞ。ノートPC片手にお気軽にご応募ください🙇🙇。

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

先週のウォッチで公式の更新情報をいくつか先回りできたのがちょっとうれしいです😊。

digest pathをループから切り出してオブジェクト割り当てを削減

# actionview/lib/action_view/helpers/cache_helper.rb#L#211
-     def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil)
+     def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil, digest_path: nil)
        if skip_digest
          name
        else
-         fragment_name_with_digest(name, virtual_path)
+         fragment_name_with_digest(name, virtual_path, digest_path)
+       end
+     end
+      def digest_path_from_virtual(virtual_path) # :nodoc:
+       digest = Digestor.digest(name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies)
+        if digest.present?
+         "#{virtual_path}:#{digest}"
+       else
+         virtual_path
        end
      end

つっつきボイス:「局所最適化っぽい改修かな」「毎回計算して引っ張ってくるのをやめて、一度使ったものを使い回す形にする、よくある形の修正」「いわゆるメモ化ですね😃」

# actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb#L47
+     def digest_path
+       @digest_path ||= @view.digest_path_from_virtual(@template.virtual_path)
+     end

MySQLのデフォルト文字コードセットがついにutf8mb4

# activerecord/Rakefile#L
    desc "Build the MySQL test databases"
    task :build do
      config = ARTest.config["connections"]["mysql2"]
      %x( mysql --user=#{config["arunit"]["username"]} --password=#{config["arunit"]["password"]} -e "create DATABASE #{config["arunit"]["database"]} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
      %x( mysql --user=#{config["arunit2"]["username"]} --password=#{config["arunit2"]["password"]} -e "create DATABASE #{config["arunit2"]["database"]} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
      %x( mysql --user=#{config["arunit"]["username"]} --password=#{config["arunit"]["password"]} -e "create DATABASE #{config["arunit"]["database"]} DEFAULT CHARACTER SET utf8mb4" )
      %x( mysql --user=#{config["arunit2"]["username"]} --password=#{config["arunit2"]["password"]} -e "create DATABASE #{config["arunit2"]["database"]} DEFAULT CHARACTER SET utf8mb4" )
    end

つっつきボイス:「お、とうとう来た㊗️」「もっと早くに移行してもよさそうなのに、まだだったんですね」「そうそう、かなり大きなbreaking changesなのでずっと見送られてた⚾️」「マイグレーションが避けられないから?」「いや、database_ymlができてればそこにはエンコーディングが書かれているものなのでそっちは問題ない」「別の問題なんですね」「実はMySQLでutf8mb4を安心して使えるようになったのはMySQL 5.7からの話で、5.6.xだとその下のマイナーバージョンによってはインデックス周辺で追加の操作が必要になったりするので、マイナーバージョンに気をつけておかないとutf8mb4でたまにハマることがある」「お〜😲」「5.7以降ならマイナーバージョンを気にせず使える😋: たぶんそういうのもあってutf8mb4への移行に踏み切ったんでしょうね」

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

「おや、#33608の修正だとcollation(照合順序)が修正されてないっぽい?collationがutf8mb4_unicode_ciだと例の寿司ビール問題↑が発生しちゃうので」「コードレビューでもツッコミ入ってますね」「たぶんこの後のコミットでcollationも対応するだろうし: collationも大事だから」

参考: 【MySQL】照合順序とは? - Qiita

こんなつぶやきも見つけました↓☺️。


同PRより

おそらくこれに関連して、以下のコミットでMySQL 5.1がutf8mb4文字セット非対などの理由でついにサポート終了しました🙋🏻‍♂️。

#inspectでもカラムフィルタが効くようになった


つっつきボイス:「これは先週扱った180dcd1の続きのPRとしてドキュメントも追加されていました」「例のfilter_attributesですね😃」

ActiveStorageのルーティングパス/rails/active_storageをカスタマイズ可能に

routes_prefix属性が追加されて/files/blobs/:signed_id/*filenameなどのパスを使えるようになりました。

# activestorage/lib/active_storage.rb#L35

 module ActiveStorage
   extend ActiveSupport::Autoload
...
+ mattr_accessor :routes_prefix, default: "/rails/active_storage"

つっつきボイス:「今までは固定だったんですね」「従来はget "/rails/active_storage/blobs/:signed_id/*filename"ってなってたし」「思い切りハードコードされてた」「こんなのがまだ残ってたんだな〜: Rails使っているのを見せたくないことも多いだろうし」

ActionCableの接続でnameにRedisのidを含むようになった

# 修正前
$ redis-cli client list
id=669 addr=127.0.0.1:46442 fd=8 name= age=18 ...
# 修正後
$ redis-cli client list
id=673 addr=127.0.0.1:46516 fd=8 name=ActionCable-PID-19413 age=2 ...
# actioncable/lib/action_cable/subscription_adapter/redis.rb#L16
      cattr_accessor :redis_connector, default: ->(config) do
-       ::Redis.new(config.slice(:url, :host, :port, :db, :password))
+       config[:id] ||= "ActionCable-PID-#{$$}"
+       ::Redis.new(config.slice(:url, :host, :port, :db, :password, :id))
      end

つっつきボイス:「前はname=が空だったんですね」「バグかな?っと思ったけど今まではRedisにつなぐときにname=を指定してなかったのか: これでRedis接続を名前で区別できるようになったと」「$$って何だろうと思ったらプロセスidが取れるRubyの特殊変数でした↓」「そうそうこれ」「この記事書いといてよかったと思った瞬間😋」

[Ruby] Kernelの特殊変数をできるだけ$記号なしで書いてみる

レコードが実際にsaveされるまでカウンタキャッシュが更新されないようになった

これはコミットログから見積もった最新の修正です(つっつき会時点)。過去のさまざまな改修を経て、仕上げとして@_after_replace_counter_calledガード条件を削除したとのことです。長患いを経て包帯が取れた感じですね✨。

# activerecord/lib/active_record/associations/belongs_to_association.rb#L50
        def replace(record)
          if record
            raise_on_type_mismatch!(record)
-           update_counters_on_replace(record)
            set_inverse_instance(record)
            @updated = true
-         else
-           decrement_counters
          end
           replace_keys(record)

           self.target = record
         end
...
-       def update_counters_on_replace(record)
-         if require_counter_update? && different_target?(record)
-           owner.instance_variable_set :@_after_replace_counter_called, true
-           record.increment!(reflection.counter_cache_column, touch: reflection.options[:touch])
-           decrement_counters
-         end
-       end
-        # Checks whether record is different to the current target, without loading it
-       def different_target?(record)
-         record._read_attribute(primary_key(record)) != owner._read_attribute(reflection.foreign_key)
-       end

つっつきボイス:「kamipoさん4度目の正直!」「あぁ〜カウンタキャッシュは結構大変なんですよね〜: トランザクションと絡んでくると特に」「お〜😲」「カウンタキャッシュってアプリケーション層でやろうとするとどうしても大変で、本来ならDBMS側でtrigger関数なんかを設定してやる方がきれいに書けるし、速い💪」「トランザクションも?」「確実にトランザクショナルになるので安全🏥」「アプリ層だとトランザクションと一致しなくなったりすることがあるのか」「とは言っても、アプリ層だとlambdaでコードを渡せるとか便利な点もいろいろあります」「単なるカウンタキャッシュが欲しいだけならデータベースにトリガを追加する方が軽くて速い: よほど下手なやり方をしなければですが」

Rails向け高機能カウンタキャッシュ gem ‘counter_culture’ README(翻訳)

Rails

元Airbnb/PayPal開発者が語る大規模Rails支払システム構築のノウハウ


つっつきボイス:「そういえばAirbnbのサイトもRailsですね」「転職活動用の職歴アピール記事かなとも思いましたが」「テスタビリティにaudit trail(監査用の追跡記録)とか、支払サービスの構築でやりそうなことはひととおり押さえてそう」


airbnb.ioより

「ActiveRecordの上に置くProtectedAccessって何でしょう?」「これはいわゆるエンタープライズアプリケーションアーキテクチャなんかでよくある、上に層を1つ重ねるものじゃないかな: ActiveRecordを生で扱うにはシステムが大きすぎるときなんかにこういう設計にすることがあります」「お〜😲」

「うん、続きに書いてある↓: 既存レコードは更新せずに必ずINSERTだけで記録すると」「あー、監査ではデータが消えちゃまずいからこういうふうにしそうですね: こんなgemがあった気がしたけど何だっけ…(PaperTrailでした)」「全記録を残すという目的以外に、INSERTのみで記録すると再インデックスが一切不要になるストレージ層のフラグメンテーションを回避できるというメリットもあります: 既存レコードを更新するとデータベースを再インデックス(VACUUMとか)が必要になるので(追記: 最近のPostgreSQLはvacuum不要です)」「あ〜そっか!😃」「大規模なデータベースなんかでよく使われる戦略です🗻」

一方ProtectedAccessは境界面で(モデル同士を)隔離しつつ、amount=saveやActiveRecordモデルを使える。saveが呼ばれると、既存のレコードを更新するのではなく新しいレコードを作成して保存する。Paymentテーブルにアクセスできる実際のモデルを呼び出すことはできないようになっている(class Payment < ProtectedAccessオブジェクトのprivateメンバー以外何もないため)。
同記事より大意

PostgreSQL 10: テーブル継承と宣言的パーティショニングでスケーリングする(翻訳)

「記事の続きはというと、バリデーションは厳し目にしてなるべく手前の方で問題を検出するようにする: これは正しい戦略📊」「『Fail Fast (and loud!)』だから早期発見周知徹底的な」「あとはService Objectを使う話↓: コードは冗長になるけど、この規模になるとこういう形でやることになるでしょうね☺️」

# 同記事より
class CompleteTransaction < ServiceBase
  def initialize(opts = {})
    validate(opts)
    @txn = opts[:txn]
    @buyer = opts[:buyer]
    @status = opts[:status]
  end

  def validate(opts)
    # use parameter validation to strongly check expected parameter values
  end  

  def perform
    response = Net::HTTP.post_form....
    # inspect response and return accordingly
  end
end

Rails tips: Service Objectパターンでリファクタリング(翻訳)

「Complexity Filters?」「これはRubocopの設定にあるABCコードサイズという評価基準」「なるほどそっちですか」「開発人数が増えてくるとこうやってABCスコアを減らすことも必要になるだろうな(つらいけど😆)」

  • Assignment(代入)
  • Branch(呼び出し)
  • Condition(条件文)

参考: RuboCopのABC Sizeチェックについて調べた - 毒シューマイ

「Disable replica readsは、決済系の処理はレプリカデータベースから読み込まないようにする: そりゃそうだ😎」

「全体にバランスのいい記事!😍」「俺はエンタープライズアプリ書けるぜ!というアピールとしてもいい感じ💪」

追記:

参考: SQLite Query Language: VACUUM

JSON Web Token(JWT)とRailsのcookie store


つっつきボイス:「はてブに上がってたヤツです」「あ〜これこれ😆😆: まだ最後まで読んでないけどっ」「文中でRailsのcookie storeもJWTと同じような問題を抱えてるとあったので」「Railsのcookie storeもいろいろつらみがあるし、自分もJWTをセッションに使うのはあまりやりたくない😔」「『JWTはステートがない』って書かれてますね」「JWT自体はピュアなAPIインターフェイスみたいなものなので、ステート管理の機能はないはず」

「『鍵管理』問題、あるある」「『退職者問題』って、以前もウォッチで話題になったマスターキーの保存場所の話にも通じる感じですね」「ちなみにJWTはAPIでは割とメジャーな方式です☺️」


jwt.ioより

Rpush: Railsでも使えるRubyプッシュ通知gem(Ruby Weeklyより)


同リポジトリより


つっつきボイス:「FireBaseなどをプッシュのバックエンドに使うRubyのインターフェイスという感じですね: 他にもこういうのがバックエンドに使えるのか↓」「Windows Phone!使う人いるのかな〜😆」「😆」

  • Apple Push Notification Service(Safari Push Notificationsも含む)
  • Firebase Cloud Messaging(旧Google Cloud Messaging)
  • Amazon Device Messaging
  • Windows Phone Push Notification Service
  • Pushy

「頑張って個別のサービスのコードを書かなくてもこうやってRubyらしいインターフェイスでプッシュ通知を書けるというのは中々いいかも😋」「😍」「とりあえず★押しとこ👉」

# 同リポジトリより
app = Rpush::Adm::App.new
app.name = "kindle_app"
app.client_id = "..."
app.client_secret = "..."
app.connections = 1
app.save!

「そういえば社内勉強会でも、サーバーからのプッシュは何かと大げさになりがちという話をされてましたね」「プッシュの仕組みはいろいろあるけど実装がかなり違うので、こういう共通化層がないとしんどいですね😭」

RubyMine更新情報(Ruby Weeklyより)


つっつきボイス:「RubyMineはやっぱりいいな(しみじみ)「よさげな機能あるかな?」

「メソッドへの切り出しの改良が多いみたい」「切り出しで同じことやってる部分も見つけて置き換える↓」


同記事より

「show usageでそのメソッドが使われている場所を表示する機能は前からあったっぽいけど、Railsのコードを追いかけたりするのに便利かな」「findするのと同じ?」「結果は同じですが、RubyMineのキャッシュに乗る分速いでしょうね😋」

「置き換え時にExcludeで除外を指定できる機能も前からあったかな」「知らなかった〜」「置き換え、やるとついイケないところまで置き換えちゃうんで基本使ってない😅」「ファイル名をリネームするときに事故りやすい傾向あるかも」

「サブストリングを変数や定数に切り出す機能↓もなかなか」「使うことあるかな?とも思うけど、すごく込み入っているときなんかに役立つかも」「JavaだとEclipseにこの手の機能があった気がするけど、それをRubyとかRailsでできるのがスゴイ」


同記事より

「手取り足取りというか痒いところに手が届くような改善😃」「だいたいIntelliJ IDEA本体での改善でしょうから、他のJetBrains IDEでも使えそう😋」

Martin Fowler『Refactoring 2nd Edition』が予約開始

3月のウォッチ同書の情報をお伝えしていましたが、やっとAmazonで予約開始ということのようです。


つっつきボイス:「おぉ、Martin FowlerのRefactoring」「基本的にJavaが対象だったかな」「あれ、2nd EditionはJavaScriptにも対応したと聞いてたけど?」「あ、ほんとだ💦」「今ならJavaScript入れる戦略でしょうね」「まだ英語版しか出ないのか」「それも11月末発売で」

Ruby版のRefactoringも2nd Edition出るといいですね🍭」「Martin先生がRuby版出すかな〜🤔: Javaというかプログラミング設計の大物ですね」

後で調べると、Refactoring Ruby EditionではMartin先生はメインの著者ではないそうです。

BrowserifyからWebpackへ


つっつきボイス:「Browserify、あったなーそんなの😆」「app/assets以下を整理してWebpackに移行するとか大変そう: 結局Sprockets系のアセットヘルパーを全部Webpack用に直さないといけないので😔」「私もオレオレRailsアプリでこれやりたいと思ってるんですが手こずりそうで😅」「素直なCSSで書かれているだけならすぐ寄せられるんですけど、変数展開とか使ってたりすると一気に難しくなってつらい」


browserify.orgより

参考: Browserify: それはrequire()を使うための魔法の杖 - Qiita

その他Rails


つっつきボイス:「ちょうど私たちのつっつき会と同じ時間帯にやってるようです」

Ruby trunkより

Rubyのキーワード引数の今後

先週ちらっと触れたキーワード引数スライドですが、今日社内勉強会でも発表して引数周りを少し追いました。正直、以下に共感します。


つっつきボイス:「今日の勉強会の発表はよかったっす💪」「ありがとうございます🙇: TechRacho記事にまとめます」「キーワード引数はいろいろヤバい」「勉強会でも話したけど、どうして動くのかわからないのに動いているのが一番つらい😆」「メソッド呼び出しでnil足したら動いた話でしたっけ?」「nil足して動くようなのは全然大したことなくて、メソッド定義を見ればだいたい納得がいくんですが、define_methodとかsendpublic_sendあたりが絡むとヤバいんじゃないかと思う」「メソッド定義を見てもさっぱりわからないヤツ😭」「メタプロですね」「受け取った引数をそのまま渡している箇所が想定から外れているのにたまたま動いていて、breaking changesが入って制約が厳しくなるとあちこちで火を噴く、なんてことがありそうで」「エラーで落ちるならまだいいんだけど、違う解釈で通ってしまったりするとコワイ😰」「さすがにそういう変更はかけないかな: 警告出して落とすことはすると思う」「大江戸Ruby会議 07でもwarning出す方向で考えると言ってました」

参考: instance method Module#define_method (Ruby 2.5.0)
参考: instance method Object#__send__ (Ruby 2.5.0)
参考: instance method Object#public_send (Ruby 2.5.0)

「ツイートの『Hash のキーが Symbol なのか String なのか混ざっている時にわけわからなくなる』、ほんにこれ」「そうそうそう!😤」「そんなときのためのHashWithIndifferentAccess↓という神クラスですよ: これがデフォルトの動作でいいんじゃないかと思うこともあるけど、ハッシュのキーをオブジェクトにしたい場合もありますからね😎」

参考: ActiveSupport::HashWithIndifferentAccess

「普通のハッシュとは別に、シンボルだけをキーに取るシンボルハッシュみたいなものがあるといいんじゃないかと思うことある」「それ欲しいヤツ!」「でなければ、今のハッシュをシンボル専用にして、任意のオブジェクトをキーにしたいときはそれ専用のObjHashみたいなものを別に用意するとか」「ハッシュのキーはほとんどの場合シンボルにしますからね」「breaking changesになるからやらないでしょうけど🤔」

「そういえば大江戸Ruby会議07で、『シンボルでハイフンが使えたらうれしい』という意見を見かけました」「あ、シンボルリテラルでハイフンを使いたいってこと?」「ですね: ""で囲まずにやりたいと」「パーサーに怒られそう😆」「でも今のRubyはこういう書き方↓ができるから随分楽になりましたね😋」「あー、式展開で任意の文字列をシンボルにするのか😳」「ですです😎」「これが使えるから今のRubyのシンボルリテラル周りはだいたい満足✨」

[1] pry(main)> :'hogehoge'
=> :hogehoge
[2] pry(main)> piyo = '1-29eikdmfc/~!@#$%'
=> "1-29eikdmfc/~!@\#$%"
[3] pry(main)> :"hoge#{piyo}"
=> :"hoge1-29eikdmfc/~!@\#$%"

Ruby

Apache OpenWhiskでRubyがネイティブサポート


つっつきボイス:「OpenWhisk?」「FaaS(Function as a Service)ということで、AWSでいうLambdaに相当しそう」「at any scaleで↓こういうものを使って構築できるということみたい」


openwhisk.apache.orgより

「Apacheのプロジェクトですが、Apache Webサーバーとは関係なさそう?」「少々紛らわしいんですがWebサーバーとは別で、いわゆる「Apache Projects」ですね: ApacheではWebサーバー以外にもものすごくたくさんのプロジェクトが動いてます↓」「え、こんなにいっぱいあるんだ!😳」「しかも質の高いものが多いことで知られてます🧐: あのHadoopHBaseもApache Projectsだし」「へー!」「kafkaもRubyKaigiで登場してましたね」「karafkaですね」「CloudStackもApache Projectsなのかー」


apache.orgより

「ちなみにRubyバインディングのincubator-openwhisk-runtime-rubyは今の所★はゼロですが」「まあKubernetesにデプロイできるということはGCPなんかにもすっと置けそうですね😊」

「ちょっと話逸れますが、大江戸Ruby会議07で、AWSのDockerコンテナよりGCPのDockerコンテナの方が速いという話題が出てました↓」「AWSのコンテナは結局のところEC2のVMの上で動くんですが、Googleなら専用ハードウェア上で動かすとかやってるかもしれない: この辺はあくまで推測ですが」「おー」「GoogleならLinuxカーネルにも手を加えていそうだし: AWSはあくまで普通のLinuxカーネルなので(Amazon Linuxというのもあるけど)」「ふむふむ」「だとするとGCPのコンテナはその環境に依存して他のコンテナサービスだとうまく動かないとかたまにあったりするのかな?」

RSpecの原理を単独で学べるGist(Ruby Weeklyより)


つっつきボイス:「お、このコード単体で実行できるのね」「まさに先週のウォッチに出てきたbundler/inlineを使ってる」「ですです: このままirbに貼り付けて動きます😃」「シンプルでわかりやすくていいんじゃない😋」

「こういうのでRSpecにもっと親しみが持てるようになるかしら?」「いや〜それは中々😆: RSpecで最初につまずくのはこういうexpect↓で引数をかっこ()で渡すのかブロック{}で渡すのかというところ」「そうそう😆」

# 同Gistより
expect(foo).to have_value(1)

「そしてかっこで渡す場合とブロックで渡す場合でかなり挙動が変わるし😭」「はぁー😳」「そしてブロックで渡したときだけraiseで取れるし」「そうそう」「じゃ全部ブロックにすればいいかというと、マッチャーによってはできないものがあるという」「苦労の連続😢」

benchmark-trend: Rubyのベンチマーク(Ruby Weeklyより)

# 同リポジトリより
print trends
# =>
# {:exponential=>
#   {:trend=>"1.38 * 0.00^x",
#    :slope=>1.382889711685203,
#    :intercept=>3.822775903539121e-06,
#    :residual=>0.9052392775178072},
#  :power=>
#   {:trend=>"0.00 * x^2.11",
#    :slope=>2.4911044372815657e-06,
#    :intercept=>2.1138475434240918,
#    :residual=>0.5623418036957115},
#  :linear=>
#   {:trend=>"0.00 + -0.01*x",
#    :slope=>0.0028434594496586007,
#    :intercept=>-0.01370769842204958,
#    :residual=>0.7290365425188893},
#  :logarithmic=>
#   {:trend=>"0.02 + -0.02*ln(x)",
#    :slope=>0.01738674709454521,
#    :intercept=>-0.015489004560847924,
#    :residual=>0.3982368125757882}}

つっつきボイス:「あー、こんなふうに↓rangeで値を変えてベンチマークを取れるのか」「数値そのものの意味がよくわからないんで何とも言えないけど、値を変えていったときに指数(exponential)、power(乗数)、線形(linear)、対数(logarithmic)でパフォーマンスが落ちていく様子が取れるっぽい」「何かのモデルに沿ってるのかな?」「これを信用するかどうかだけど、ちゃんと使えば有用なのかもしれない」「実際にベンチマーク取ってるからプロットしちゃえばいいじゃんという気はするけど😆、このgemはプロットの近似の式まで出してくれている」「たぶん自分用のツールなんでしょうね」「そんな気はするけど筋はよさそう😊」

# 同リポジトリより
Benchmark::Trend.range(8, 8 << 10, ratio: 2)
# => [8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]

Rubyのredoキーワード(Ruby Weeklyより)

# 同記事より
for i in 1..3 do
  puts "Iteration #{i}"

  redo if i == 1

  puts 'After redo'
end

# produces:
#
# Iteration 1
# Iteration 1
# Iteration 1
# Iteration 1
# ... infinite loop

つっつきボイス:「redoってキーワードあったなそういえば: ちなみにRubyにはcontinueはない」「redoってnextと違うやつで、nextはイテレーションするけどredoはイテレーションせずに文字どおりそのループをもう一回やり直す」「まあredoってあんまり使ったことないけどw、Rubyの基本構文として随分前からあるはず」

参考: 制御構造 — redo (Ruby 2.5.0)

Brighton Ruby Conference 2018のVimeo動画

Boring Ruby Code – Adam Niedzielski from Andy Croll on Vimeo.

2018年7月に開催されたBrighton Ruby Conference 2018のの動画を、TechRachoの翻訳記事でお世話になっているAndy Croll氏↓がVimeoにアップしているのを見つけました。

Rails: モデルの外では名前付きスコープだけを使おう(翻訳)


つっつきボイス:「海外のRuby Conferenceか」「イギリスのBrightonですね」「スライドが欲しいスライドが」「上のBoring Ruby Codeとかタイトルだけ見るとちょっと面白そう」「やな感じのsend↓」「式展開してるし😰」


同動画より

Persistent-💎: Rubyのイミュータブルデータ構造

# 同リポジトリより
my_array = a💎[1, 2, 3]

思い切り絵文字使ってます。


つっつきボイス:「珍しくGitLabでやってるし」「何だこれは😳」「Rubyでこんなことする人ときどき見かけるし」「💎を付けるとfreezeしたものを返すだけみたい: 完璧にお遊びですね🏖」

たぶん「007 ダイヤモンドは永遠に」にかけてるんでしょうね。

その他Ruby


つっつきボイス:「trって何だっけ」「正規表現を使わずに文字列を置き換えるやつだったと思います」「そうそう、正規表現だとたいてい遅い」

参考: instance method String#tr (Ruby 2.5.0)

「そういえば何でtrって名前なんだろ?」「(ググって)あー、Linuxのtrコマンドが元なのか」「man trするとtranslate characterと出た」「頭の2文字でtrと略したんだろな」

参考: tr - コマンド (プログラム) の説明 - Linux コマンド集 一覧表

クラウド/コンテナ/インフラ/Linux/Serverless

さくらのDockerホスティングサービス「Arukas」


同サイトより

参考: Arukasハンズオン資料 - 基本操作編 - Qiita
参考: Arukasハンズオン資料 - 事前準備編 - Qiita
参考: Docker の基本学習 ~ コンテナ間のリンク - Qiita


つっつきボイス:「今日の社内チームミーティングで発表されてたので」「どのぐらい本気出すかが気になるところ😎」「Herokuのライバル的な」「価格でもうひと頑張りしてくれたらな〜」

SQL

PostgreSQLのCTEは取扱い注意(Postgres Weeklyより)


つっつきボイス:「CTE = Common Table Expressions」「うは、ぽすぐれだとこんな構文なのか↓」「そしてCTEだと数百倍遅いことがあると」「毎回評価されて遅くなるとかそんな感じ?」

-- 同記事より
haki=# with cte as (select * from foo) select * from cte where id = 500000;
id     | padding
 — — — — — — — — — — — — — — — — — — — — — 
500000 | b292eb19f3145fb087648d5956dfa44e
Time: 227.675 ms

ぽすぐれのドキュメントで見ると、WITHtop_regionsで取ったものをWHERE region IN (SELECT region FROM top_regions)のところで参照できるということか↓」「つまり入れ子のSELECT文を事前に呼んでおいてメインのところでコンパクトにすっきり呼び出せるという」「ほぅほぅ😊!」「Withって何だかVBみたい😆」「RECURSIVEで自己参照もできるし」「普通はできないヤツなのに、ぽすぐれやるな〜💪」

-- postgresql.jpより
WITH regional_sales AS (
        SELECT region, SUM(amount) AS total_sales
        FROM orders
        GROUP BY region
     ), top_regions AS (
        SELECT region
        FROM regional_sales
        WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
     )
SELECT region,
       product,
       SUM(quantity) AS product_units,
       SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;

参考: WITH問い合わせ(共通テーブル式)
参考: With...End With ステートメント (Visual Basic)

JavaScript

目新しいJSライブラリを評価するときの12個のポイント(JavaScript Weeklyより)


同記事より


つっつきボイス:「普通にチェックする部分かなと思いつつ」「絵文字がカワイイ🐻」「Momentumはいわゆる『勢い』ですね」

「アレ」する方法をPythonとJSで比べてみた(JavaScript Weeklyより)

これのRuby版があってもいいのかも?


つっつきボイス:「PythonのアレはJavaScriptでどう書くんだっけ?のチートシート」「そういえばPHPのあの関数はRubyではどう書くかみたいなのはよく使ってたし」

CSS/HTML/フロントエンド/テスト

jxck.ioの「次世代 Web カンファレンス 2019」


つっつきボイス:「あのjxck.ioの中の人が、ちょっとコワモテのWebカンファレンスを来年開催するそうです」「会場は法政大学か」「発言は個人としてのみを前提」「お金は扱わないと」「事前の仕込みはなしで、純粋に討論だけでやるのね」「こういう話がしたいんだろうな〜ワカル😊: W3CとかWHATWGはあまりこういう感じでディスカッションとかしなさそうだし」「パネラーも錚々たるメンバー: お、知ってる人もいる」「研究系のカンファレンスに近いかな」「これはかなり面白そう: 話についていくのは中々大変だと思うけど😎」

ドワンゴの「Webフロントエンド パフォーマンス改善ハンドブック」


つっつきボイス:「そうそう、こういうパフォーマンス改善の常識ってどんどん大きく変わっていくんですよね〜Chromeとかの最適化なんかで変わってきたりとか」「個別の要素には普遍的なものも多いんですけど、具体的な手順なんかが変わったりする: 昔はこれこれの項目をチェックしなければいけなかったけど今はJSのJITが効いて高速化したのでスルーされたりとか」「移り変わり激しい🏎」「このハンドブックは新しいのでそのあたり追従してる感じですね」

その他CSS/HTML/フロントエンド/テスト


つっつきボイス:「社内Slackで投下していただいたヤツです」「いつの間にかシリーズ化してるし」「わかばちゃんつぇ〜🌱」

言語よろずの間

Phusion PassengerがC++からGoへの移行を表明


つっつきボイス:「へぇー、PassengerがGolangに行くのか」「Go言語はミドルウェアに向いているし、最低限のコンテナとして動かすにはとても向いていると思うので、C++で頑張るよりはいいんじゃないかな😋」「私もそう思います😊」

その他

Twitterのタイムライン


つっつきボイス:「お、いつの間に」「私も早速オフにしました📉」

番外

「世界を変えた書物」展

展示は残念ながら昨日24日で終了ですが、私は家族で見に行っちゃいました😋。


つっつきボイス:「展示が無料だったというのが主な理由で😆」「活版印刷前のはあった?」「さすがに印刷機登場以後でした: 時代が新しくなるに連れて印刷がどんどん精密になっていてスゴイなとも思ったし、昔は本を出版するのってめちゃめちゃ金がかかったんだろうなというのが想像つきました」「装丁とか挿絵とか図とかね😊」「作者自ら銅版画に鉄筆で図を描いたりとか苦労が偲ばれました」

数学ニュース2つ

ここ数日話題になってます。ABC予想について望月新一教授が2012年に発表した証明に修復不能なギャップが見つかったというニュース(望月教授は現在反論中)と、89歳の英国数学者Michale Atiyah教授がリーマン予想を証明したと主張しているという記事です。

しかし早速続報が↓。


今回は以上です。

バックナンバー(2018年度後半)

週刊Railsウォッチ(20180918)ビューテンプレート探索が高速化、mini_scheduler gem、レガシコントローラのリファクタリングほか

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

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

Rails公式ニュース

Ruby Weekly

Postgres Weekly

postgres_weekly_banner

JavaScript Weekly

javascriptweekly_logo_captured

デザインも頼めるシステム開発会社をお探しなら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探訪シリーズ