Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

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

こんにちは、hachi8833です。先日の大江戸Ruby会議 07の白眉は、Rubyのキーワード引数分離についての議論↓と、Aaron PattersonさんのAsakusa.rb 10周年のお祝いメッセージが特濃だった(tenderlove/allocation_sampler)ところでした。Asakusa.rb10周年おめでとうございます!🎉🎉

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

今回のエントリは少なめです🙇。

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

つっつき時点では公式の更新情報がなかったのでコミットログなどから見繕いました。

ビューテンプレート探索を高速化

かなり速くなったようです。

# actionview/lib/action_view/template/resolver.rb#L368
-     exts = EXTENSIONS.map do |ext, prefix|
-       if ext == :variants && details[ext] == :any
-         "{#{prefix}*,}"
-       else
-         "{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}"
+     def find_template_paths_from_details(path, details)
+       # 可能なパスをすべてチェックするのではなく、他のglobと同様、正しいprefixを持つファイルを検索する
+       query = "#{escape_entry(File.join(@path, path))}*"
+        regex = build_regex(path, details)
+        Dir[query].uniq.reject do |filename|
+         # この正規表現は、(prefix以外にも)詳細部分にもマッチするファイルの探索と、
+         # 大文字小文字を区別しないファイルシステム向けのフィルタという2つの役割を担う
+         !filename.match(regex) ||
+           File.directory?(filename)
+       end.sort_by do |filename|
+         # ファイルを1つずつチェックするのではなくディレクトリを探索しているので、
+         # そのままでは戻り値の順序が一定しない
+         # この正規表現でのマッチ結果を用いて詳細部分をインデックスでソートする
+         match = filename.match(regex)
+         EXTENSIONS.keys.reverse.map do |ext|
+           if ext == :variants && details[ext] == :any
+             match[ext].nil? ? 0 : 1
+           elsif match[ext].nil?
+             # No match should be last
+             details[ext].length
+           else
+             found = match[ext].to_sym
+             details[ext].index(found)
+           end
+         end
+       end
-     end.join
+     end
# 修正前
Warming up --------------------------------------
   lookup users/show     6.000  i/100ms
Calculating -------------------------------------
   lookup users/show     61.302  (± 4.9%) i/s -    306.000  in   5.011577s

# 修正後
Warming up --------------------------------------
   lookup users/show   353.000  i/100ms
Calculating -------------------------------------
   lookup users/show      3.845k (± 5.3%) i/s -     19.415k in   5.064962s

つっつきボイス:「globって何だろうと思ったらDir.globのことでした」「そういえばglobってあった」「コメントの日本語は🤔?」「あ、私が取り急ぎ訳しました」「今回の改善は著しいですね😍前よりコード量増えてるのに20倍近く速くなってる」「👍も30超えてるし」「ベンチマークではlookup_context.find_templateを調べてるのか↓」「裏方の改善だから何もしなくても恩恵が得られるヤツ😎」

# 同PRより
require './config/environment'

Benchmark.ips do |x|
  x.report "lookup users/show" do
    ApplicationController.new.lookup_context.find_template("users/show", [], false, {}, {})
  end
end

参考: Dir.glob と Find の違い - Qiita

ActionDispatch::IntegrationTestTestHelperをインクルード

DHHのあげた#33838への対応です。


つっつきボイス:「これは小物かなと思いつつ」「integration testにTestHelperがデフォルトでインクルードされたのか」「ActionMailer::TestHelperには何が入ってるのかな...↓assert_*系のメソッドか」「RSpecなんかだとこういうのを自分でインクルードしたりしますね」「せっかくテスト用ヘルパーがあるんだからデフォルトで入れてやろうぜってことなんでしょうね」「minitestですけどね☺️」

参考: ActionMailer::TestHelper

