週刊Railsウォッチ(20190121)Rails 6.0.0 beta1リリース、Railsは2019年も「あり」か、Jetsでサーバーレス、ES2018の新機能、RSpecの心ほか

こんにちは、hachi8833です。Slackのアイコンやら色合いやらが微妙に変わって社内がざわついていました。


つっつきボイス:「Slackのデザイン変更、はてブでもざわついてましたね😅」「このデフォルトアバター↓変えたくてしゃーないんですが、Slackのadminでも変えられないっぽい😢」「この英語圏っぽさ…か、可愛くない😆」

「キャラクターの可愛さに対する感覚って、アジアの中でも違ったりするけど、これは少なくとも日本的ではないなー」「越えられない壁🗻」「そう思うとGitHubのOctocat(本当はMonalisa)は日本的ではないけど大当たりですね: そこまで深く考えずにデザイン発注したらしいと何かで見た気がしますが」「キャラクターはつくづく水物🛶」

後で調べたらこの方↓が生みの親でした。

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話の再構成です👄
  • 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください

臨時ニュース: Rails 6.0.0 beta1がリリース(Rails公式ニュースより)

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

最近のコミットではAction Cable、特にテストとガイドの改修が目立ちました。

RelationのwhereでRuby 2.6の(1..) rangeをサポート

# activerecord/test/cases/arel/attributes/attribute_test.rb#L642
+       if Gem::Version.new("2.6.0") <= Gem::Version.new(RUBY_VERSION)
+         it "can be constructed with a range implicitly ending at Infinity" do
+           attribute = Attribute.new nil, nil
+           node = attribute.between(eval("0..")) # Use eval for compatibility with Ruby < 2.6 parser
+
+           node.must_equal Nodes::GreaterThanOrEqual.new(
+             attribute,
+             Nodes::Casted.new(0, attribute)
+           )
+         end
+       end

つっつきボイス:「おーRuby 2.6のinfiniteサポート😍」「これもRails 6で入るみたいですね」「Rails 6がRuby 2.6をサポートするようになった一環なんだろな」

参考: Feature #12912: An endless range `(1..)` - Ruby trunk - Ruby Issue Tracking System

relation.where(column: (1..))って、ぱっと見..の後ろを書き忘れたみたいに見えちゃいます😅: 慣れてないだけですが」「whereにはこうやって書けるみたいだけど、正直なところ、これを普通のrangeで使う機会はあまりなさそう&あまり使いたくないかなー😆」「ちょっとためらいます😅」「ただ言語表現として書けることについてはまあいいかなとも思いますし、この改修もそのぐらいの意図なのかなと」

1..って、むしろコードゴルフで少しでも短く書きたいとか、ぱっと見そう見えない無限ループを簡単に作っていたずらするとか、そういう方面をいろいろ考えちゃう😆」「わかりみ〜😆」「RubyKaigiで@mametterさんが主催してたTRICK 2018↓みたいな場面で使えそうだし」

その後

#34906の続きが入りました↓。

WebワーカーでAction Cableを使ったときのReferenceErrorを回避した

