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

週刊Railsウォッチ(20180302)Ruby 2.6.0-preview1とWebpack 4.0リリース、爆速検索APIサービスAlgolia、Clowneでモデルをクローンほか

こんにちは、hachi8833です。Ruby生誕25周年おめでとうございます!

3月最初のウォッチ、いってみましょう。最近社内での記事つっつき会が盛り上がっていて嬉しい限りです。

Rails: 今週の改修

Rails 5.2はまだ動いています。「2月中に出したい」は叶いませんでした。以下は5.2のcommitからです。

紀元前の日付の扱いをPostgreSQLに合わせた

# activemodel/lib/active_model/type/date.rb#L44
         def new_date(year, mon, mday)
-          if year && year != 0
+          unless year.nil? || (year == 0 && mon == 0 && mday == 0)
             ::Date.new(year, mon, mday) rescue nil
           end
         end

つっつきボイス: 「出た〜紀元前!」「どこに使うんだろうか」「は〜ん、年を-4みたいにできるようになったのか↓」

# activerecord/test/cases/adapters/postgresql/date_test.rb#L31
+  def test_bc_date_leap_year
+    date = Time.utc(-4, 2, 29).to_date
+    topic = Topic.create!(last_read: date)
+    assert_equal date, Topic.find(topic.id).last_read
+  end

PostgreSQLのdatedatetime同様に無限値を扱えるようにした

# activerecord/lib/active_record/connection_adapters/postgresql/oid/date.rb
+# frozen_string_literal: true
+
+module ActiveRecord
+  module ConnectionAdapters
+    module PostgreSQL
+      module OID # :nodoc:
+        class Date < Type::Date # :nodoc:
+          def cast_value(value)
+            case value
+            when "infinity" then ::Float::INFINITY
+            when "-infinity" then -::Float::INFINITY
+            else
+              super
+            end
+          end
+        end
+      end
+    end
+  end
+end

つっつきボイス: 「どゆこと?」「PostgreSQLって'-infinity'::dateって書き方できるとは」「さすがぽすぐれ: 知らないと使わないだろうけど」「マイナスのInfinityもあると: そりゃそうだ」

# activerecord/test/cases/adapters/postgresql/date_test.rb#L6
+class PostgresqlDateTest < ActiveRecord::PostgreSQLTestCase
+  def test_load_infinity_and_beyond
+    topic = Topic.find_by_sql("SELECT 'infinity'::date AS last_read").first
+    assert topic.last_read.infinite?, "timestamp should be infinite"
+    assert_operator topic.last_read, :>, 0
+
+    topic = Topic.find_by_sql("SELECT '-infinity'::date AS last_read").first
+    assert topic.last_read.infinite?, "timestamp should be infinite"
+    assert_operator topic.last_read, :<, 0
+  end

「そういえばMySQLのdateは確か内部でstringになってて、マイナスすると9999みたいに9並びになっちゃう9999-99-99みたいなありえない日付のクエリでも通ってしまう」「えー」「PostgreSQLは確か型チェックか何かをやってて、9999はまだしも9999-99みたいなのになるとエラーになったと思う」

参考: MySQL 5.6マニュアル 11.3.1 DATE、DATETIME、および TIMESTAMP 型

DATETIME 値の範囲は '1000-01-01 00:00:00.000000' から '9999-12-31 23:59:59.999999' であり

MemCacheとRedisでローカルキャッシュのread_multifetch_multiをサポート

# activesupport/lib/active_support/cache/strategy/local_cache.rb#L123
+          def read_multi_entries(keys, options)
+            return super unless local_cache
+
+            local_entries = local_cache.read_multi_entries(keys, options)
+            missed_keys = keys - local_entries.keys
+
+            if missed_keys.any?
+              local_entries.merge!(super(missed_keys, options))
+            else
+              local_entries
+            end
+          end


つっつきボイス: 「RedisとかMemCacheのAPIで1個ずつアクセスするより一括で取ってくる方が速いんで、そうなるように拡張系の命令を使ったと: まあ書いてあるとおりですねw」

シリアライズのinclude:が効かなくなることがある問題を修正

# activemodel/lib/active_model/serialization.rb#L180
         unless includes.is_a?(Hash)
-          includes = Hash[Array(includes).map { |n| n.is_a?(Hash) ? n.to_a.first : [n, {}] }]
+          includes = Hash[Array(includes).flat_map { |n| n.is_a?(Hash) ? n.to_a : [[n, {}]] }]
         end

つっつきボイス: 「ネステッドなシリアライズかー」「ま、自分はシリアライズでJSONにしちゃうこと多いけど: ハッシュをシリアライズするよりJSONにしとけばRuby以外でも使えるし」「確かにー」

RuboCopの設定でFoo::methodスタイルを禁止に

# .rubocop.yml#L159
+# Prefer Foo.method over Foo::method
+Style/ColonMethodCall:
+  Enabled: true