「今さらですけど、integration testはシステムテストとはまた別なんですよね?」「RSpecで言うとfeature testに相当するのがintegration testでしょうね: integration testはやったことないんですが」「そういえばintegration testでCapybaraは使われてるのかな?」「integration testはずっと前からRailsにあるんでCapybaraとは別でしょうね」「integration testはRailsフレームワーク自身のテスト用ですしね」「システムテストはCapybaraと共に導入されているし、間違いなくCapybaraと連携してる」

Rails: システムテストをRSpecで実行する(翻訳)

Integer#multiple_of?の高速化

riganiさんのアバターにしばし見とれてしまいました。

# activesupport/lib/active_support/core_ext/integer/multiple.rb#L10
  def multiple_of?(number)
    number != 0 ? self % number == 0 : zero?
    number == 0 ? self == 0 : self % number == 0
  end

zero?より== 0が速く、!=より==が速いんだそうです。


つっつきボイス:「Integer#multiple_of?なんてのがあったの?」「倍数かどうかの判定ですね」「どれだけ速くなったのかな...1.33倍」「引数がゼロのときはこのぐらい速くなると」「ゼロ以外のときはそうでもない感じ」「numberが1のときもtrue?😆」

「アバター自分で描いてるっぽい❤️」「この方、Nim言語というのもやってますね」「これそのうちウォッチで取り上げようかな😋(忘れないようにしないと💦)」

ActiveRecordにfilter_attributes属性を追加

59cae07を追っているうちにfilter_attributes属性がつい最近追加されたことに気づきました。config.filter_parametersを設定してあっても、誤って#inspectされてログに出てしまうことがあったのを修正するためだそうです。

# activerecord/lib/active_record/core.rb#L129
+     # #inspect呼び出しで公開されたくないカラムを指定する
+     class_attribute :filter_attributes, instance_writer: false, default: []
# activerecord/lib/active_record/core.rb#L495
    def inspect
      filter_attributes = self.filter_attributes.map(&:to_s).to_set
      # 初期化されていないオブジェクトが割り当てられている場合にwarningを生成しないよう
      # defined?(@attributes)をチェック
      inspection = if defined?(@attributes) && @attributes
        self.class.attribute_names.collect do |name|
          if has_attribute?(name)
-           "#{name}: #{attribute_for_inspect(name)}"
+           if filter_attributes.include?(name) && !read_attribute(name).nil?
+             "#{name}: #{ActiveRecord::Core::FILTERED}"
+           else
+             "#{name}: #{attribute_for_inspect(name)}"
+           end
          end
        end.compact.join(", ")
      else
         "not initialized"
       end

       "#<#{self.class} #{inspection}>"
     end

参考: ActiveRecord::Core::ClassMethods#filter_attributes


つっつきボイス:「filter_parametersは確かに昔からありますね」「↓こうすると内部でinspectが呼ばれてログに出てしまう」

# 同記事より
@account = Account.find params[:id]
payload = { account: @account }
logger.info "payload will be #{ payload }"

参考: Rails4でfilter_parametersのネスト - Qiita

rails newすると、"password"というカラム名がフィルタされる設定がconfig/initializers/filter_parameter_logging.rbに書き込まれるんですね: フィルタしたいカラム名をこのファイルに追加できる」「Railsのログに[FILTERED]って出ているとすげ~って思う💪: いつの間にって感じ」

「そういえばfilter_parametersでフィルタするカラム名はシンボルや文字列で指定できるんですけど、たとえばうっかり:nameとか指定してしまうと、nameを含むカラム名と部分一致してことごとくフィルタされちゃったりするんですよね😅」「ありそう〜」「シンボルだからカラム名と完全一致しないとフィルタされないだろうと思うじゃないですか、でもそうじゃない: シンボルも文字列も実はカラム名と部分一致する😭」「😆」「だからフィルタが間違って効きすぎないようにするには、シンボルや文字列じゃなくて、正規表現を使って始まりと終わりもびしっと指定しないといけないんですよ」「まあpasswordという文字を含むカラム名は原則ログに出しちゃあかんというのはワカル: だからこそpassword_confirmationとかもフィルタされるし」「安全側に倒すという意味ではそういう作りになるのはしょうがないのかも」「親切設計なんですけど、その親切を理解してないとつまらないワナを踏んじゃう」

