Tech Racho エンジニアの「?」を「!」に。
  • 開発

週刊Railsウォッチ(20180413)RailsConf 2018、Form Objectの昔と今、rubyreferences.github.ioのドキュメントがスゴイ、GitHubが10歳にほか

こんにちは、hachi8833です。心を鬼にして記事数を抑え込みました。

若葉萌える季節のウォッチ、いってみましょう。今回はつっつき成分少なめです(追伸: 結局いつもと変わらなかった...)。

各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ

Rails: 今週の改修

以下、Rails 6向けのmasterから見繕いました。ドキュメントの修正が増えてます。


つっつきボイス: 「5.2が出たせいかコミットも一息ついた感じがします」「そういえば出てましたね(汗」

【速報】Rails 5.2.0正式リリース!Active Storage、Redis Cache Store、HTTP/2 Early Hintほか

コレクションのキャッシュとHTTPキャッシュを併用するとエラー→修正

# activerecord/test/cases/relation/mutation_test.rb#L62
-    (Relation::SINGLE_VALUE_METHODS - [:lock, :reordering, :reverse_order, :create_with, :skip_query_cache, :skip_preloading]).each do |method|
+    (Relation::SINGLE_VALUE_METHODS - [:lock, :reordering, :reverse_order, :create_with, :skip_query_cache]).each do |method|
       test "##{method}!" do
         assert relation.public_send("#{method}!", :foo).equal?(relation)
         assert_equal :foo, relation.public_send("#{method}_value")
       end
     end

出たばかりの5.2_stablemasterの両方に入りました。

skip_preloading!のアサーションはイミュータブルであるはずが、コントローラでfresh_whenを使うとarelが定義されてしまっていることがある。
生成されたSQLにはskip_preloadingは効かないので、この値を設定するときはチェックをスキップして安全にすべき。
このプルリクでは、assert_immutabilityチェックを使うセッターを定義するのに使われるSINGLE_VALUE_METHODSからskip_preloadingを削除し、リレーションの属性アクセサに置き換えた。
同PRより

dalli gemのエラー修正

# lib/rack/session/dalli.rb#L160
-      # Capture generate_sid's super so we can call it from generate_sid_with
-      alias_method :generate_sid_super, :generate_sid
-
-      def generate_sid
-        # no way to check env['rack.multithread'] here so fall back on
-        # Dalli::Client or ConnectionPool's internal mutex cf. our own
-        @pool.with {|dc| generate_sid_with(dc) }
-      end
-
       def generate_sid_with(dc)
         while true
-          sid = generate_sid_super
+          sid = generate_sid
           break sid unless dc.get(sid)
         end
       end

つっつきボイス: 「Railsではなくdalliっていうgemの修正でした」

その後Rails側の#5bca1f2でdalliがアップデートされたようです。

# Gemfile#L48
-gem "dalli", "< 2.7.7"
+gem "dalli"
 gem "listen", ">= 3.0.5", "< 3.2", require: false
 gem "libxml-ruby", platforms: :ruby
 gem "connection_pool", require: false


同リポジトリより

「dalliって何だろうと思って今回ちょっと下調べしたんですが、memcachedクライアントなんだそうです」「dalliはとってもメジャー: Rails + Memcachedだと大体出てきますね」「でdalliのリポジトリにあるこの超有名な絵↑のタイトルが「記憶の固執」(The Persistence of Memory)だからきっとそこから付けたにキマってる」「へぇぇ!そのまんまw」「固執ってこう、あまり馴染みない言葉: プログラマーだとpersistencyといえばたいてい永続化ですしね」「基本の意味は『頑固な汚れ』の頑固とか『こびりつく』みたいな感じかなー」

いつぞやウォッチで取り上げたsurrealist gem↓は、ダリはダリでもmemcachedとは関係なかったですね。


nesaulov/surrealistより

APIモードにデフォルトでDefaultHeadersを含めた

# actionpack/lib/action_controller/base.rb#L232
       HttpAuthentication::Basic::ControllerMethods,
       HttpAuthentication::Digest::ControllerMethods,
       HttpAuthentication::Token::ControllerMethods,
+      DefaultHeaders,
...
-    def self.make_response!(request)
-      ActionDispatch::Response.create.tap do |res|
-        res.request = request
-      end
-    end
-
     ActiveSupport.run_load_hooks(:action_controller_base, self)
     ActiveSupport.run_load_hooks(:action_controller, self)
   end

つっつきボイス: 「APIモードってRailsをAPIサーバーとして動かすアレですよね?」「そうでしょうね」「Changelogに『デフォルトのヘッダー設定を、コントローラにインクルードされる個別のモジュールに移動した』とある↓」「どうやらリファクタリングの一環のようですね: ActionController::Baseにあったメソッドを引っこ抜いてモジュール化して、APIとかにもインクルードしたってことみたい」「おー、ActionController::Baseに置くと使いもしないところにも読み込まれて大雑把すぎるから、って感じですかね」

# actionpack/CHANGELOG.md
+*   Move default headers configuration into their own module that can be included in controllers.
+
+    *Kevin Deisz*

direct_uploads#create responseからJSON rootを除外

# activestorage/app/controllers/active_storage/direct_uploads_controller.rb#L17
     def direct_upload_json(blob)
-      blob.as_json(methods: :signed_id).merge(direct_upload: {
+      blob.as_json(root: false, methods: :signed_id).merge(direct_upload: {
         url: blob.service_url_for_direct_upload,
         headers: blob.service_headers_for_direct_upload
       }) 

つっつきボイス: 「ActiveStorageですね」「テストコードを見るとblob↓がありますけど、レスポンスにまでblobを入れたくないよねという意図みたい」

# activestorage/test/controllers/direct_uploads_controller_test.rb#L133
+    @response.parsed_body.tap do |details|
+      assert_nil details["blob"]
+      assert_not_nil details["id"]
+    end

「これ↓を取りたいということですね」

参考: バイナリ・ラージ・オブジェクト - Wikipedia -- blob

changes_to_saveでの属性変更を防止

# activemodel/lib/active_model/attribute_mutation_tracker.rb#L23
       attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
         change = change_to_attribute(attr_name)
         if change
-          result[attr_name] = change
+          result.merge!(attr_name => change)
         end
       end
     end

つっつきボイス:HWIAって何でしたっけ...あ、HashWithIndifferentAccessか」「何つう略し方w」
HashWithIndifferentAccessって死ぬほどわかりづらいからなー: すごくよく間違えるし、名前も長いし」「そんなに手強いのか...RubyじゃなくてRailsのActiveSupportなんですよね: よく使われてるし、Rubyには取り入れないんでしょうかね?」「いやーどうかな...、Rubyには入れなさそうな気がするー...だって(Rubyの文字列やシンボルは)同じものではないから」

「ところで、今日社内勉強会で発表したGoby言語なら文字列とシンボルが同じクラスなんで大丈夫(`・∀・´)エッヘン!!」「そういえばCrystal言語はRubyの遅くなりそうな実装を取り除いた感じのもの』らしいんですけど、Goby言語の話を聞いててそれをちょっと思い出しました」「たしかTuring Complete FMの第5回のmrubyの回でそういう話があったので」「あ、Miuraさんでしたっけ?: 私もその回聞きました♥」「Turing Complete FMマジ面白い」

Elixir言語はRubyとは似てないんでしたっけ?」「見た目はともかく中身は結構違ってた気がします: ElixirのフレームワークであるPhoenixはRailsに似てるとかじゃなかったでしたっけ?」「そのあたり今度もうちょっと追ってみようかな...」

「ところでPRの方ですが、これもresult[attr_name] = changeで配列をじかに書き換えてるやつですね: 先週のつっつきにも似たようなミューテーションあった」「ハッシュの配列って...?[{ a: "a" }]のことかー!」「確かにそうなりますよね」「話逸れますが、文章とか翻訳でいつも気にしてるんですけど、所有の「の」って、『ナントカのナントカのナントカ』みたいになったときとか特に、意味が広がって誤解を生じることあるんですよね: 日本語でも英語でも」

参考

テストでヘッドレスChromeのGPUをWindowsで無効化

# actionpack/lib/action_dispatch/system_testing/browser.rb#L33
         def headless_chrome_browser_options
           options = Selenium::WebDriver::Chrome::Options.new
           options.args << "--headless"
-          options.args << "--disable-gpu"
+          options.args << "--disable-gpu" if Gem.win_platform?

           options
         end

つっつきボイス: 「これはトリビアなやつっぽいですね」「"--disable-gpu"は割りと普通に書きますけど、コミットメッセージ↓見ると、そもそも他のプラットフォームのヘッドレスChromeでは当分これが不要だから、Windowsでだけ指定するってことみたい」

Per Chromium team this has not been necessary on other platforms for quite some time: https://bugs.chromium.org/p/chromium/issues/detail?id=737678#c1
IMHO, this should be backported to 5-2-stable
同PRより

Rails

書籍『Docker for Rails Developers』


同サイトより

まだベータ版だそうです。

  • はじめに
  • 開発
    • RubyをインストールせずにRubyを実行
    • Railsイメージの微調整
    • Docker Composeでアプリを宣言的に記述
    • アプリの先: Redisの追加
    • DB追加: Postgres
    • Docker化環境のテスト
    • gem管理の高度な戦略
    • ちょい困ってる点
  • productionに進める
    • productionの概要
    • クラスタの作成
    • アプリのデプロイとスケール

つっつきボイス: 「これは今日morimorihogeさんがSlackに流してくれた情報ですね」「いろいろ盛りだくさんな感じ...でも180ページだから多くはないですね」「Railsがわかってる人なら一気に読み下せそう」「20ドル弱か: どうしようかなー」

Herokuの「Review Apps」


つっつきボイス: 「昨日の記事↓を訳してて知りました」「HerokuのReview Appsって前からあったような...?」「あ、ぐぐったら2016年からリリースされてた」
「今BPS社内のGitLabサーバーにもこれ的な機能を構築してもらってますよね」「言われてみれば」「CIに通ったらレビュー環境を自動構築してくれたりしますね」「それ記事にしましょうよ」

「このしくみ、内部ではSandStarって名前が付いてるんですけど、ちなみにこの名前でググるとけもふれが真っ先に出てきますよ」「やべ、私のカバーできてない分野w: サンドスターでぐぐってみると、何だかガンダムのミノフスキー粒子みたいな趣ですね」「はっは...」

「ところでsand starってヒトデなんですね」「あれ?ヒトデってstarfishだと思ってた」「sandstarの由来はBOTのthumbnail見て分かるとおり完全にけもフレですよねw」

Rails: rakeタスクをRubyオブジェクトで美しく保つ(翻訳)

参考: Heroku Review AppsでPRごとに動作環境を作成せよ - Qiita

Railsの設計の悩みと、Form Objectの今と昔

Railsを始めて一ヶ月半経ったので振り返りをする - ゆとり日記

とにかく設計に悩む事が多い。
特に最近悩んでいるのが「controllerがファットになった時の対処法」。Viewに渡す情報が多い画面を作っていると、あっという間にcontrollerの処理が膨らんでしまい、対処法で毎回悩んでいる。

上の記事で以下のTechRacho記事を引用いただいていたのでたどり着きました。『設計に悩む事が多い』のあたりが気になったので。

肥大化したActiveRecordモデルをリファクタリングする7つの方法(翻訳)


つっつきボイス: 「『設計に悩む事が多い』のあたりが気になったので」「↑この『肥大化したモデル』記事、BPSに入社する前に読みましたよ」「そういえば訳したのだいぶ前でした」

「『肥大化したモデル』見てて思い出したんですけど、Form Objectって、この記事の頃に比べて必要性がちょっと薄れたような気がしないでもないんですよね」「というと?」「もともとForm Objectって、ビュー画面で昔のform_for(注: 今は非推奨)するときに、フォームとモデルが対応していないからそれをラップして属性を生やすのが主な使い方、みたいに自分は思ってるんですね: ほかにも使い方あるんでしょうけど」「ふむふむ」「でも今はform_withがあるじゃないですか、form_withなら属性が生えてなくてもちゃんとやってくれるんですよ」「ほー!」「だから少なくともForm Object使ってた理由の1つは消えることになるんですよね」「↓あー、form_withドキュメントのこのあたりですね」「ですです」

form_withのそういうところってかなりいいと思うんですよ: 極端に言えばモデルなくたって使えるし、だから昔のform_forのときみたいな使い方だけならForm Objectいらないんじゃないかなって」

「あとForm ObjectってService Object的に使うこともできちゃうじゃないですか: で、2017年に誰かが"Form Objectは肥大化しやすい"って記事書いてたように肥大化の原因になったりとか」「なるほどー」「その記事どこにあったかな...Qiitaのアドベントカレンダーとかだった気がするけど見つからない...」

「Form Object、もちろんちゃんと設計して使うならいいんでしょうけど、取りあえず雑に置いとけみたいなレベルだったら使わなくていいんじゃないかなと思ったわけです」「おー!今の話、自分にはいろいろストーリーが見えてきてとてもうれしいです❤️」「自分の解釈ですけどねーw」

モデルを複数使うフォームとかなら、Form Objectの出番ありそうですね。

「Form Object肥大化&役割が大きくなりがち問題は同意: ただ、複雑なリクエストを受けるフォーム(よくある「詳細検索」とか)において、acceptableなパラメータとかを一括で管理できる見通しの良さはありますよね」

「あとForm Object作るときに結構大事なのは、Controllerのparams生渡しだけを前提に書かないことかなと思ってます: params前提でやり過ぎるとHTTP Requestの受けでしか使えなくなっちゃうのでつらい」「Jobとかrake taskの中でも同じForm Objectを使えるようにしてたりすると有用」

Rails 5.1〜: ‘form_with’ APIドキュメント完全翻訳

dev.toの中の人がRailsConfに登壇

dev.toといえば超速で有名ですね。そういえばdev.toはRailsで構築されているのでした。


railsconf.comより


つっつきボイス: 「dev.toがRailsってのがスゴイですよね」「あちこちで記事になってますけど、あらゆる最適化を尽くしてるんでしょうね」

参考: はてなブックマーク - なぜ dev.to がこんなにも速く、こんなにも自分にとって感動的なのか

「ちなみにそのRailsConf、先日の5.2リリース速報記事でもちょっと紹介したんですけど、セッションの多さがヤバいです↓」「めちゃくちゃ多いじゃないですか!スロット7つあるし、到底見きれないですね...」「これとこれとこれだけ見るって心に誓うぐらいじゃないと能率が落ちそう」「amatsudaさんも登壇するのか」(以下延々)


railsconf.com/scheduleより

「...『Pairing: a guide to fruitful collaboration 🍓🍑🍐』ってペアプロの話っぽいですね」「またしても雑学ですが、fruitfulというと聖書を思い出しちゃうんですよ: 『産めよ増やせよ地に満ちよ』って確か英語だと『Be fruitful and multiply』だった」「へー、じゃ相当ポジティブな意味なんですね」「そんな感じです」(以下延々)

Hanami 1.2リリース

たぶん花見の季節に出したかっただろうと思います。


つっつきボイス: 「HTTP/2 Early Hints、Hanamiにも入るんですね」「そういえばAaron Pattersonインタビューでearly hints知りました」「あれ?form_for↓?ww」「何かいいタイミングというか、歴史逆行してる?中身知りませんが」

<!--同記事より-->
<%=
  form_for :search, "/search", remote: true do
    # ...

    submit "Search"
  end
%>

「Hanamiって、何だか思ったよりずっとRailsの影響大きそう?」「わかりませんが、Railsから離れる方が難しいかも」「form_for使うぐらいだし、もっとRailsから一線を引いた感じなのかと思ってました」「自分も何となくSinatra寄りなのかなと思ってた」「db:migrateもあるみたいですし」

Hanamiフレームワークに寄せる私の想い(翻訳)

Ruby trunkより

Module#refine自身にrefineかけたら参照できなかった

# 同issueより
using Module.new {
  refine Module do
    def refine *;
      puts self
    end
    public :refine
  end
}
Object.refine # => NoMethodError

つっつきボイス: 「ヘ(゚д゚)ノ ナニコレ?まったくわかんないw」「refineできるけど呼べない...?」「bugなんですね」「さすがurabeさん」

フランス語でこんにちは

bonjour,
chaque fois que je lance mailcatcher et que je me rends sur la page : 127.0.0.0:1080, mailcatcher stop et me rapporte un bug.
Ci-joint, un fichier txt du rapport de bug.
Très cordialement,
lflapy


つっつきボイス: 「珍しかったので」「これもフランス語分かんないすねー: 内容はうっすらわからんでもないけど」「Third Party's Issueにトリアージされた」

提案: ハッシュと配列にも+@-@が欲しい

I like .dup and .freeze, more than + and - on class String.


つっつきボイス: 「最初よくわかんなかったけど、上からしてdupfreezeを記号でやりたいってこと?」「Cのパッチ↓を見ると、+はたとえば配列がfrozenならdupして、frozenでなければ配列自身を返す、と」「あそういうことか」

 * call-seq:
 *   +ary  -> ary (mutable)
 *
 * If the array is frozen, then return duplicated mutable array.
 *
 * If the array is not frozen, then return the array itself.
 */
static VALUE
rb_ary_uplus(VALUE ary)
{
    if (OBJ_FROZEN(ary)) {
    return rb_ary_dup(ary);
    }
    else {
    return ary;
    }
}

「で-はその逆で、freezeしてたら自身を返してそうでなかったらコピーを返す」

/*
 * call-seq:
 *   -ary  -> ary (frozen)
 *
 * If the array is frozen, then return the array itself.
 *
 * If the array is not frozen, return a frozen copy of it.
 */
static VALUE
rb_ary_uminus(VALUE ary)
{
    if (OBJ_FROZEN(ary)) {
    return ary;
    }
    else {
    return rb_ary_freeze(ary);
    }
}

「この書き方は好きになれない...: perlみたいなぱっと見わかりにくい魔術的記号言語にRubyが向かっていく気がして」「ですね: 記号は限りある資源なのに」「ルーン文字のように力を持つ文字みたいな」

Ruby

Rubyのyield

# 同記事より
def one_yield
  yield
end
def multiple_yields
  yield
  yield
end
$> one_yield { puts "one yield" }
one yield
 => nil
$> multiple_yields { puts "multiple yields" }
multiple yields
multiple yields
 => nil

つっつきボイス: 「これはyieldの基本的な使い方の説明ですね」「長くないしすっと読めそうかな」

smart_init: Rubyの初期化コードを簡略化するgem

いま翻訳中のWhy Service Objects are an Anti-Pattern — INTERSECTに出てきました。

def initialize(network_provider, api_token)
  @network_provider = network_provider
  @api_token = api_token
end

# 上を下のように書ける

class ApiClient
  extend SmartInit

  initialize_with :network_provider, :api_token
end

# またはサブクラス化

class ApiClient < SmartInit::Base
  initialize_with :network_provider, :api_token
end

つっつきボイス: 「★は少ないですが」「ふーむ、コンストラクタでそんなにいくつも引数を取らないといけないとしたら、そっちの方が問題かもね」「後、コンストラクタ回りのメカニズムを隠蔽するというのは自分的には何だかオカシイ気がする」「そもそもこのgem、ActiveRecordに乗らないでしょたぶん?」

「でもこのgemを作るのはとっても簡単だと思う: だからこれを使うというより、Ruby初心者がこういうgemを一度自分で書いてみるといいかもね」「なるほど、練習課題として」

「変なこと言いますけど、昔自分もRubyでこうやって引数とインスタンス変数で同じ名前を何度も書くのが何か冗長だな?って思ったことがあって、これ見てたらそれを思い出しちゃいました」「まぁそれがRubyの慣習ですから: Javaもそう」

Rubyメタプログラミングのデバッグ(RubyFlowより)

# 同記事より
require 'csv'
class User < Struct.new(:email, :name)
  def to_csv
    [name, email]
  end
  def self.export(users)
    post_to_api(create_csv(users))
  end
  def self.create_csv(users)
    CSV.generate do |csv|
      csv << ["name", "email"]
      users.each do |user|
        csv << user.to_csv
      end
    end
  end
  def self.post_to_api(string)
    puts "sending to api"
  end
end


同記事より


つっつきボイス: 「メタプログラミングのデバッグぇえ」「ざざっと見てみると、アプリのデバッグというより、メタプログラミングするとどんな挙動になるかをirbで見てみよう、という感じっぽいですね」「class_evalはこんな感じになるんやで、みたいな」

プライベートなRubyサーバーをGCPにデプロイ

Googleの日本語記事とgemです。


つっつきボイス: 「y-yagiさんのツイートですね」「いわゆる社内用gemサーバーなんかを速攻でGCPに立てられるってことですね」「すっげー」「SQLも使えたり」「プライベートgemサーバーのメンテそのものは面倒くさいけどw、今までみたいにメンテもせずgemサーバー立てるのもツライとかよりはずっとマシかもね」「このぐらいスッと立てられるならそうですね」

ドリコムさんとかgemサーバー立ててますよね?」「そうそう、大きい開発会社ならたいてい必要になってくるヤツ」「ドリコムさんはgemをどんどん書く文化って聞いたことありますね」「プライベートなのも公開しているのもあるだろうし」

参考: ドリコムで使ってるgem一覧 #railsdm - くりにっき

🌟「The Ruby Reference」のドキュメントは凄い🌟


rubyreferences.github.ioより


つっつきボイス: 「ネットですごく話題になってますね: 基本的には公式ドキュメントの内容を持ってきて整理した感じですが、ビシっと整形されててすっごく読みやすい」「おーこれは確かによくできてる!」「いいわ〜❤️」「で、ブログの方はそれを作ってくださったzverokさんですね: こんな感じで作ったみたいです↓」「エライな〜」

  • ソースリポジトリのRDocが主
  • ruby-lang.orgからも多少
  • 自分でもそこそこ記事書いて埋めた(Rubyのコメントの書き方とか公式ドキュメントにないので)
  • 上から下まですっと読み通せるように整形とかがんばった

「確かに2.5以外のもこうやって見られたらどんなにいいだろうと」「うんうん」

今週の🌟を進呈いたします。おめでとうございます。そういえばTechRachoでも何度かzverokさんの翻訳記事を掲載しました。

Ruby: 「マジック」と呼ぶのをやめよう(翻訳)

Rubyの「クラスマクロ」と「クラスインスタンス変数」

# 元記事より
module XmlFormattable  
  def to_xml
    formatter.format
  end

  def render(file_name, object, options)
    formatter.render(file_name, object, options)
  end

  def formatter
    @formatter ||= XmlFormatter.new(self, "format type goes here!!")
  end
end  

# ダメな書き方
class Itunes::Album  
  include XMlFormattable
  XML_FORMAT = "itunes_version_9"
end

class Spotify::Album  
  include XmlFormattable
  XML_FORMAT = "spotify_version_7"
end  
class DDEX::Album  
  include XmlFormattable
  XML_FORMAT = "ddex_version_38"
end

つっつきボイス: 「ほうほう、確かに最初のダメなコード例はヒドイww」「どの辺がひどい感じ?」「だって定数を宣言してそれを書き換えてるだけだし: それ定数にする必要あるー?名前空間切りたいとかかもしれないけど」

「(眺めながら)あーだからクラスマクロなのか!なるほどね」「というと?」「普通ならこういうのはインスタンス変数のスコープなら継承とかmixinでやったりするけど、これはクラスの持ち物だから、マクロという呼び方で共通化しようとしてるんじゃないですかね」「そういえば記事の冒頭に『クラス変数クラスマクロとは、クラス定義時に1回だけ使われるクラスメソッド』ってありますね」「定数名がすべてコピペで同じなのはダサいからそこを何とかしようという趣旨みたい」

「ちなみにこういうの↓をまるっとやってくれるのがActiveSupportのconcernsなんですよね」「そうそう」「そうでしたか!」「要はただのクラスメソッドですけど」

# 同記事より
module XmlFormattable  
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def xml_format(name)
      # coming soon!
    end
  end

「で、それをクラス変数@@使ってやろうとしたらダメだった、さてどうしたらよいでしょうか?という流れですね」「うわーモジュールにクラス変数書いてるゾw」「どんなふうに動くんでしょうねw」

「最終的に、クラスインスタンス変数ならできたぜってことみたい」「謎のクラスインスタンス変数w」「クラスインスタンス変数って、名前につられがちでいつもややこしいっす...」(以下延々)

この記事訳してみようかと思います。

参考: 【まとめ】インスタンス変数、クラス変数、クラスインスタンス変数 - Qiita

SQL

postgresql-topn: 「トップN」問題解決を支援する拡張

先週のウォッチで取り上げたTopN for your Postgres databaseで紹介されていたので。いま翻訳中です。

-- 同記事より
-- Create a roll-up table to capture most popular products
CREATE TABLE popular_products
(
  review_date date UNIQUE,
  agg_data jsonb
);

-- Create different summaries by grouping top reviews for each date (day, month, year)
INSERT INTO popular_products
    SELECT review_date, topn_add_agg(product_id)
    FROM customer_reviews
    GROUP BY review_date;

PostgreSQLのこのクエリが好きやねん(Postgres Weeklyより)

-- 同記事より
dvdrental=> WITH fake_month AS(
SELECT setup::date
FROM generate_series('2007-02-01', '2007-02-28', INTERVAL '1 day') AS setup
)
SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
LIMIT 10;
legit | sum | fake
-------+---------+------
1 | 2808.24 | 1
2 | 2550.05 | 2
6 | 2077.14 | 6
8 | 2227.84 | 8
9 | 2067.86 | 9
17 | 3630.33 | 17
18 | 3977.74 | 18
19 | 3908.59 | 19
20 | 3888.98 | 20
21 | 3786.14 | 21
(10 rows)

つっつきボイス: 「1.は『LEFT JOINなのに右のNULLをよしなにしたい』...?右にNULL出したいからLEFT JOINなんじゃ?よくわからん」「INNER JOINじゃダメなのかな?」「GROUP BYしてるからNULLが邪魔っけとか?」(以下延々)「時間ないので次いきましょうー」

PostgreSQLのデータ肥大化に立ち向かう(Postgres Weeklyより)

VACUUMも効かないような場合の手法だそうです。


つっつきボイス: 「VACUUMもダメだと相当大ごと」「字ちっちゃいけど、pgcompacttableとpg_repackを使うみたいですね」「ちなみに、postgresqlのVACUUMは雰囲気としては昔懐かしWindowsのデフラグみたいな機能なので、データそのものの肥大化対策にはならないと思って良いですね」「再配置・効率化がメインなので、compressionが目的の機能ではない」

JavaScript

Node.jsプロジェクト構造チュートリアル

Codeshipの記事です。

// 同記事より
'use strict'

// required environment variables
[
  'NODE_ENV',
  'PORT'
].forEach((name) => {
  if (!process.env[name]) {
    throw new Error(`Environment variable ${name} is missing`)
  }
})

const config = {
  env: process.env.NODE_ENV,
  logger: {
    level: process.env.LOG_LEVEL || 'info',
    enabled: process.env.BOOLEAN ? process.env.BOOLEAN.toLowerCase() === 'true' : false
  },
  server: {
    port: Number(process.env.PORT)
  }
  // ...
}

module.exports = config

JavaScript「proxy」入門(JavaScript Weeklyより)


同記事より

JavaScriptのcoercion(JavaScript Weeklyより)


つっつきボイス: 「む、このサイト、重い...」「さっきも重かったです」
「coercionってこういうやつなのか...↓」「えー!」「Ruby脳だとわけわからなくなりそう」

// 同記事より
'2' + 2 // 22
15 + '' // '15'
+'12'   // 12

[1] + [2] – [3] === 9になる理由は一番最後に書いてますね」「絶句」

CSS/HTML/フロントエンド

画像や動画の遅延読み込み

Googleの技術ブログです。

PWA

これもGoogleのサイトです。

MozillaのWebAssembly向けブラウザIDE


webassembly.studioより


つっつきボイス: 「先週のpaiza.ioもそうですけど、ブラウザでやるのが普通の世界になりつつありますね...」

参考: Mozillaが「WebAssembly Studio」発表。C/Rust/AssemblyScript対応のオンラインIDE - Publickey

バズるかどうかを事前に予測ですって

参考: アドビがチラ見せした最新AI機能はまるで「未来」だ ── AIが判定するコンテンツの良し悪し:Adobe Summit 2018 | BUSINESS INSIDER JAPAN


つっつきボイス:BPSのデザインチームの人がアドビ先生凄い!ヤバいって言ってましたね」「今度教えてもらおうっと」

サイト: https://www.adobe.io/apis/cloudplatform/sensei.html

ChromeとFirefoxの新しい認証標準「WebAuthn」(Frontend Focusより)


つっつきボイス: 「WebAuthnって、生体認証をブラウザでできるってことか...」「W3CでCandidate Recommendationになってる↓」

参考: Web Authentication: An API for accessing Public Key Credentials Level 1

Go言語

Go言語の詳細な内部解説

0x0000 TEXT     "".add(SB), NOSPLIT, $0-16
  0x0000 FUNCDATA   $0, gclocals·f207267fbf96a0178e8758c6e3e0ce28(SB)
  0x0000 FUNCDATA   $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 MOVL       "".b+12(SP), AX
  0x0004 MOVL       "".a+8(SP), CX
  0x0008 ADDL       CX, AX
  0x000a MOVL       AX, "".~r2+16(SP)
  0x000e MOVB       $1, "".~r3+20(SP)
  0x0013 RET

0x0000 TEXT     "".main(SB), $24-0
  ;; ...omitted stack-split prologue...
  0x000f SUBQ       $24, SP
  0x0013 MOVQ       BP, 16(SP)
  0x0018 LEAQ       16(SP), BP
  0x001d FUNCDATA   $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x001d FUNCDATA   $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x001d MOVQ       $137438953482, AX
  0x0027 MOVQ       AX, (SP)
  0x002b PCDATA     $0, $0
  0x002b CALL       "".add(SB)
  0x0030 MOVQ       16(SP), BP
  0x0035 ADDQ       $24, SP
  0x0039 RET
  ;; ...omitted stack-split epilogue...

つっつきボイス: 「これめちゃ凄いドキュメント!: Gobyの人たちも色めき立ってます」

結城浩さんもすなるGo

参考: 動詞で『すなる』の意味を何方か教えてください。 jfjnc078 - 土佐日記の... - Yahoo!知恵袋

その他

GitHubが10歳に


つっつきボイス: 「まだ10歳なのに、ずっと前からあるような気がしてきました」「もうないと生きていけないヤツ」「そういえばGo言語がで生まれた直後ってGitHubあったかしら?(2009年でした): そんな時期にGitHubに全面的に依存したエコシステム作ったのってある意味英断かも」「Go言語の人たち、バクチ運強いんですよきっと」

https://www.youtube.com/watch?v=5M2cCXynKyY

四畳半問題

https://twitter.com/azapen6/status/983648640722874369


つっつきボイス: 「あ、あ、本当にできないかも!」

ゼロ幅スペースのチート増殖中

詳しくは以下の記事をどうぞ。

Unicodeで絶対知っておくべきセキュリティ5つの注意(翻訳)

WiFiだけで倉庫ロボットを導入

他のインフラがいらないのは画期的かもです。

番外

ドラえもんにこんな道具あった気が

参考: 「現実より広いVR空間を歩ける技術」NVIDIAが発表 | Mogura VR - 国内外のVR/AR/MR最新情報

よい仕事

電磁誘導の最強感

3Dプリンタで家を量産

ちなみにこの動画を見るきっかけになったVOA(Voice Of America)のLearning Englishサイトは英語の自学自習に最適で超おすすめです(オール無料)。何しろ米国の国家予算で運営されてますので、しっかり金かけてるのがよくわかります。動画にきっちり字幕が表示されているのがうれしい点で、私は毎朝これ見ながら5分間シャドウイングしてます。

参考: Wikipedia-ja ボイス・オブ・アメリカ


今週は以上です。

ツィートより

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

週刊Railsウォッチ(20180406)ruby-sass gemが非推奨に、Roda gem、paiza.ioは便利、Linuxは/procで遊ぼうほか

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

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

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Postgres Weekly

postgres_weekly_banner

Frontend Focus

frontendfocus_banner_captured

JavaScript Weekly

javascriptweekly_logo_captured


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。