RuboCopのデフォルト設定ではメソッド呼び出しの::記法は禁止されていないんですね。


つっつきボイス:YAML::loadみたいな記法見たことあったな」「クラスメソッドならこの呼び方も一応できる」

::は、定数(クラスやモジュールも含む)、コンストラクタ(Array()Nokogiri::HTML()など)の参照にのみ使う
Rubyスタイルガイドを読むより


Rubyスタイルガイドを読む: 文法(1)メソッド定義、引数、多重代入

Rails 6ではUTF-8エンコーディングを強制しなくなる

ここからはRails 6のmasterブランチです。

主要なWebサイトのほとんどでTLS 1.0が無効になったことで、IE8以下のブラウザの利用がどんどん困難になった。他のブラウザには影響しないので、UTF-8エンコーディングはデフォルトでは強制しないことにする。
Andrew White


つっつきボイス: 「『これでShift_JISで書けるぜ!』なんてことにはならないだろうけどね」「nilで『強制しない』という意味なのか↓」

# actionview/lib/action_view/railtie.rb#L12
+    config.action_view.default_enforce_utf8 = nil

「昔話になっちゃうけど、ガラケー時代のエンコーディング周りはほんと地獄でしたねー: キャリアに応じてShift_JISで出力したりEUC-JPで出力したりとか、キャリアごとに顔文字変換するとか」「音符がうんこになるバグなんてのもありましたね」「そもそも携帯ネットワークはインターネットでもなければIPネットワークすらないし、RFC準拠とかなかったし」「ひえ〜」「メアドをRFC準拠の正規表現で処理したらユーザーからメアドが通らなくなったって苦情が来たり: 数字で始まったりドット2つ重ね..みたいな非RFCなメアドが使われちゃってた」

参考: 【PHPで作る】初めての携帯サイト構築 - 第3回 携帯サイトの文字コードに気をつける

新機能: "rails routes --expandedを追加

$ rails routes --expanded
--[ Route 1 ]------------------------------------------------------------
Prefix            | high_scores
Verb              | GET
URI               | /high_scores(.:format)
Controller#Action | high_scores#index
--[ Route 2 ]------------------------------------------------------------
Prefix            | new_high_score
Verb              | GET
URI               | /high_scores/new(.:format)
Controller#Action | high_scores#new
--[ Route 3 ]------------------------------------------------------------
Prefix            | blog
Verb              |
URI               | /blog
Controller#Action | Blog::Engine

[ Routes for Blog::Engine ]
--[ Route 1 ]------------------------------------------------------------
Prefix            | cart
Verb              | GET
URI               | /cart(.:format)
Controller#Action | cart#show

こんな感じで出せるそうです。


つっつきボイス: 「これうれしい!」「Route 1はちょいダサかな」「いつものrails routesだとURLがめちゃ長くなりますからね」

新機能: ActiveModel::Attributes#attributesを追加

# activemodel/lib/active_model/attributes.rb#L69
+    def attributes
+      @attributes.to_hash
+    end

つっつきボイス: 「アトリビューツアトリビューツw」「何という名前」「その実態は#to_hashと: ということはattributesはハッシュじゃないのかな」「あと#to_hashすることでオブジェクトが別になるからdupしていることになる」

システムテストのスクショのパスを絶対パスに変更

ログからすぐ開くのに便利だからだそうです。

# actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L46
           def image_path
-            @image_path ||= absolute_image_path.relative_path_from(Pathname.pwd).to_s
+            @image_path ||= absolute_image_path.to_s
           end

つっつきボイス: 「こういう変更は地味に大事!マジで」「Pathname.pwdもUnixのシェルコマンドそのまんま」「先週のウォッチで出たrm_rfみたい」

Rails

Rails 5.2.0の良スライド3本立て


つっつきボイス: 「TechRachoでも5.2.0をまとめようと思ってたんですが、重要な部分はこのスライド3本でほぼ網羅されているんで、もういいかなと」「いいと思いまーす」「『ここを見ろ、以上』ということでー」

そのまま一同でしばしスライドつっつきになだれ込みました。

apply_join_dependencyかー」「association scopeのJOINが無視されてた話とか、つらいなー」

Webpack 4.0がリリース


auth0.comより


  • Node JS 4のサポート廃止: 今後はNode >= 8.9.4で
  • さよならCommonsChunkPlugin、こんにちはSplitChunksPlugin
  • WebAssemblyをサポート
  • javascript/autoなどのModule Typeをサポート
  • developmentモードとproductionモードを導入
  • webpack.config.jsでのエントリポイント定義が不要に
  • ビルドの高速化
  • プラグインシステムの刷新
  • コマンド体系がwebpck-cliに全面移行(webpack-cliは今後インストール必須)
  • NoEmitOnErrorsPluginなどの非推奨化

つっつきボイス: 「Node JS 4のサポート廃止は割りと大きいかも: これ系に依存してるのって結構あった気がする」「Zapierは"node.js v4.3.2"ってなってますね」「WebAssemblyもいいな」