参考: Railsのlogに出したくない情報をちゃんと出さないようにする - Qiita

Edgeguidesには「パラメータは正規表現の部分一致でフィルタされる」とあります。日本語版Railsガイドにはまだ反映されていませんが、現在作業中です。

なお、このPRでedgeapi.rubyonrails.orgというサイトがあることを今頃知りました。

「edgeapiはmasterブランチのRails APIをいち早く見ることができるサイトですね」「へぇえ〜、これちょっといいかも😋」

archive.orgで調べたらedgeapiは2010年からあるんですね💦。

DatabaseLimitsで使われてないメソッドを非推奨化


  • column_name_length
  • table_name_length
  • columns_per_table
  • indexes_per_table
  • columns_per_multicolumn_index
  • sql_query_length
  • joins_per_query

つっつきボイス:「kamipoさんが『このメソッドたち絶対使わないっしょ』ということで非推奨にしたようです」「DatabaseLimitsって何だろそもそも?🤔」「たとえばsql_query_length()なら、クエリの長さがこれ以上増えると実行できないから実行時に動的に調べる...やらねーよそんなこと😆」「😆」「遅くなるだけだし」「PRメッセージを見ると、単に使われてないだけじゃなくて、ほぼほぼテストされてないってありますね😵」「まあたとえばマイグレーションでクエリがすごく長くなって落ちる前に、ちょっと気の利いたメッセージを出すとかクエリを調整するとかしたい、なんて使いみちならあるかも?やらないだろうな〜やっぱり😆」

参考: Ruby on Rails 5.2 / ActiveRecord::ConnectionAdapters::DatabaseLimits — DevDocs

追いかけボイス: 「DatabaseLimits 、SQLを文字列として生成しているコードなんかではWHERE文のサイズが爆発してMySQLのmax_allowed_packetを超過しちゃうということは割とあるので、その辺を見るメソッドだったんだろうなあと思った: AR/Arelで吸収して欲しいから使わないけど」「"WHERE hoge IN (#{bigger_ar_obj.pluck(:id).join(',')})"とかやると溢れる」

Rails

Knapsackでテストを高速安定実行(RubyFlowより)

Knapsackは以前のウォッチでも取り上げましたが一応。同記事で紹介されているスライド↓は、その名もRUG::BというベルリンのRubyユーザーグループが主催した9月のミートアップ発表されたものです。


knapsackpro.comより

mini_scheduler: Sidekiqで反復ジョブを登録するgem(Ruby Weeklyより)

# 同リポジトリより
class MyHourlyJob
  include Sidekiq::Worker
  extend MiniScheduler::Schedule

  every 1.hour

  def execute(args)
    # some tasks
  end
end

Discourseのgemです。

discourse.orgより


つっつきボイス:「every 1.hourって書けるのね😲」「daily at: 12.hoursという書き方もできるみたいです」「役に立ちそうなgemでしょうか?」「使ってみないとわからないけど、こうやって表現できるのはいいことじゃないかな?」「Sidekiqでさっとスケジューリングしたいときにはいいのかも😋」

これとはあまり関係ありませんが、最近Railsdm Podcast #3↓に登場したy-yagiさんもactivejob-cancelというgemを作っています。

「ジョブのキャンセルってやっぱり面倒なんでしょうか?」「ジョブが動き出す前でもそもそもキャンセルしていいのかを判断しないといけないし、動き出してからだとキャンセル処理で原状復帰しないといけないし」「50%進めちゃったけどキャンセルしてよいのそれ?みたいなところを考えないといけないし、タイミングによってはシビアになるだろうし」