# actioncable/app/assets/javascripts/action_cable.js
(function(global, factory) {
  typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : factory(global.ActionCable = {});
})(this, function(exports) {
  "use strict";
  var adapters = {
-   logger: window.console,
-   WebSocket: window.WebSocket
+   logger: self.console,
+   WebSocket: self.WebSocket
  };

つっつきボイス:「Webワーカーがwindowdocumentにアクセスしようとするとエラーになってたそうです」「それはウィンドウがないからですね」「あ、そういうことか😳」

「Action Cable使ってたらWebワーカーでwindowdocumentにアクセスするのはまったく普通だから、とっくに誰かが踏んでいてもおかしくないし、こういう基本的なエラーが今になって修正されてるということは、Action Cableってまだあまり使われてないのかな?🤔」「最近Action Cableの改修が多いのは、6.0ではもっと使ってもらおうみたいな流れなのかな?」「これは単に地雷を踏んだ人が改修したんではないかと😆」

ガイドの「Decoratorパターン」を既存クラスのオーバーライドに変更

# guides/source/engines.md#L1091
### Overriding Models and Controllers
Engine model and controller classes can be extended by open classing them in the
main Rails application (since model and controller classes are just Ruby classes
that inherit Rails specific functionality). Open classing an Engine class
-redefines it for use in the main application. This is usually implemented by
-using the decorator pattern.
+redefines it for use in the main application.

For simple class modifications, use `Class#class_eval`. For complex class
modifications, consider using `ActiveSupport::Concern`.

-#### A note on Decorators and Loading Code
+#### A note on Overriding and Loading Code

-Because these decorators are not referenced by your Rails application itself,
-Rails' autoloading system will not kick in and load your decorators. This means
+Because these overrides are not referenced by your Rails application itself,
+Rails' autoloading system will not kick in and load your overrides. This means
that you need to require them yourself.

つっつきボイス:「ガイドの修正ですが、Decoratorパターンは適切ではないということでオーバーライドに改めたようです」「自分はDecoratorキライだからまあどっちでもいいけど😆」「そうでしたね😆」

参考: Decorator パターン - Wikipedia

「しかしoverrideというのもどうなんだろう?🤔: これでコミッターのコンセンサスを取れたのがちょっと不思議ではある」「これはこれで微妙なんでしょうか?」「お、コミットメッセージ↓にこう書いてあるし: それならDecoratorじゃないというのはワカル」

現行のエンジンガイドでは、Overriding Models and ControllersセクションでDecoratorパターンを参照しているが、Decoratorパターンは既存クラスをreopenするものではなく、既存オブジェクトのインスタンスに機能を追加するもの(RubyではよくDelegatorで実装されるヤツ)なので、自分には適切でないように思える。
同コミットより抜粋・大意

「Decoratorの図↓にもあるように、通常のGoFのDecoratorパターンではコンポジットを使うので、delegate的に書くのが本来のあり方と言える」「あー」「Rubyならこの辺はどうにでも書けますけどね☺️」


Wikipediaより

「そしてガイドのコードはクラスをreopenしているから、その意味では確かにDecoratorパターンではない」「なるほど!😃」「Decoratorパターンではないのは確かだけど、代わりにoverrides/というディレクトリ↓を作るのは自分的にどうも引っかかるな〜😅」「services/とかforms/みたいなディレクトリですね😆」「とはいえ、何かディレクトリを作ってカスタマイズできるよというサンプルは何らかの形でガイドにある方がいいですね: 自分もガイドでそういう書き方を参考にしたことがあるし」

-# MyApp/app/decorators/models/blorgh/article_decorator.rb
+# MyApp/app/overrides/models/blorgh/article_override.rb

「といってservices/をサンプルに使うとそれはそれで議論になりそうだから、サンプルにするならforms/あたりがいいんじゃないかと」「フォームなら利用頻度も高いですし😋」

Active Recordからいろいろと削除


つっつきボイス:「3つともkamipoさんのコミットでした」「1つ目と3つ目はprevent_writesattr_accessorからattr_readerに移したと: 書き込み可能で公開すべきではないからということですね」「2つ目は単なるリファクタリングか」

# activerecord/lib/active_record/connection_adapters/abstract_adapter.rb#L83
-     attr_accessor :pool, :prevent_writes
-     attr_reader :schema_cache, :visitor, :owner, :logger, :prepared_statements, :lock
+     attr_accessor :pool
+     attr_reader :schema_cache, :visitor, :owner, :logger, :lock, :prepared_statements, :prevent_writes
      alias :in_use? :owner

rake app:updateでActive Storageが更新されないのを修正

# railties/lib/rails/generators/rails/app/app_generator.rb#L309
+     def update_active_storage
+       unless skip_active_storage?
+         rails_command "active_storage:update"
+       end
+     end
+     remove_task :update_active_storage

つっつきボイス:「ちょうどさっき社内でrake app:updateの話をしてたところだった」「重箱の隅ですが、今どきのRailsならrakeじゃなくてrailsじゃないかと😆」「そこ気になってました😆」「まだまだrake使ってるんだよねみんな☺️: 自分も使ってるし」「私はrailsでやってます✨」「rakerailsは今はほぼ同じだけど、微妙に違ってる部分もあるのが面倒😓」

[Rails 5] rakeタスクがrailsコマンドでもできるようになった

「ところでapp:updateってどのぐらい使われてるんだろうか?」「オレオレRailsアプリでときどき使ってみたことあります: 思ったより書き換えが多くて、特にイニシャライザのコードが多めに書き換えられたのでちょっとビビりました」「Rails wayで書いている限りそんなにおかしなことにはならないとは思うけど、書き換えが広範囲に渡るから差分を見るのが憂鬱になりそうではある😥」「1項目ずつ尋ねられるから、変更内容をその都度吟味すれば大丈夫だと思います」

データベースを変更するコマンドを追加

データベースを変更するrails db:system:changeコマンドを追加

bin/rails db:system:change --to=postgresql
   force  config/database.yml
    gsub  Gemfile

このコマンドは現行アプリの対象データベースアダプタをconfig/database.ymlテンプレートのコピーで置き換え、現行のデータベース用のgemを対象データベース用のgemで置き換える。

Gannon McGibbon
同コミットより大意


つっつきボイス:「rails db:system:changeというコマンドが追加されて、--to=postgresqlみたいにデータベースを切り替えられるようになったそうです」「ほんとだ--to=postgresql…ってそんなことやらねーし🤣」「誰得🤣」「まあ開発のごく初期段階とかならあるのかもしれないけど」

「こういうデータベース切り替えがすんなりいくとは思えないし、無理にRails本体で頑張らなくてもgemの形で導入すればいいんじゃね?って思うし」「ですね」「こういう機能がなまじ公式にサポートされていると、『Railsはデータベースを簡単に切り替えられるよ❤️』と勘違いされて乱用されたりしそうだし」「そっちの方が副作用大きそうですね」「新しい機能というだけで使いたがる人もいたりするし、その意味でもgemでやる方がよさそうに思えるけどなー🧐」

Rails

Railsは2019年も「あり」か(Hacklinesより)


つっつきボイス:「英語タイトルは煽る気満々ですが」「何つう😆」「辞書的にはdon’t give a fuckは基本的に否定形で使われる俗な言い回しで『どうでもいい』『知ったこっちゃない』みたいな意味ですね」

「Railsは死んだとか終わったみたいな話はもう今に始まったことじゃないし😆」「Rails終わった説もまったく根拠がないわけではないとか、いろいろデータを引用しながらそのあたりを冷静に分析してる感じでした」「やっぱり何も指標がないよりはあった方がいいですし☺️」

「記事では、Railsの強みは短期開発、ビジネスロジックの実装しやすさ、豊富なライブラリで、向いているのは普通のWebとかEコマース、CMS、コンセプトが流動的なアプリ、プロトタイピングというあたりだそうです」「一度はメジャーに近づいたところもRailsのいい点かも🥰」「Railsに弱みがあるとすればパフォーマンスやスケーリングや柔軟性、用途によってはオーバーキルとか、Rubyが機械学習方面にまだ明るくないとか、だそうです」「自分も誰かに『Railsってどうなんですか?』って聞かれたらだいたいこういう感じで答えるかなー☺️」

「記事ではRubyの代替としてとりあえずSinatraとHanamiとServerless Rubyが挙げられてますね」「個人的には、SinatraやHanamiだとあまり変わり映えしないし、RailsからSinatraやHanamiに乗り換えるぐらいならRailsのままでいいかなと思うし」「記事でも、用途を選べばRailsは十分『あり』という結論ですね」

「Railsから乗り換えるとしたらServerless Rubyの方が可能性が開けていそうな気がする: Rackのない環境にはそれなりに惹かれるものがあるし、Serverless RubyはRailsでは代替できないので」「ActiveRecordはServerless Rubyで欲しいですか?」「でかいライブラリはサーバーレスだと使いづらいので、ActiveRecordはなくてもいいかな😆」

「思ったよりずっとまともな記事だった👍」「タイトルの煽り以外は😃」「これ翻訳したらPV取れそう😋」「翻訳しよっかな😋」

Redditに落ちてたテストコードを改善してみた(Hacklinesより)


つっつきボイス:「誰かさんがRedditで『こんなテスト書いたんだけど合ってる?』って質問してて、それに答えた記事だそうです」「『オレならこう書くぜ!』みたいな☺️」

RSpecが推す書き方とは

# 同記事より(以下同文)
it "must be valid" do
  value(user).must_be :valid?
end

「まず上のコード例↑があって、記事の人はこれで悪くはないけど自分ならcontext使ってこう書く↓と言ってる」

context "fresh instance" do
  it "is valid" do
    expect(user).to be_valid
  end
end

「そしてsubject使うとさらにいい感じになるとも言ってる↓」

subject { FactoryBot.build(:user) }

context "fresh instance" do
  it { should be_valid }
end

「こうやってsubjectを使って書く↑やり方は、(好みを別にすれば)とてもRSpecらしい書き方ですね: RSpecの典型的な見本とも言える」「というと?」「ポイントは、it {}の中にshould be_validだけを書いていること」「あー、つまりRSpecはit {}の中にそれだけ書けば済むことを目指してるんですね?」「まあそういうことです☺️」

「RSpec的には、it {}の中を極力シンプルにしたい、そのためにsubject { FactoryBot.build(:user) }を事前に書いて下準備している」「subjectってそういう意図だったんだ…RSpecの心をわかってなかった💔」

「心情的にはこちらの記事↓と同じく『実はminitestでいいんじゃね?派』ですが😆」「気持ちわかりみです😆」「まあRSpecはDRYに書きたくなるところがありますが」

RSpecえかきうた

「Email uniquenessのこの書き換え↓もいいですね〜: と言いつつ書き換え前のでも全然いいんじゃね?とも思うけど😆」「書き換え前のはベタだけど、やってることは自分にもどうやらわかります」「つかテストはやってることがわかることが肝心だし: テストのリファクタリングに時間かけるぐらいなら😆」

context "with an duplicated email" do
  it "is not valid" do
    user.save
    user2 = FactoryBot.build :user
    user2.wont_be :valid?
    user2.errors.count.must_equal 1
    user2.errors[:email].must_equal ["has already been taken"]
  end
end

↓

context "when email is not unique" do
  let!(:other_user) { FactoryBot.create(:user, email: subject.email) }

  it "is not valid" do
    expect(subject.errors[:email]).to eq(["has already been taken"])
  end
end

「なかなかいい記事👍」「RSpec強者からのお言葉でした👑」

データベース制約追加時には「multiple migration」戦略を使おう(Hacklinesより)

TechRachoの翻訳記事↓でもよくお世話になってるAndy Crollさんの記事です。

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

# 同記事より
class AddComposerToSongs < ActiveRecord::Migration[5.2]
  def change
    add_column :songs, :composer, :string, default: "Lin-Manuel Miranda", null: false
  end
end

つっつきボイス:「ほむほむ、これはマイグレーションでのデータベースがロックされる時間をなるべく短くしようという話みたい」「というと?」

「上のコード例みたいに、マイグレーションでadd_columnする段階でdefault: "Lin-Manuel Miranda"みたいにデフォルト値も設定すると、たとえばそのテーブルに1万行あればそのカラムに1万個のデフォルト値が書き込まれるので、それが完了するまでデータベースがロックされてしまいます」「あー🤭」「つまりマイグレーションがそれだけ重くなる🏋🏻‍♀️」

「修正後のマイグレーションでは、まずadd_column :songs, :composer, :stringだけを実行する: これならカラムの値はnullになるので一瞬で完了する」「ふむふむ」

「それが終わってから、set_default_composerみたいなデフォルト値設定用のフック↓を一時的に作っておいて、rakeタスクとかでSong.where(composer: nil).update_all(composer: "Lin-Manuel Miranda")を手動で実行することでカラムに値を入れる」

# 同記事より
class Song < ApplicationRecord
  before_save :set_default_composer

  def set_default_composer
    self.composer = "Lin-Manuel Miranda" if composer.nil?
  end
end

「カラムのアップデート後が終わった後に、change_columnで制約をつければ書き込みが発生しないのですぐ終わる」「あとはフックを消せば完了🏁」「なるほどー😃」

「長時間ロックされそうなマイグレーションは、こうやって分割すれば原理的にはロック時間を短縮できる、はず」「実際にこのとおりにやるかどうかは別にしても、ものすごく巨大なテーブルを扱うときにはこうした点を常に意識する必要がありますね🧐」「でないとサービスが長時間停止してしまいかねない…😇」

rails_async_migrations: マイグレーションで非同期をサポート

# 同リポジトリより
class Test < ActiveRecord::Migration[5.2]
  turn_async

  def change
    # data update logic you would put into a worker here
  end
end

つっつきボイス:「たまたまマイグレーションねたが続きました」「確かにマイグレーションは時間がかかるから、非同期に実行できればそれに越したことはないけど🤔」「この図↓の右は普通のマイグレーションでしょうか?」「左はsidekiqで動いていて右は通常のマイグレーションということでしょうね」


同リポジトリより

「うーん、やりたいことはわかるけど、ニーズがどのぐらいあるのかよくわかんない😆」「★もそんなにないですね」「こういうgemが必要になるようなユースケースがまったくないわけではなさそうだけど、よほどバカでかいテーブル使ってるfatなRailsアプリとか?」「無理に一般化するより個別にやる方がいいのかな🤔」「このgemがあってうれしいという状況が思いつかないなー: あって逆につらいとかはありそうだけど😆」

Action TextがRails 5.2でも動いたお(Ruby Weeklyより)


つっつきボイス:「Action TextがRails 5.2でも動いたそうです」「gemになってるからやれそうではあるけど、Action Textの元になった例のエディタ使えば…って何って名前だっけ?」「やべ、ど忘れした」「Trix!」

全然関係ありませんが、TRIXというフュージョンバンドのコピーを数年前手伝ったことがあります。そっち方面に疎いので曲名も思い出せません😅。

スクラムガイドから削除された5項目(Hacklinesより)


scrum.orgより


つっつきボイス:「スクラムのガイドが毎年更新されてるって初めて知りました」「スクラムは団体がちゃんと仕様を策定していますし、いわゆる認定スクラムマスターの資格もPMP並にしっかり整備されていて認定基準も明確なので、勝手にスクラムマスターとか名乗れないようになってますね」「おー!」「アジャイルという言葉は人によって捉え方がまちまちですが、そういうわけでスクラムという言葉はとてもしっかり定義されていて、ちゃんとやるととても厳しい: だから自分はスクラム不得意〜🤣」「🤣」

参考: スクラム (ソフトウェア開発) - Wikipedia
参考: 認定スクラムマスター研修とは? - Qiita
参考: PMP - Wikipedia

今度は「Active Deployment」が欲しい(Ruby Weeklyより)


つっつきボイス:「お、ちょうど先週のウォッチで『CapistranoがRailsに組み込まれてもいいんじゃね?』っと話しましたね」「そうでした!」「記事でもまさにCapistranoの話してるし: Railsに標準のデプロイ方法があればいいのにという趣旨、自分もわかりみ😍」

「確かに何らかのデプロイ層を標準で定めるというのはありかも?: 今のRailsだと、デプロイ方法が死ぬほどあるとまではいかなくても3種類ぐらいはある感じなので」「うんうん」「コードのみをデプロイする方式とか(sshでもいいしsshじゃなくてもいいけど)、Dockerみたいにできあがったコンテナをガバっと置き換える方式とか、Herokuのようにマネージドなデプロイシステムに乗る方式とか、そのあたりかな🤔」「なるほど!」「HerokuはどちらかというとDockerに近いかも」

「Railsがメジャーになるに連れて、インフラができないアプリエンジニアも増えてきましたし😆」「😆」「それまである程度Web開発の経験があった人ならデプロイもある程度勘が働くと思いますが、インフラを知らないエンジニアだけでアプリを作ってしまうと、二度と同じアプリを作れなくなってしまったりすることもありますし😅」

「てなことを考えると、Active Deploymentみたいなのはあってもよさそうだし、つかCapistranoをまるっと取り込んじゃえばいいのに😆」「私も腑に落ちます」

その他Rails

つっつきボイス:「Railsの公式APIドキュメントサイトのhttps://api.rubyonrails.org/で、ディレクトリ名を/v4.2.11/みたいに指定すると、過去バージョンのAPIドキュメントを表示できることに気づきました: 近々簡単な記事を公開します」「なるほど、でも自分はやっぱり複数バージョンを串刺し検索できるhttps://apidock.com/rails)↓が使いたいんだよ〜😭: どうしてRails 4.2.7で更新停止しちゃったんだろう」「やっぱりそうですよね😅」


apidock.comより


Ruby

JetsとRubyでAWS Rekognition動かすサーバーレスなSlackコマンド作った(RubyFlowより)


同記事より

# 同記事より
class ScrapeImagesController < ApplicationController

  def scrape
    render json: { # Slackに即座に応答する
      response_type: 'ephemeral',
      text: "Slackコマンドのデプロイ完了!"
    }
  end

end

つっつきボイス:「今が旬のサーバーレス🥕: 以前のウォッチでも取り上げたJets↓を使い始める人が出てきたのか」「ですね😋」「JetsならAWSで手軽にさわれるし、記事もまさにそういう感じだし✈️」

「AWS Rekognitionって認識サービスか何かでしょうか?」「知らんかったけど、どうやらそうみたい↓」

「ちょっと使ってみたい気がする😍: ちょうど今日のチーム内発表でもSlackとの連携にGAS(Google Apps Script)↓を使ってましたが、自分ならJetsを試したかも」「😍」「JetsはAWSにデプロイするところまでカバーしてたと思うし、筋は悪くなさそうだし」

「そういえば私も2年前ぐらいにGASとかGCP↓で遊んでみたことがあったんですが、当時はまだツールがPython2だったりと少し混乱気味だった印象でした: 最近やっとPython3になってだいぶ整理されたようです😋」「たしかGoogleにはPythonの偉い人がいるから中々上げられなかったのかも?」

参考: GCP と G Suite を含む Google Cloud - 無料トライアル  |  Google Cloud

「AWSは最初がちょっとめんどくさいんですよね😆」「GCPも違う意味で最初面倒だった印象😆」「でもGCPはボタンひとつでプロジェクトを作ったりできるじゃないですか: AWSは小さなサービスをいろいろ組み合わせて作らないといけないので、Lambdaを書いただけでは動くようにならないという😅」「あー」「API Gateway↓とつないだりとか、いろいろしないといけない🧐」

参考: Amazon API Gateway(API を簡単に作成・管理) | AWS

「GASって確かGCPよりも前からあったんですよね: だもんで元々お手軽ではある😋」「私がGCPで遊んでたのはちょうどそれらが統合されようとしている最中だったので、サービス名が変わったりドキュメントが追いついてなかったりとかがつらかった覚えが😅」

追記(2019/01/24)

情報ありがとうございます!🙇。

Ruby 2.6.0p0のNet::Protocolのセキュリティ問題 — 修正済み(Ruby Weeklyより)

# 同記事より
PAYLOAD_SIZE = 8_301_500
data = 'a' * PAYLOAD_SIZE + '···'

client = Api.new
client.get
client.add(data)
client.del(data)
puts client.get #=> ["aaaaaaaaaaaa...\xC2\xB7\xC2\xB7\xC2\xB7"]

つっつきボイス:「ざっとしか見てないけど、uncompleted payloadの周りの処理に問題があるらしき: 指摘さえしてもらえればRuby側で対応できそうな問題かな」「お、既に修正コミット↓が出てると最後に書いてありますね」「パッチモンスターことnobuさんがやってくれた😍」「Ruby 2.6.1で反映されるんですね👏」

参考: Fix Net::Protocol::BufferedIO#write when sending large multi-byte string · ruby/ruby@1680a13

pipe_operator: RubyでUnixのパイプ操作を実証してみた(Ruby Weeklyより)

# 同リポジトリより
"https://api.github.com/repos/ruby/ruby".pipe do
  URI.parse
  Net::HTTP.get
  JSON.parse.fetch("stargazers_count")
  yield_self { |n| "Ruby has #{n} stars" }
  Kernel.puts
end
#=> Ruby has 15120 stars
-9.pipe { abs; Math.sqrt; to_i } #=> 3

# Method chaining is supported:
-9.pipe { abs; Math.sqrt.to_i.to_s } #=> "3"
sqrt = Math.pipe.sqrt #=> #<PipeOperator::Closure:0x00007fc1172ed558@pipe_operator/closure.rb:18>
sqrt.call(9)          #=> 3.0
sqrt.call(64)         #=> 8.0

[9, 64].map(&Math.pipe.sqrt)           #=> [3.0, 8.0]
[9, 64].map(&Math.pipe.sqrt.to_i.to_s) #=> ["3", "8"]

つっつきボイス:「ElixirやUnix風のパイプをRubyで実証したかったようです🚬」「関数型勢が好きそう☺️: しかし遅延評価とかやってそうな雰囲気だし、ぱっと見UnixというよりはElixir的に見えるけどな〜: Elixir知らないけど😆」「やっぱそう思いますよね? Unix風というからには|でしょうけど、Rubyでその記号でつなぐわけにはいかなさそうだし😆」「PROOF OF CONCEPTと書いてあるから、実用というよりはアイデアの実証なんでしょうね☺️」

参考: パイプライン演算子 · Elixir School

Elixirでは|>だそうです。

solargraph: RubyのLanguage Server(Ruby Weeklyより)



solargraph.orgより


つっつきボイス:「お、RubyのLanguage Serverじゃないですか🥰」「このSolargraphって初めて見ましたが新しい割に★500超えてますね」「数年前にRubyKaigi↓でLanguage Serverが盛り上がってた気が」「そうでした!あのときのとはまた別物みたいですね」

参考: Ruby Language Server - RubyKaigi 2017

「やっぱりLanguage Serverがあるといい😋」「エディタでLintをかけるときとかに使うヤツですね😋」

参考: lint - Wikipedia

「JetBrainsはLanguage Serverを喜びそう」「あ、JetBrainsは確かUpsourceというチーム系プロダクトでそういうの持ってますよ🧐」「え、知らなかった😳」「Upsourceならコードジャンプも含めてほぼIDEと同じことできるので強力😎」「へー!」「なのでおそらく実質Language Serverと同じものを持ってるはず: LSPとかでAPI公開まではしてなかったと思いますが」

参考: Upsource: Code Review, Project Analytics, and Team Collaboration by JetBrains

参考: IDE上でコードレビュー完結!Upsourceを使ってみる - Qiita

「みんなLanguage Serverでやれれば理想ですね」「エディタごとに独自対応する苦労がなくなるのはいいこと😙」

ついでにLanguage Serverの情報がまとまってるサイトも見つけました↓。


langserver.orgより

GemfileなしでBundlerが使える話(Ruby Weeklyより)

短い記事なので引用はしません。


つっつきボイス:「Gemfileなしでもgemfile do endブロックでBundlerが使えるらしいです」「あれ?こういうのちょっと前にも見たことがある気がするナ🤔」「そういえば既視感ある…ウォッチで扱ったかな🤔」

ありました↓。「Rails OOP上級編」です。

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

Bundler 2の続報


bundler.ioより


つっつきボイス:「例のBundler 2に続報が出てました」「お、Bundler 2にはv1とv2を自動的に切り替える機能があるけど、それでつまずく可能性があるのか😨: でもGemfile.lockファイルのBUNDLED WITHで指定されているバージョンを指定してbundlerをインストールすれば回避できると」「知らないとハマりそうですね😭」「たしかすごく古いBundler使ってた頃はBUNDLED WITHがなかったと思う」

Can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)

その他Ruby


つっつきボイス:(○×※●…)「これはやさしすぎ😆」「やっぱり😆」



つっつきボイス:「上は何と比べて遅いんだろか?🤔」「どれどれ…あ、PHPerKaigi↓か」

「PHPの人たちが自分たちでペチパーって呼んでるとは知らなかったー」「PHPerKaigiはいかにも日本国内っぽいので、海外事情を考えなくていい分締切は遅いんでしょうね☺️: 国際的なカンファレンスの締切は早いのが普通」

Ruby trunkより

提案: ブロックなしのProc.newでwarningを表示しないで欲しい場合がある

# 同issueより
def foo bar = Proc.new
  bar.call
end

foo      { p "block" } # warn
foo ->() { p "block" } # no warn

つっつきボイス:「tenderloveさんからのissueで、この書き方がRailsでそこそこ使われているらしいのでwarningを出さないで欲しいそうです」「こんなwarningを出す機構がRubyにあったとはー😳」「->()だと出ないんですね」

「ついでにko1さんが、こんな変な書き方↓を見つけたと書き込んでました」「うひょー、ここでlocal_variable_getするか普通😆、キモい、キモすぎる🥶」「う、わかんない😅」「引数の:bはこの瞬間にどう評価されるんだろうか…謎すぎる」「実装に依存するって書いてますね」「これはそうでしょうね: JRubyとかでどう変わるかわかったもんじゃないし」

# 同issueより
def foo o = binding.local_variable_get(:b), &b
  p o.class
end

foo{} #=> Proc

参考: instance method Binding#local_variable_get (Ruby 2.6.0)

引数 symbol で指定した名前のローカル変数に設定された値を返します。
docs.ruby-lang.orgより

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

AWS Lambdaでカオスを注入(Serverless Statusより)

コードはPythonですが。


つっつきボイス:「記事にあるLambda Layerって何でしょうか?」「Lambda Layerは最近のAWSに入ってきた機能のひとつで、たとえばDockerのOverlayFSみたいに、環境Aと環境Bと環境Cのレイヤをかぶせてひとつの環境にするみたいなことができるものですね」「なるほど!」

参考: 新機能 – AWS Lambda :あらゆるプログラム言語への対応と一般的なコンポーネントの共有 | Amazon Web Services ブログ
参考: Overlayfs - ArchWiki

「SSMというのも初めて見ました😅」「SSMはたしか、Lambda系の機能を簡単に使えるようにするもので、SSMパラメータストアからLambdaで環境的な値を取ってこれるみたいなヤツ」「AWS System Managerの略語がなぜかSSMなんですね…」

参考: AWS Lambda functionと EC2 Run Commandで、かんたんSlash Commandデプロイ - Qiita
参考: LambdaでAWS Systems Manager パラメータストア(KMS暗号化)を利用する際に注意すべき性能について | Skyarch Broadcasting

「で、記事はLambda Layerを使ってカオスライブラリを注入する方法を丁寧に説明していますね: なかなかいい記事👍」「カオスって前に教えていただいたカオスエンジニアリング↓的なものでしょうか?」「ちゃんと読んでませんが、上の記事のはNetflixがやってるようなカオスエンジニアリングとはまた違うっぽい: Lambdaのレイテンシをランダムに変えるレイヤライブラリ程度のものかなと」「あ、そうでしたか💦: ちらっとchaos engineeringという言葉が見えたんですが、よく見たら以下の記事にインスパイヤされたという記述でした😅」

参考: Netflix 驚異的なトラブル対応 カオスエンジニアリングとは、何か?

参考: Applying principles of chaos engineering to AWS Lambda with latency injection

GCP Cloud FunctionsでGo 1.11がサポート


つっつきボイス:「Go言語ってもう1.11なんだ」「ですね: 目玉はGoでWebAssemblyバイナリを吐けるようになったことですが、まだどう使おうかみんな迷ってる雰囲気です」

mrubyをWebAssemblyで動かす(翻訳)

「GCPのCloud Functionsが今までNode.jsとPythonだけだったのが意外でした」「そうそう、GCPのはまだ対応言語が少なかった: AWS Lambdaの方はこの間対応言語が一気に増えましたし🏋🏻‍♀️」「Cloud Functionsも尻に火がついた感じですね😆: ちょっと前の記事ですが、そのあたりの現状がまとまってました↓」「記事ではLambdaのPHPとか未対応になってたけど、今じゃPHPもSwiftも含めてLambdaで動かない言語はほぼないし😆: DockerはさすがにLambdaじゃ動かせないかなー」

参考: 各Cloud Functions で使える言語比較(2018年7月) - Qiita

「お、よく見るとIBMのCloud Functionsも強い💪」「ほんとだ、去年半ばの時点でたいてい網羅してるし😳」「IBMはSwiftのコンパイラも持ってるってことか: さすがIBMパワー🔵」



ibm.comより

その他クラウド


つっつきボイス:「これねー、ちょっとよくない流れかなー😢」「ですね、しかもあのRedisがやってるというのが😢」「Redisはしょっちゅう使ってるから下手すると巻き込まれそう: MongoDBとかは個人的にどうでもいいけど😆」「😆」「もしかするとMySQLとMariaDBのときみたいに分裂するかも?」「あー」「商用に使われたくないみたいな気持ちはわかるんだけど、過去にそうやって優秀なソフトウェアが分裂することがちょくちょくあったので💔」

「PassengerとかGitLabみたいに、EnterpriseエディションとCommunityエディションを分けるぐらいならいいけど、Redisには名前変わって欲しくないなー」「同意です」「オープンソースを商売として軌道に乗せるのはいろいろ難しい…」

SQL

Dejavu: ElasticsearchのWeb UI(DB Weeklyより)


opensource.appbase.io/dejavuより


つっつきボイス:「もしかしてよくあるやつでしょうか?」「ElasticsearchのWeb UIはまあいっぱいありますが、このDejavuはネイティブなElasticsearchにクエリを投げるっぽいかな: 悪くなさそうに見えるのでちょっと動かしてみたい気はしますね😋」「😃」

JavaScript

知っておきたいES2018の新機能(JavaScript Weeklyより)

// 同記事より
const arr1 = [10, 20, 30];

// make a copy of arr1
const copy = [...arr1];

console.log(copy);    // → [10, 20, 30]

const arr2 = [40, 50];

// merge arr2 with arr1
const merge = [...arr1, ...arr2];

console.log(merge);    // → [10, 20, 30, 40, 50]

つっつきボイス:「ES2018は知らないことだらけ」「ドット3つの...↑なんてのがあるのか!ドット2つ..は前からあった気がするけど」

参考: 「…」←これ、ただの省略記号かと思ってました。(Spread operatorのお話)|もっこりJavaScript|ANALOGIC(アナロジック)
参考: JavaScriptで123.toString()はエラーになるけど、123..toString()は正常に動作する。これってトリビアの種になりませんか? (JavaScript おれおれ Advent Calendar 2011 – 12日目) | Ginpen.com

「そういえばこういうenumerable↓なんてのもあったけど、こういうPrototypeの根っこのあたりはできるだけ触らないようにしてたからなー」「怖そう😨」「よく理解しないうちに使って地雷を踏みたくないし💣」

// 同記事より
const car = {
  color: 'blue'
};

const car2 = Object.create(car, {
  type: {
    value: 'coupe',
    enumerable: true,
  }
});

console.log(car2.color);                      // → blue
console.log(car2.hasOwnProperty('color'));    // → false

console.log(car2.type);                       // → coupe
console.log(car2.hasOwnProperty('type'));     // → true

console.log({...car2});                       // → {type: "coupe"}

「Asynchronous Iterationなんてのも😳」「なるほど、こう動くと↓」「このarr[Symbol.iterator]()って記法は何だろう…」「Symbol.iterator自体はES2015からあったのか」「おー」「function * ()とか何が起こるのかもわからん😆」「他のプログラミング言語でできてたことができるようになったんだろうなとは思うけど、見慣れない書式はどうもねー😆」

// 同記事より
const arr = [10, 20, 30];
const iterator = arr[Symbol.iterator]();

console.log(iterator.next());    // → {value: 10, done: false}
console.log(iterator.next());    // → {value: 20, done: false}
console.log(iterator.next());    // → {value: 30, done: false}
console.log(iterator.next());    // → {value: undefined, done: true}

「やや、Promiseにとうとうfinallyが入るし!」「おースゲー😻」「ってことは今までなかったのか😆」「えぇー、そうだったっけ😅」

// 同記事
fetch('https://www.google.com')
  .then((response) => {
    console.log(response.status);
  })
  .catch((error) => { 
    console.log(error);
  })
  .finally(() => { 
    document.querySelector('#spinner').style.display = 'none';
  });

ES2018の正規表現

「おー、ES2018で正規表現も拡張されるし」「何と!正規表現厨としては身を乗り出しちゃいます🥰」「名前付きキャプチャみたいに基本としか思えない機能がやっと入るのね」「何という今さら😆」「後読み(Lookbehind)もやっと人並みになったー😂」「正規表現でUnicodeプロパティも扱えるようになるし」「そうっ!! それもずうっと待ってました😤」

// 同記事より
const re = /\b(?<dup>\w+)\s+\k<dup>\b/;
const match = re.exec('Get that that cat off the table!');        

console.log(match.index);    // → 4
console.log(match[0]);       // → that that

[連載:正規表現] Unicode文字プロパティについて(1)

「いやー今までJSの正規表現はどうも不自由だなって思ってたけどやっぱり正しかった😆」「😆」「6年ぐらい前にいろんな言語の正規表現を調べたんですが、そのときにJSの正規表現は機能が足りなすぎてアカンと思ってずっと避けてました」「まあJSで正規表現バリバリ使う感じじゃなさそうだけど」「何しろJSにはLookbehind自体がなかったし、他の言語と違ってサードパーティのネイティブ正規表現ライブラリも導入できないし、悲しすぎました😭」

JavaScript: Chrome V8なら正規表現で後読み(look behind)がフル機能で使える

「でもこれでJSの正規表現がとうとう『ボクらの知ってる正規表現』になってくれる感🎊」「RubyやPerlやPythonではとっくにできてた機能😆」「長かった、長かったよー😂」

「ということは、正規表現の分JSがデカくなるだろうから、ES2018は組み込みだと苦しくなるかもしれない🤔」「あーありそう」「Unicodeの文字プロパティとかいかにもデカくなりそうだし」

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

「次世代 Web カンファレンス 2019」終了


つっつきボイス:「昨年のウォッチで軽く紹介した、法政大学で行われたWebカンファレンスです」「ああ例の、初心者お断り感が強く漂う、強者による強者のためのWebカンファレンスですね☺️」「勝てる気がしない😆」「ひたすら議論だけしたいみたいなスタンスだったかな」「記事の最後に『次回とか全く考えてない』とありました」「たしか知人も参加してたはず…いたいた🎯」「こういう議論をできる場というのはたしかに欲しくなりますね」

Yet Another REST Client


つっつきボイス:「YARCって、もしやとっくに有名なんでしょうか?」「自分はこのRESTクライアント入れてます↓☺️」「Restlet!、こういうのもあるんですね」「昔また別のクライアント入れてたことあったけど、アップグレードしたら動かなくなった😭」

「ちなみにこういうRESTクライアントは、プロファイルを作ってチームで共有するとデバッグやテストがとってもやりやすくなる😎」「そうそう、そうなんですよ~😂」

「うろ覚えなんですが、このRestletをうまく設定するとライブラリからも読み込めるようになって、GUIで作ったリクエストをテストコードで読み込んでそこからリクエストを投げるなんてことも確かできた」「おぉ〜!」「そうしておけば、テスターの人が自分で組み立てたリクエストをそのままテストコードに読み込ませてテストできるので、人間が行ったテストを繰り返し実行するなんてことが比較的やりやすくなる🥰」「いいこと聞いた😋」「でも所詮リクエスト単位になっちゃうので、シナリオ的な動作には向いてませんが😆」

その他フロントエンド

言語

「低レイヤを知りたい人のためのCコンパイラ作成入門」

その他

Git Explorer: 「gitのあのコマンド何だっけ」を支援


同サイトより


つっつきボイス:「Gitのあのコマンドって何だっけ?を探せるサイトだそうです」「自分だったらRubyMineで検索するかな🤣」「ワイも〜🤣」「RubyMineはいろいろ強いし💪」

住所.jpの住所データベース


同サイトより


つっつきボイス:「このjusyo.jpのデータベースはたまたま見つけたんですが、日本郵便のブチブチにちぎれた郵便番号CSVと違ってちゃんとwell-formedになってて、しかもメンテナンスが継続してるのが、とてもとてもうれしかったので😂」「SQLite3とかのファイルをそのまま置いてくれてるなんて、エラ〜イ👍」「そうそう、日本郵便のKEN_ALL.csvはいろいろ地獄感あってヤバい👿」

「KEN_ALL.csv、最近だと知らない人も多いのかな👴」「昔はよくSQLを初めて学ぶときなんかにサンプルとして使ったりしてましたね」「そしてKEN_ALL.csvはまともにパースできない」「そう!😤、いかにも昔のホストコンピュータっぽい固定フィールド長でした」「はりゃ〜公式データなのにひどい😅」「でも日本の郵便番号システムは、そもそも1つの郵便番号に複数の町村名が割り当てられたりする↓から完全になりようがないし」「そうなんですよ: ひどいよジャイアン😭」

参考: KEN_ALL.CSV (郵便番号検索)の落とし穴 - Qiita

# 同記事より
498-0000 三重県桑名郡木曽岬町, 愛知県弥富市
618-0000 大阪府三島郡島本町, 京都府乙訓郡大山崎町
871-0000 大分県中津市, 福岡県築上郡吉富町

「なのに地名から郵便番号を検索しようとすると今度は情報が足りないという😇」「どうにもならない😇」「jusyo.jpもさすがに日本の住所を隅から隅まで完璧に網羅しているわけではないようです」

「jusyo.jpのSQL化されたデータの何がありがたいって、京都市内の恐ろしく難解な道案内住所表記をちゃんと別フィールドに分けているところ😂😂」

参考: 難解な京都の住所表記。3パターンを抑えればとても分かりやすいです! | テナントプラス営業ブログ

「jusyo.jpはデータも継続的にメンテされてるみたいでそこもうれしいです😂」「でないと意味ありませんしね☺️」

「そういえば銀行コードのデータベース↓も更新割と多いんですよね」「あー!そうかも」「支店が統廃合されたりしたらデータベースに速攻反映しないと『お金おろせないんですけど』とかたちまちクレームが集中するし😇」「実はすっごく大事なデータベース」

参考: 金融機関コード・銀行コード検索

社内自作キーボード愛好家に

その他のその他



つっつきボイス:「これ見た見た😆」「昭和100年のインパクトが😆」「今は昭和94年なのか」「きっと2000年問題の対応が間に合わなかったとかで、内部データをむしろ昭和に切り替えて、表示だけ平成にして切り抜けちゃえみたいな対応だったんだろうなとか😇」「いかにも〜😇」「いろいろしどい😇」

参考: 2000年問題 - Wikipedia

番外

宿題を手伝うAlexa

逆説的ですが、小学校低学年までなら反復練習を促進する意味でむしろありかもと思ってしまいました。

参考: 「アレクサ、5ひく3は?」Amazon Echoが6歳児の宿題を手伝う | ロボスタ


つっつきボイス:「むしろ子どもの学習意欲が高まるんじゃないかと思って」「耳で覚えるとか、暗記系には結構いいかも?」「英語なんかもそうだけど、しゃべった方が覚えられるというのはあるし」「Alexaなら当分文章題なんか解けないだろうし、目くじら立てるよりそのぐらいに考えて平和利用する方がいいかなって」


今回は以上です。

おたより発掘

バックナンバー(2019年度第1四半期)

週刊Railsウォッチ(20190115)Rubyの<=でクラス同士を比較、Rubyの記号の読み方いろいろ、Ruby C API解説サイトほか

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

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

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines

Publickey

publickey_banner_captured

DB Weekly

db_weekly_banner

Serverless Status

serverless_status_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言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

夏のTechRachoフェア2019

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