書籍『99 Bottles of OOP』


sandimetz.comより

名著『オブジェクト指向設計実践ガイド』でおなじみのSandi Metz女史の新刊が昨年から発売されています。ちょうど翻訳まで終えた記事「Why We Argue: Style — Sandi Metz」の末尾の広告で知りました。セールに気づけばよかった...

同書の章タイトルだけ自分用に雑に訳してみたのですが、場所をとるのでGistに置いてみました。

なお、同書のタイトルは以下ののもじりです。宴会で一気飲みを煽るときに歌うんでしょうか。


つっつきボイス: 「↑ジャケがいい」「酔っぱらいの歌ですな」
「前作『オブジェクト指向設計実践ガイド』は手続き脳が抜けきれてない私にはすごくよかったんで、くやしいけどこの本も定価で買っちゃいました」「ワタイも買ってたのに後忘れてたー」「そういえばJavaのインターフェースって特異だから、あの考え方を前提にするとRubyではどう適用したらいいのか最初よくわかんないかもしれないですね」「それはあるかも」
「たとえばPHPやPerlみたいな世界からRuby脳に変わるときにはオブジェクト指向設計ができてないといろいろ大変っすね: Rubyのライブラリがそもそもオブジェクト指向全開なものが多いし」「とにかくこういう本は一冊読んでおくべき」

参考:

ActiveRecord.no_touchingでtouchingを一時的に無効化する(RubyFlowより)

# 同記事より
user = User.find(user_id)

ActiveRecord::Base.transaction do
  User.no_touching do
    user.photos.find_each do |photo|
      # userはtouchされない
      photo.update!(some_attributes)
    end
  end

  user.touch
end

つっつきボイス: 「む、サイトが開かない」「落ちてるかな?」

今は動いています。

参考: Rails API no_touching

KubernetesデプロイのためにRailsをリファクタリングした(RubyFlowより)

# 同記事より
require 'yaml'
require 'erb'

class ConfigParser
  def self.parse(file, environment)
    YAML.load(ERB.new(IO.read(file)).result)[environment]
  end
end

つっつきボイス: 「Kubernetesはこれだけconfigしないといけない↓のが大変: それぞれenvをどうやって注入するかとか」「そういうコンテナサービスについて気を付けるべき点は例の超定番『The Twelve-Factor App』で言われてますね」

  • ローカルアプリ
  • Dockerコンテナを使うローカルアプリlocal app using docker containers
  • docker-composeを使うローカルアプリ
  • CapistranoをOpenStackとベアメタルサービスにデプロイ
  • Kubernetesからminikubeと実際のクラスタにデプロイ


12factor.netより

そういえばRuby25の会場でtagomorisさんが「クバネーティス」と発音していました。個人的には「クーベルネイテス」の方が何だかドイツ語っぽくてええかなという気もしたり(↓ギリシャ語由来だそうです)。

タイムゾーン関連記事2本(Hacklinesより)

いずれも短い記事です。

# 同記事1より
class ApplicationController
  around_filter :set_time_zone

  private

  def set_time_zone
    old_time_zone = Time.zone
    Time.zone = 'Asia/Kolkata' # current_user.time_zone
    yield
  ensure
    Time.zone = old_time_zone
  end
end
# 同記事2より
  def in_time_zone(zone = ::Time.zone)
    time_zone = ::Time.find_zone! zone
    time = acts_like?(:time) ? self : nil

    if time_zone
      time_with_zone(time, time_zone)
    else
      time || self.to_time
    end
  end

つっつきボイス: 「うんうん、マルチロケールのアプリでこういうのやるよね: 弊社のManga Rebornでもそういうコード書いた覚えある」「記事1はTime.zone使ってて、記事2はTime.zone使うなin_time_zone使えって言ってるー」
Time.zoneってクラス変数だった気がするんだけど、マルチスレッドだと死ぬやつじゃね?」「それともconfigか? configならスレッドスコープ」「あ、両方か↓: config.time_zoneTime.zone」「一時的に使うだけならTime.zoneでやるなということね」

# http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.htmlより
# application.rb:
class Application < Rails::Application
  config.time_zone = 'Eastern Time (US & Canada)'
end

Time.zone      # => #<ActiveSupport::TimeZone:0x514834...>
Time.zone.name # => "Eastern Time (US & Canada)"
Time.zone.now  # => Sun, 18 May 2008 14:30:44 EDT -04:00

参考: Rails API in_time_zone

外部キーなしでActiveRecord関連付けを行う(RubyFlowより)

# 同記事より
def find_target
  # ... あまり関係ないコードも混じってるのであしからず ...
  sc = reflection.association_scope_cache(conn, owner) do
    StatementCache.create(conn) { |params|
      as = AssociationScope.create { params.bind }
      target_scope.merge(as.scope(self, conn)).limit(1)
    }
end