sourcemaking.com: デザパタ/アンパタ/リファクタ/UMLを網羅した解説サイト


同サイトより

自著の販売促進サイトのようです。以下の3冊が紹介されています。


つっつきボイス:「たまたま見つけたんですが、デザパタもアンチパターンもリファクタリングもUMLもカバーしているサイトです」「ほほ〜?」「サイトのコンテンツのまとまりがとても良くて、おっと思いました: アンチパターンも開発アンチパターンにアーキテクチャアンチパターンにプロジェクト管理アンチパターン、リファクタリングもコードの臭いとリファクタリング手法と分かれています↓」「おー、デザパタのあたりを見てるけど、コード例にJavaとかPHPとかDelphiとかはあるけどRubyは入ってないか(残念!)」「アンチパターンはあまりコードを使わずに説明しているっぽい」「シングルトンパターンは雑にやるとマルチスレッドに対応できないとかちゃんと書いてあるのがエライ😋」


同サイトより

Martin Fowlerさんのサイトとかの方が一次情報ですし内容も濃いと思うんですけど、あまりに雑然としていて追うのが大変なので😭」「😆」「Wolf ticketとか、知らないアンチパターンもありますね🤔」「こんなにいろいろあったかなと」「そういえばアンチパターンって凝った言い回しが多くて日本語にするのに四苦八苦します」

wolf ticketは「空約束」「看板に偽りあり」的な意味のようです。

[保存版]人間が読んで理解できるデザインパターン解説#1: 作成系(翻訳)

Rails OOP上級編(RubyFlowより)

# 同記事より
# lib/quote_connector.rb
require 'httparty'

class QuoteConnector
  URL = 'https://talaikis.com/api/quotes/random/'.freeze
  # since this is constant, we REALLY don't want to mutate it

  def initialize(adapter: HTTParty)
    @adapter = adapter
  end

  def call
    adapter.get(URL).body
  end

  private

  attr_reader :adapter
end

つっつきボイス:「記事の中に『DHHはDIを信じない』(2013年の記事)↓ってリンクがあるけど、知らなかった💦」「DIは基本的にJavaの問題解決手法だし、DHHがRubyでDIするか〜?っていう気持ちになるのはワカル」

参考: Dependency injection is not a virtue in Ruby (DHH)

「記事に出てくるinline bundler syntaxって何だろう?と思ったら、↓こういうふうにコードの中でbundlerを呼び出すのか😲」

# bundler.ioより
require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'json', require: false
  gem 'nap', require: 'rest'
  gem 'cocoapods', '~> 0.34.1'
end

puts 'Gems installed and loaded!'
puts "The nap gem is at version #{REST::VERSION}"

「こういう書き方って再現コードとかでよく使われてたと思います: gemがなくてもREPLでその場で動かしたいコードとか」「へ〜!😳」「たとえばActiveRecordのバグを再現するときとかに、こうやってbundlerでこのgemとこのgemを読み込んで、ActiveRecordのテーブルはメモリ展開しておくとか」「確かに説明のためにRailsをフルでセットアップしてられないし」「プレゼンのときにも便利そう」「Gemfileを用意しなくてもいいですしね😎」

レガシコントローラをSOLIDパターンでリファクタリング(Hacklinesより)

# 同記事より
 module Api
   module Admin
     module Analytics
       class ProductsController < V1::ApiController
         def top_sold
           raise ParamsMissing, 'params missing' if params_missing
           raise InvalidDateInterval, 'range of days is not allowed' unless check_date_interval
           response = perform(
             merchant_id: current_merchant.id,
             url: analytics_params[:url]
             start_date: analytics_params[:start_date],
             end_date: analytics_params[:end_date]
           )

           render json: ::Analytics::FormatService.top_product_format(response['metrics']), status: :ok
         rescue RestClient::Exception => ex
           render json: JSON.parse(ex.response), status: :unprocessable_entity
         rescue => ex
           render json: { message: ex.message }, status: :unprocessable_entity
         end

         ...
         ...
         ...
       end
     end
   end
 end
end

つっつきボイス:「リファクタリング前↑はやたらraiseとかrescueとかしまくっててごちゃごちゃしてる」「よく起こりがちなコード👓」「ざっとしか見てないけど、リクエストとレスポンスの処理を分けつつ、エラーハンドリングやバリデーションを切り出してそこに委譲する感じかな〜」

# 同記事より
module Anaylytics
  class Request
    module ErrorsHandler
      include AcctiveSupport::Concern
      include ActiveSupport::Rescuable

      included do
        rescue_from RequestError, with: :deny_access
      end

      protected

      class RequestError < StandardError
         ...
         ...
         ...
      end

      private

      def deny_access
        ...
        ...
      end
    end
  end
end

「ぱっと見Railsと関係ないコードかな?っと思ったけど、rescue_from↑が出てくるのはもうRailsのコードに間違いない😋」

参考: Ruby on Rails 5.2 / ActiveSupport::Rescuable::ClassMethods#rescue_from — DevDocs

「最終的に以下のようにErrorsHandlerをインクルードすればRequest.getでエラー処理ができるようになる感じかな」「よしよし☺️: 本線の処理とエラーの処理は別にしたいし」

# 同記事より
...
...
include Analytics::Request::ErrorsHandler

def top_sale
  response = Anaylytics::Request.get(:top_sale, params: {
    merchant_id: current_merchant.id,
    start_date: analytics_params[:start_date],
    end_date: analytics_params[:end_date]
  })

  render json: response, status: response.code
end
...
...

Ruby

ネイティブ拡張を使うgemを書く(Ruby Weeklyより)

#include <ruby.h>
#include <libclipboard.h>
#include "extconf.h"

static clipboard_c *cb = NULL;

VALUE set_text(VALUE _self, VALUE val) {
    Check_Type(val, T_STRING);
    VALUE result = Qnil;
    char *text = clipboard_text(cb);
    if (NULL != text) {
        result = rb_str_new(text, strlen(text));
        free(text);
    }
    if (false == clipboard_set_text(cb, StringValueCStr(val))) {
        rb_raise(rb_eRuntimeError, "Failed to write to clipboard.");
    }
    return result;
}

VALUE get_text(VALUE _self) {
    VALUE result = Qnil;
    char *text = clipboard_text(cb);
    if (NULL != text) {
        result = rb_str_new(text, strlen(text));
        free(text);
    }
    return result;
}

void Init_simple_clipboard() {
    cb = clipboard_new(NULL);
    if (NULL == cb) {
        rb_raise(rb_eRuntimeError, "Failed to create clipboard context.");
    }
    VALUE mod = rb_define_module("SimpleClipboard");
    rb_define_module_function(mod, "get_text", get_text, 0);
    rb_define_module_function(mod, "set_text", set_text, 1);
}

つっつきボイス:「いわゆるやってみた系の記事かなと思いますが」「お、クリップボードを扱うのか」「クリップボードの中身を取り出すにはどこかでシステムにアクセスしないといけないからC拡張でやったんでしょうね」「素のRubyからクリップボードを扱うのは大変そう」

後でclipbordというそれ用のgemがあるのを見つけました。

RubyとRustでそれぞれパスワード生成してみた(Ruby Weeklyより)

# 同記事より
Options.number.times do
  password = Options.length.times.map do
    dict.sample(random: SecureRandom)
  end.join(Options.separator)

  puts password
end
# 同記事より
    use std::iter::repeat_with;

    let mkpass = || {
        repeat_with(|| rng.choose(&dict).expect("dictionary shouldn't be empty"))
            .take(opts.length)
            .map(|s| *s)
            .collect::<Vec<&str>>()
            .join(&opts.separator)
    };