つっつきボイス:unscope?」「unscopeは割りと使いますよ: デフォルトスコープのorderだけ消したりとか」「今はreorderとかあるけど」

Railsのdefault_scopeは使うな、絶対(翻訳)

rails_refactor: 名前リファクタリングgem(Hacklinesより)

https://www.youtube.com/watch?v=-sX05s0STs8


つっつきボイス: 「あー、これコントローラ名をリファクタリングするgemか」「IDEの機能一発でできるかなと思ったんですが」「できないんですねこれが: routes.rbとかビューとかあちこちリネームが必要になるんで地味ーに面倒」「ときどき直し漏れがあったり: でgit commitするときに気づくと」
「まーGemfileに追加してまでやることかな?とは思う」「使い捨てですかね」「でもこの機能がRailsに標準で取り込まれるならわかるし、あったらすごくうれしい: rails generate renameみたいな感じで」「あー!それ欲しいかもー!」

searchkick: ElasticsearchとRailsでインテリジェント検索(Awesome Rubyより)

ankaneさん作のgemです。

# 同リポジトリより

# モデル
class Product < ApplicationRecord
  searchkick
end

# インデックスにデータを追加
Product.reindex

# クエリ
products = Product.search("apples", fields: [:name])
products.each do |product|
  puts product.name
end

つっつきボイス: 「へーこういう曖昧マッチが効くのか↓」「Elasticsearchのハンドラ的なやつっぽいけど、結構何でもできそうに見える」

  • stemming - tomatoes matches tomato
  • special characters - jalapeno matches jalapeño
  • extra whitespace - dishwasher matches dish washer
  • misspellings - zuchini matches zucchini
  • custom synonyms - qtip matches cotton swab

Clowne: Rubyモデルをクローンするgem(RubyFlowより)


同記事より

# 同記事より
# app/cloners/order_cloner.rb
class OrderCloner < Clowne::Cloner
  include_association :additional_items
  include_association :order_items, scope: :available

  nullify :payed_at, :delivered_at

  finalize do |source, record, _params|
    record.promotion_id = nil if source.promotion&.expired?
    record.uuid = Order.generate_uuid
    record.total_cents = OrderCalculator.call(record)
  end
end

Clowneは「道化師」(clown)とクローンを掛けてますね。


つっつきボイス: 「ははぁ、上の図↑みたいにリレーションがチェインしているものをクリーンにクローンできるってことか」「たとえばユーザーアカウントの項目が複数のテーブルでできていて、そのアカウントをコピーしたい、でもリレーション先のマスターはコピーしたくない、とか」
「ところで他人が書いたdupとかって基本信じたくないというのは、ありますね」「あーたしかにdeep copy的なのは自分で実装しないとコワイw」「ActiveRecordに特化してそういう部分をやりやすくしてくれるgemなんでしょう、きっと」「複雑なやつをいっぱいクローンしないといけないときとかにはありがたいかも」
「そういえばJavaだとこの手のcloneメソッドは自分で書かないといけないようになってましたね」「ですですー」

Overcommitで各種静的解析を呼んでRubyコードをlintする(Random Rubyより)

Git Hookを使ってコミット時のフックでRuboCopなどを呼んでいます。



同リポジトリより


つっつきボイス: 「社内で使ってた人がいたのを思い出したので」「Overcommitは、基本入れた方がいいですね: CIが重いとつらくなるけど」「CIがfailしたらgit commitが失敗するようにしたり」「それはスバラシイ!」

「お、ちょうどいいところに: Overcommitって使ってみてどうでした?」「...みんなが使ってくれないと意味がないかも...」「あ確かに」「CI側をがっつり設定して、CIがfailするものをプッシュするとすごく怒られるようにしておけば、みんな自主的にこういうツールを使うようになるかも」

VAPIDでプッシュ通知

# 同記事より
# app.rb
post '/push' do
  Webpush.payload_send(
    message: params[:message]
    endpoint: params[:subscription][:endpoint],
    p256dh: params[:subscription][:keys][:p256dh],
    auth: params[:subscription][:keys][:auth],
    ttl: 24 * 60 * 60,
    vapid: {
      subject: 'mailto:sender@example.com',
      public_key: ENV['VAPID_PUBLIC_KEY'],
      private_key: ENV['VAPID_PRIVATE_KEY']
    }
  )
end

正直、プッシュ通知しようとするサイトはむかつきますが。


つっつきボイス: 「RFCだから一応標準」「Webプッシュで認証/承認周りをやってくれるのね」

参考: Web PushをFCMとVAPIDで認証してブラウザにプッシュ通知を送る

Proxyパターンを再考する(Hacklinesより)

#prependをProxyパターンで使うお話です。