Redisでインメモリのブルームフィルタを実装する(Ruby Weeklyより)


元記事より

記事では、当初は先月のウォッチでも扱ったbloomfilter-rbを使ったのが、コンカレンシーの問題と更新の遅さを解決するため自分たちで再実装したとのことです。

# 同記事より
temporary_bloom_filter = TemporaryBloomFilter.new(user)

temporary_bloom_filter.insert(['user3@example.com', 'user4@example.com', 'user5@example.com'])

temporary_bloom_filter.count
# => 5

temporary_bloom_filter.include?('user5@example.com')
# => true

temporary_bloom_filter.include?('user6@example.com')
# => false

参考: What is a Bloom Filter Pattern? | Redis Labs -- Redisでサポートされているrebloomというデータ型(記事では使わなかったとのこと)


つっつきボイス:「ブルームフィルタはfalse positiveはあってもfalse negativeはないんだそうです」「つまり間違って『ある』と判定する可能性はあっても間違って『ない』とは判定しないってことね😋」

参考: ブルームフィルタ - Wikipedia

bindef: Rubyで書かれたバイナリ生成DSL(Ruby Weeklyより)

# 同記事より
# 以後の文字列エンコードをUTF-32にする
pragma encoding: "utf-32"
str "hello"
str "there"

# 以後の文字列エンコードをUTF-8にする(デフォルト)
pragma encoding: "utf-8"
str "utf-8!"

# pragmaにブロックを渡してスコープを絞れる
pragma endian: :big do
  # このブロック内ではビッグエンディアンのみを出力
  # Rubyの名前空間と定数は通常どおり機能することと、
  # `bindef`は`f32`と`f64`でfloatを使うことに注意
  # of `f` and `d`.
  i64 0xFF00FF00
  f64 Math::PI
  f32 Float::INFINITY
end

つっつきボイス:「ビンデフ?」「pragmaとか出てくるとCとかC++みたい」「pragmaってAda言語が元だったのか」「AdaというとAda Lavelaceから命名されたという古典ネタをつい思い出してしまいました」

参考: C言語 プリプロセッサ
参考: Ada について話します - Qiita

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

AWS System Managerにsshなしでコンソールログインできる「Session Manager」機能登場


つっつきボイス:「ssh鍵なしでブラウザからコンソールが使えるのはありがたいかも☺️」「それがいいのかというのはさておいて😆」「自分のPCがない客先とか旅行先でも使えるし」

参考: SSH不要時代がくるか!?AWS Systems Manager セッションマネージャーがリリースされました! | Developers.IO

SQL

PostgreSQLのchar型に使いみちはあるか(Postgres Weeklyより)

xof=# select length(c) from chars;
 length 
--------
      1
(1 row)

xof=# select substring(c from 8 for 1) = ' '::char(1) from chars;
 ?column? 
----------
 t
(1 row)

xof=# select substring(c from 8 for 1) = ' '::varchar(1) from chars;
 ?column? 
----------
 f
(1 row)

xof=# select length(substring(c from 8 for 1)) from chars;
 length 
--------
      0
(1 row)

xof=# select c || 'y' from chars;
 ?column? 
----------
 xy
(1 row)

つっつきボイス:「charを使っても節約できるのはたかが知れてるし、挙動も何だか謎なので、長さが1より大きいならvarchartextでいいんじゃね?という話のようです」「' '::char(1)だとtrueだけど' '::varchar(1)だとfalse...」「charはやっぱり固定幅なのね」「使わないかな〜」「使わないですね」

参考: 文字型 -- PostgreSQL 9.4

追いかけボイス: 「DBMSのchar型は、アラインメントを合わせたりできるのでカリカリにチューニングするDBAな人達とかは結構神経質にやってる人もいると思う: DBAがいるようなプロジェクトでないとあまり見ないけど」

ZomboDB: PostgreSQLをElasticsearchと連携(Postgres Weeklyより)


ロゴはリポジトリより

-- 同リポジトリより
CREATE EXTENSION zombodb;

CREATE TABLE products (
    id SERIAL8 NOT NULL PRIMARY KEY,
    name text NOT NULL,
    keywords varchar(64)[],
    short_summary text,
    long_description zdb.fulltext,
    price bigint,
    inventory_count integer,
    discontinued boolean default false,
    availability_date date
);

CREATE INDEX idxproducts 
          ON products 
       USING zombodb ((products.*)) 
        WITH (url='localhost:9200/');

つっつきボイス:「★1600超え」「普通にElasticsearchを使えばいいのかな?と思いつつ」「PostgreSQLで一貫して使いたい人向けなんでしょうね」「↑上みたいにCREATE EXTENSION zombodb;してUSING zombodbとすると使えるようになると」「WITH (url='localhost:9200/')は全文検索サーバーのURLを指定するってことなのかな?🤔」「するとこんなふうに==>でElasticsearch風なクエリを書ける↓と」「アプリ層からは普通にSQL叩いているように見えるのはちょっとうれしいかも」「この追加クエリ部分はSQLじゃないですけどね🤣」「ちなみにまだベータ版だそうです」

SELECT * 
  FROM products 
 WHERE products ==> '(keywords:(sports OR box) OR long_description:"wooden away"~5) AND price:[1000 TO 20000]';

当初Elasticsearchがなくても使えるのかなと思ったのですが、system requirementで5.6.xか6.xと指定されていました。

その他SQL

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

Priority Hints

     <img src="img/1.png" importance="high">
     <img src="img/2.png" importance="low">
     <img src="img/3.png" importance="low">
     <img src="img/4.png" importance="high">

つっつきボイス:「importance="high"とか書けるのっていい!😍」「何だか夢みたいじゃないですか😆」

HTTP発展小史


  • HTTP 0.9
  • HTTP/1.0
  • HTTP/1.1
  • HTTP/2

つっつきボイス:「HTTP 0.9なんてのがあったんですねっ😆」「😆」「HTTP/1.1ってどんだけ長く使われてるんだと」「この日進月歩の時代に☺️」「このサイトにはHigh Performance Browser Networking (O'Reilly)を掲載しているようですが何だか丸ごと載せてるみたい」「太っ腹🤩」

言語よろずの間

日本語Wikipediaエンティティベクトル


同記事より(CC BY-SA 4.0)


つっつきボイス:「比較的シンプルな処理でいい感じにできるのがいいなと思って: 『ヤマハ』と『ヤマハ発動機』の類似度の違いとか、北海道の札幌に相当するのは沖縄県のどこか、とか」「おぉ〜面白い☺️」

その他言語よろず

その他

イノベーションのジレンマ

Inbox by Gmailが消える?


つっつきボイス:「個人的にちょっとショックだったので😭」「これも消えるんですね〜: Gmailに注力するって書いてあるみたいだし」「一瞬使ってたけど☺️」「これだけ大きい企業なのにあっさりやめるあたりが、上の『イノベーションのジレンマ』の逆を行ってる感😆」「Google、Pixelは日本で出さないのに...😢」「そういえば今度Pixelを日本で発売するとかしないとかでざわついてますね↓」

参考: Google、新型スマホのティーザーサイト公開 「Pixel 3」日本発売か - ITmedia NEWS

番外

メイドイン軌道の高性能光ファイバー

参考: 史上初の宇宙製品は地球産の100倍高性能な光ファイバーかもしれない - GIGAZINE


今回は以上です。

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

週刊Railsウォッチ(20180910)公開つっつき会#2、RSpecは何を参考にするか、イベントソーシング、marginalia gem、負荷テストツールvegetaほか

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

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

Rails公式ニュース

Ruby Weekly

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines

Postgres Weekly

postgres_weekly_banner


CONTACT

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