# 同記事より
module Proxy
  require 'etc'

  # Dynamically re-creates receiver's class methods, intercepts calls 
  # to them and checks user before invoking parent code
  #
  # @param receiver the class or module which has prepended this module
  def self.prepended(receiver)
    obj_mthds = receiver.instance_methods - receiver.superclass.instance_methods
    obj_mthds.each do |m|
      args = receiver.instance_method(m).parameters # => [[:req, :x], [:req, :y]]
      args.map! {|x| x[1].to_s}
      Proxy.class_eval do
        define_method(m) do |*args|
          puts "*** intercepting method: #{m}, args: #{args}"
          raise "Unauthorised access!" unless Etc.getlogin == 'fred'
          super(*args)
        end
      end
    end
  end
end #module

class Account
  def initialize(balance)
    @balance = balance
  end

  def deposit(amount)
    @balance += amount
  end

  def withdraw(amount)
    @balance -= amount
  end

  def self.interest_rate_for(a_balance)
    a_balance > 10_000 ? '3.2%' : '5.5%'
  end

  prepend Proxy

end

つっつきボイス: 「変更前のコードの方、method_missingしてsendするとかエグいなー: Javaのひとたちはこういうコードが許せなかったりとか?」「いやーそこまではないかもー」「これは認証のプロキシなのか!: 権限がなければraiseして、権限があればデレゲートすると」「天才か?」

「で変更後のコード↑はというと、method_missingを使わずに、prependの中でclass_evaldefine_method使ってやると」「たしかにー: 変更後の方がキレイ」「とってもProxyパターン」

Ruby: Proxyパターンの解説(翻訳)

参考: Module#prepend

CertBot: Let's Encrypt証明書をもっと楽に導入


certbot.eff.orgより: (CC BY

Let's Encrypt Ruby on Rails and Nginxにしようかと思ってたのですが、記事中のこちらの方が気になったので。

主催しているEFFはElectronic Frontier Foundationという非営利団体です。


つっつきボイス: 「CertBotは有名っすね」「あれLet's Encrpyptコマンドじゃなかったっけ?」「↓名前変わってた...」「ややこしいのう」

Certbot クライアント(旧・Let's Encrypt クライアント)
https://letsencrypt.jp/command/より

「まあapt-cache searchしてあるほうを入れればいいかとw」「多分ディストリビューション公式のパッケージ使う方がそのdistroのapache/nginxバージョンにちゃんと合わせられてるので、機能的な問題とかない限り、無理に最新にこだわらない方が安心して使えそう」

参考: Wikipedia-ja 電子フロンティア財団

dev.toは記事のソーシャル画像をこうやって自動生成している(Hacklinesより)

# 同記事より
  def enter_urls
    urls.each do |url|
      3.times do
        enter_url_and_click_preview("#{url}?#{rand(10_000)}=#{rand(10_000)}")
      end
      enter_url_and_click_preview(url)
    end
  end

つっつきボイス: 「SEO業界では記事の冒頭に何か大きい画像を置いとくとアクセスが増えるみたいなのがありますね」「神社の御札みたいなw」「まあ確かにそういう画像があると視線の取っ掛かりにはなりそう」「文字ばっかりの記事よりはデザイン的な座りもよくなりそう」「randかよ↑」

Railsコンソールで便利なヘルパーメソッドを書く(RubyFlowより)

オーストラリアの方だそうです。

# 同記事より
module ConsoleMethods
  def load_jwt!
    token = ::JWT.create(user_id: 'USER_ID_HERE')
    RequestLocals.store[:jwt] = token.jwt
  end
end

つっつきボイス: 「へーConsoleMethodsを拡張するとRailsコンソールでいろいろやれるのか」「Railsコンソールをそこまで使うかどうかというのはあるけど、利用頻度が高いならこうやってヘルパー化しとくといいかも」

RailsをOracleに接続する手順(RubyFlowより)

# 同記事より
default: &default
  adapter: oracle_enhanced
  database: "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=localhost)(Port=1521))(CONNECT_DATA=(SID=xe)))"

development:
  <<: *default
  username: "myproject_development"
  password: "myproject_development"

test:
  <<: *default
  username: "myproject_test"
  password: "myproject_test"

production:
  <<: *default
  username: "myproject_production"
  password: "myproject_production"

oracle-enhancedアダプタはdb:createができないらしいので、SQLで直接やってます。


つっつきボイス: 「来たなオラクル: 考えたくないヤツ」

Algolia: 爆速リアルタイム検索APIサービス


algolia.comより

とりあえずデモはめちゃめちゃ速いです。


つっつきボイス: 「そのデモサイトで適当に映画のタイトルぶっこんでみてください」「おーマジ速いわこれ!」「しかもUIカッケ~」「日本語だとあんまり引っかからないかも?」
「こういうの真面目にスクラッチから設計して作ってこれだけの性能出すのはタイヘン」「Solrとかカテゴリテーブルとか色々設計してSQLをWHERE文なりGROUP文なりを地獄のような感じで設計するとか」「有料だけどこれ使って速くなるなら使ってもええんじゃね?と思う」「裏でElasticsearchとか動いてるのかな」


algolia.com/productより

redis-cell: Redisをコマンドラインで使える

とりあえず手元で動かしてみました。Java 8入れろと言われました。


つっつきボイス:libredis_cell.soを読み出せる」「soできる!」「これで差し替えっぽく使えるという感じかな」

MonitでRailsアプリを監視(RubyFlowより)


mmonit.com/monit/より

監視というとやっぱりイヌですね。


つっつきボイス: 「Monitなつかし!」「こないだSupervisor入れようと思ってたら環境古すぎてMonit入れたけどなっ」「Monitは定番、かつめちゃ歴史長い: いわゆるスーパバイザです」「↓こういう処理とか、やりたいと思うことはひととおり書ける優秀なヤツ」「configはところどころよくわからないけど」

<!-- 同記事より -->
<!-- config/deploy/shared/monit.erb -->

check host <%= fetch(:website_url) %> with address <%= fetch(:website_url) %>
  if failed
    icmp type echo count 5 with timeout 15 seconds
  then alert

Datadog: サイト監視・分析サービス


datadoghq.comより

いっぬがカワイイ。無料プランで5ホストまでできるそうです。


つっつきボイス: 「こっちの方がかわいかったので」「そこ!?」「このDatadogも定番: サービス監視/サイト監視にも使うし、メトリック監視にも使われる」

DHHとconcerns


同ツイートより


つっつきボイス: 「おー大量のconcern!」「mixinがとてもうまく書かれているとこうなる」「しかし1回しか使わないようなmixinをconcernにするかと言われると...」「ですねー」

「これ厳密にはconcernじゃないかもしれないっす: Basecampのディレクトリ構成って、app/の下にこの場合はRecordings(複数形)というディレクトリを作って、その下にこういうのが置かれていました」「へー!」「concernで置きまくるんじゃなくて、あるモデルの配下にそれ用のモジュールを入れるみたいなフォルダ構成なんで、それならまあありかなとは思いました」「あーモデル名と同じフォルダが別にあってその下に置くと: それならワカル」「つまりincludeだけどあちこちで使われるんじゃなくて、あくまでそのモデル用のmixinか」「RuboCopの『1クラス100行制限』で怒られないためにはこのぐらい分散しないと」「例のYouTubeの番組を見た限りではそんな感じでした」

「このincludeは互いの依存関係のあるなしに応じてきれいに書き分けられているからとても読みやすい」「ここまでキレイに書けたらスゴイ」「includeは順序変わると動かなくなったりしがちですね」

「ところでDHHのYouTubeチャンネル、早くも一週間ほど更新止まってますね(´・ω・`)」「こりゃスターウォーズばりに次回作待たされるかもww」

「あとDHHの書き方なんですが、もう全然TDDじゃないんですよ」「お?」「モデルのテストすら全部振る舞いベースで、unitテストを書かないんで、スゲーなーと」「まあ確かに、自分で書いていない、提供されている機能だけを使うんだったらそのunitテストってなくてもいいんじゃね?って思ったりするな」「おー」「実はunitテスト懐疑派w」「たとえばモデルをcreateするテストとかは必要だと思うけど、そういうのはunitテストというより機能テストに近いんじゃないかな」

ここまでいける


つっつきボイス: 「ちゃんとメンテするとこのぐらいになるという見本」「しかし20msecはスゴイ」

Ruby trunkより

Ripperの新機能使いたいからnobuさんのパッチ使わせて

irbでRipperを使いたいそうです。確か今のirbはRubyで書かれた独自パーサーでした。

参考: Rubyリファレンスマニュアル Ripper

Ruby 2.5.0の「逆順バックトレース」がつらすぎる

「Railsで開発していると、バックトレースが逆順だったりそうでないところがあって頭がおかしくなりそう」だそうです。


つっつきボイス: 「何で逆順にしたんだろね?」「コールスタックを登っていく感じを出したかったとか?」

Ruby

Ruby 2.6.0-preview1がリリース(Ruby公式ニュースより)

Ruby生誕25周年のその日にリリースされました。

  • JITで--jit-verbose=1を指定可能に
  • 以下を含む新メソッド
  • パフォーマンス向上
    • Proc#call
    • block.callにブロックパラメータを渡した場合
    • ブロック渡しのパフォーマンス全般
  • その他
    • $SAFEがプロセスグローバルになり、0を渡せるようになった
    • ERB.newの引数の変更

とりあえず記念写真。

SinatraベースのSmashingとWordPressとGitHubウィジェットでイケてるダッシュボードを作った(RubyFlowより)


同記事より

マジックコメント一発でRubyを最適化

# 同記事より
# frozen_string_literal: true

HASH = {
  "mike": 123
}

def getmike
  HASH["mike"]
end

コメント欄で「細かい点がちょっと違うんじゃ?」とツッコまれています。


つっつきボイス: 「Ruby 2.2以降はハッシュキーのstring literalを自動でfreezeするのかー」「String.newと空文字""リテラルのエンコーディングは違う...だと?↓String.new使わんけどなっ」「本編記事よりコメントの方が情報量多いかも」

String.new.encoding
# => #<encoding:ascii-8bit>

"".encoding
# => #<encoding:utf-8>

オブジェクト指向だと何ができるようになるか(Ruby Weeklyより)

これもSandi Metz女史のがっつり読み物系記事です。

Rack::Proxyクイックツアー(RubyFlowより)

Rack Proxyはちょっと工夫するといい感じになるそうです。

  • サブドメインベースで複数のアプリにパススルーする
  • 移動したページへの面倒なリダイレクトルールを扱うのに便利
  • 単一のAPIリクエストを複数のコンカレントバックエンドリクエストに分散し、結果をマージする
  • 認証/承認をリクエストのプロキシより優先的に内部の信頼できるバックエンドに無条件に投げる
  • あるドメインから別のバックエンドへのプロキシでCORSが複雑になるのを回避する

つっつきボイス: 「Rackミドルウェアでやるのは確かに簡単で便利: 裏を返すと、Nginxの設定がいかに死ぬほど特殊で面倒くさいかということでもある」「それこそApacheのmod_rewriteに匹敵する地獄感を味わえますよ」「sendmail.cfとか」

参考: Mozilla オリジン間リソース共有 (CORS)

Rubyで文字列の重複を削減する(Ruby Weeklyより)

# 同記事より
if ENV['RAILS_ENV'] != "production"
  exec "RAILS_ENV=production ruby #{__FILE__}"
end

require 'memory_profiler'

MemoryProfiler.report do
  # this assumes file lives in /scripts directory, adjust to taste...
  require File.expand_path("../../config/environment", __FILE__)

  # we have to warm up the rails router
  Rails.application.routes.recognize_path('abc') rescue nil

  # load up the yaml for the localization bits, in master process
  I18n.t(:posts)

  # load up all models so AR warms up internal caches
  (ActiveRecord::Base.connection.tables - %w[schema_migrations versions]).each do |table|
    table.classify.constantize.first rescue nil
  end
end.pretty_print

frozen_string_literal: true以外にもいくつかRubyの文字列のdupを防ぐ方法を試しています。


つっつきボイス: 「この+""って書き方↓いつも不思議でしょうがないんだよなー」「どうしてこうなった感」

buffer = String.new
buffer.encoding => Encoding::ASCII-8BIT

# vs 

# String @+ is new in Ruby 2.3 and up it allows you to unfreeze
buffer = +""
buffer.encoding => Encoding::UTF-8

Rubyで分散ファイル同期(Hacklinesより)

Ruby Distributed File SyncでRDFSだそうです。Dropbox的なことをやってみたかったとのこと。


つっつきボイス: 「こういうDropbox的なオープンソースソフトウェアありましたねー: 名前思い出せん...SynkThinkだ!」「割りとよくできますこれ: Win/Linuxでも使えるし」


syncthink.comより

Ruby 3のGuildとは


engineering.universe.comより


つっつきボイス: 「Guildの情報が意外に少なかったんですが、これが割りとまとまってるっぽかったので」

TruffleRuby Native

メモリ喰いの代わりに爆速で知られるTruffleRubyのネイティブオプションについての記事です。

MJIT記事の極めつけ

英語版まで出してます。


つっつきボイス: 「この間の翻訳記事↓より後に公開されててちょっとほっとしました」「MJITの作者自らの記事には勝てないっしょw」

Rubyの新しいJIT「MJIT」で早速遊んでみた(翻訳)

こういう書き方


つっつきボイス: 「『とかしてなくて』w」「自分もアクセサでやっちゃったりするかなー: メンバ生で触るの怖いときとか」「まあ隠しとけと言えばそれまでだけど」

MatzのRuby25スピーチまとめ

RubyKaigi 2018 CFP締め切りの駆け込みっぷりが凄い

サイト: RubyKaigi 2018 closed


rubykaigi.orgより

あるあるとはいえ、笑ってしまいました。

SQL

「Why upgrade PostgreSQL?」: PostgreSQLのバージョンごとの修正点を比較表示できるサイト(Postgres Weeklyより)


つっつきボイス: 「これ便利かも」「出力はベタベタっすね...」「読みづらっ!」

(動画)KubernetesネイティブのPostgreSQL(Postgres Weeklyより)

AWS RDSがPostgreSQL 10をサポート(Postgres Weeklyより)

JavaScript

2018年のJavaScript事情(JavaScript Weeklyより)

Reduxの原則に沿ってReact.jsでフロントエンド検索ウィジェットを作る

Mozillaのsource/mapのパフォーマンスをRustとWebAssemblyで改善(JSer.infoより)

TypeScript Deep Dive


つっつきボイス: 「ところで音声読み上げってヒアリングの練習にいいかも」「最近の英語音声読み上げのクオリティ凄いし」

Vue.jsとVuexで自動セーブする

CSS/HTML/フロントエンド

簡単なものはいずれ面倒になる(Frontend Weeklyより)

制約条件の理論をソフトウェアに適用する(Frontend Weeklyより)

「制約条件の理論」は経営寄りの概念だそうです。

参考: Wikipedia-ja 制約条件の理論

Utility-First CSSと関数型的CSS(Frontend Weeklyより)

Go言語だけでフロントエンドする

先週取り上げたhttps://easydatawarehousing.github.io/ferro/にも通じそう(こちらはRubyとOpalとFerro)。

30 Seconds of CSS: CSSスニペットあんちょこサイト(GitHub Trendingより)


atomiks.github.ioより

スニペット数はまだそんなにありませんが、1週間ほどで★1600超えです。


つっつきボイス: 「お、これも中々便利じゃん?」「この間の30 seconds of codeに通じますね」

Elm言語: ブラウザベースの純粋関数型言語

Sandi Metz氏が最近関心を持っているとのことなので。

その他

SourceTree Windows版が更新

Diesel: Rust向けORM & クエリビルダ


つっつきボイス: 「社内のRust勢向けにと思って」

Dockerイメージを小さくする3つのコツ

どのネットワークかと思ったら

開発手法

ITエンジニアには筋トレが大事

私も痛感しています。


つっつきボイス: 「筋肉といえば、ウェブ魚拓の人の筋肉の付き方はヤバイですね」「ガチムチやん...」

コアもOSもシェルも自作

Six Degrees of Wikipedia: Wikipediaの記事のつながりをグラフ表示

よくあるやつといえばそれまでですが、めちゃめちゃ速いです。

Hemingway.app: 英文添削できるエディタ

ちなみに世にあるエッセイ向け英文スタイルガイドの種本のほとんどは、The Elements of Styleだったりします。もう100年近いロングセラー。

論文だとChicago Manual of Styleが定番だったかな。

「パスワード無期限」が推奨に

番外

GitHub issueをブログ代わりに

内容よりそっちがびっくりだったので。

prompts: JSらしいプロンプト(GitHub Trendingより)

AppleのクラウドはGoogleのクラウド

参考: Appleのクラウドサービス「iCloud」がGoogleのクラウドを利用していることが正式に明らかに - GIGAZINE

敷き詰め問題

これ系の問題はたいてい難問になってる気がします。


つっつきボイス: 「先に進むとヤケクソで並べたようなヤツとかあるなー確かに」「草」「この直感に反する感がタマラン」

「プログラマーの誓い」


私はプログラマーとして、以下の誓約を果たすことを誓います。
* 仕事を誠実に、かつ倫理から逸れぬよう進めます。人々に害をなすいかなる要求にも従いません。
* 先人の学びを尊重し、かつ自分の学びを後進と共有します。
* プログラミングは技術であると同時に、科学であり、思いやりであり、共感でもあることを決して忘れず、精巧なアルゴリズムや技術上の論争よりも理解することの方が重要であることも決して忘れません。
* 「わかりません」と言うことを恥じず、困ったときは的確に支援を求めます。
* ユーザーのプライバシーを尊重します。プライバシー情報は、たとえ世界中が知っていようとも自分には明かされないものだからです。
* あらゆる物事を生涯にわたって注意深く扱い、自分がミスをする可能性があることを謙虚に認めます。
* コンピュータのためでなく、人間のためにコードを書くことを決して忘れません。
* 自分の書くコードや自分の行いがもたらす可能性のある結果について常に配慮し、社会的な問題と技術上の問題、どちらの困難についても一方を軽んずることなく同様に尊重いたします。
* 誇りを失わず、勤勉に仕事に専念いたします。
* 自分がいつかは間違いを犯し、間違ったまま進む可能性があることを認めます。先入観に囚われず、誰の言葉であっても決して侮ることなく尊重し注意深く耳を傾けます。
同リポジトリより: 大意

ひと目で分かるヒポクラテスの誓いのもじりですね。

蛇腹型ロボット

Snake-inspired robot uses kirigami to move | Harvard John A. Paulson School of Engineering and Applied Sciences

マヤ文字作文


つっつきボイス: 「そういえば最近カクヨムで読んでるこの小説↓、解説も凝ってて言語マニアにはたまらんかもですヨ」


今週は以上です。

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

週刊Railsウォッチ(20180223)Ruby25開催、Rails6のパラレルテスト、書籍「RSpecによるRailsテスト入門」更新ほか

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

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

Ruby 公式ニュース

Rails公式ニュース

Ruby Weekly

Awesome Ruby

Random Ruby

RubyFlow

160928_1638_XvIP4h

Hacklines

Hacklines

Postgres Weekly

postgres_weekly_banner

Frontend Weekly

frontendweekly_banner_captured

JavaScript Weekly

javascriptweekly_logo_captured

JavaScript Live

jslive_logo_captured

JSer.info

jser.info_logo_captured

Github Trending

160928_1701_Q9dJIU


CONTACT

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