こんにちは、hachi8833です。今回の「公開つっつき会 第2回」にお集まりいただいた皆さま、ありがとうございました!おかげさまで盛況のうちに終わり、懇親会も盛り上がりました。
- 各記事冒頭にはでパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話です
- お知らせ: 来週9/17と9/23は月曜祝日のため、週刊Railsウォッチはお休みをいただきます。次回は10/1(月)となります。
Rails: 先週の改修(Rails公式ニュースより)
ActiveJobにretryやdiscardなどのフックを追加
- PR: Add hooks to ActiveJob around retries and discards by steves · Pull Request #33751 · rails/rails
# activejob/lib/active_job/logging.rb#L91
+ def enqueue_retry(event)
+ job = event.payload[:job]
+ ex = event.payload[:error]
+ wait = event.payload[:wait]
+ error do
+ "Retrying #{job.class} in #{wait} seconds, due to a #{ex.class}. The original exception was #{ex.cause.inspect}."
+ end
+ end
+ def retry_stopped(event)
+ job = event.payload[:job]
+ ex = event.payload[:error]
+ error do
+ "Stopped retrying #{job.class} due to a #{ex.class}, which reoccurred on #{job.executions} attempts. The original exception was #{ex.cause.inspect}."
+ end
+ end
+ def discard(event)
+ job = event.payload[:job]
+ ex = event.payload[:error]
+ error do
+ "Discarded #{job.class} due to a #{ex.class}. The original exception was #{ex.cause.inspect}."
+ end
+ end
元の#33740の実装↓より上の実装↑の方がよいとのことです。
def before_retry(*filters, &blk)
set_callback(:retry, :before, *filters, &blk)
end
つっつきボイス:「(ゲストに)ところで皆さんActiveJobって使ったことあります?」「名前ぐらいは」「まだです〜」
参考: Active Job の基礎 | Rails ガイド
「ざっと説明すると、ActiveJobはRails 4.2で導入された機能で、それまでResqueやSidekiqやdelayed_jobなどでまちまちに行われていた非同期処理を、ジョブの抽象表現として提供するのが目的です」「ただしActiveJob自体には定期時間になったら実行するといった機能はありません: ActiveJobは一種の抽象化クラスとして、実際のジョブはそのバックエンドにSidekiqなりdelayed_jobを配置してそちらで動かすことになります」
「で今回の修正はというと、ジョブのリトライ時などにフックをかけられるようにしたということのようですね」「…だいたいChangelogに書いてあるとおりかも: とりあえずログに出してくれるようになったし」「あー確かにリトライのときとかログに出したい」「…リトライでログが出てくれれば、何だか無限ループっぽいときにも一瞬でわかるけど、ログがないとみっちり調べないとわからないし」
「ちなみにコードにも出ているActiveSupport::Notifications
は、ActiveSupport標準のpub/subの仕組みですね: Railsのあちこちで使われているヤツ」
参考: ActiveSupport::Notifications
「なおActiveJobはまだ足りない機能が結構あるんで、実はあんまり使ってない」「おほ」「使ってみるとわかるんですけど、たとえばSidekiqだったらできることができなかったり: SidekiqってそのまたバックエンドにRedisがあってRedisのブロッキング系コマンドが使えるので『何時間後に実行』みたいなスケジューリングができるんですけど、ActiveJobにその抽象化がないので、ActiveJobでジョブを作るとそういうのができない」「ActiveJobで試しに書いたものの結局Sidekiqを生で使いましたね」「このあたりもうひと頑張りして欲しいところ」
参考: リスト型 — redis 2.0.3 documentation — ブロッキング系コマンドの解説
「BasecampではActiveJobってどう使ってるんだろう?」「あ、スケジューリングとかしない普通の非同期ジョブならActiveJobでできます: 本来単なる非同期ジョブとスケジューリングは別の話ですし」「スケジューリングとかはwheneverとか使ってもできますが、cronが必要だし、RedisやSidekiqならそういうのもできるからそっちでやっちゃいますね」「まあwheneverよりRedisサーバーを立てる方が面倒ですが」
マルチDB対応を強化
replica
オプションを追加config["replica"]
をチェックするreplica?
をHashConfig
とUrlConfig
に追加configs_for
でキーワード引数を取れるようにしたconfigs_for
でinclude_replicas
のデフォルトをfalseにするキーワード引数を取れるようにした
同PRより
つっつきボイス:「以前の(Rails 4系前半ぐらいまでの)ActiveRecord::Base
のコネクションってシングルトンだったんですよ: その頃にマルチDBやろうとしたらgemをインストールしないといけなかったんですが、何てgemだったかな…?」「octopus?」「あれは最近ほとんど更新されてない気が」
そういえば以前のウォッチではmulti_dbやswitch_pointも挙がってました。
参考: Rails4.2のコネクションプールの実装を理解する - Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)
「それが最近になってconnectionがconnectionsになる形で公式がマルチDBをある程度サポートするようになった」「config["replica"]
が入ってきたということは、Railsもますますエンタープライズアプリを志向するようになってきてこういうのが求められるようになったということでしょうね: 実際BPSでも業務系アプリの案件が増えてきてますし」「replicaだからリードオンリー向けの機能ですね」
「ところでマルチDBってやったことあります?」「いやぁまだですね」「なかなかハードです」「どんなときに使うんでしょう?」「既存のシステムのマスターデータを読みに行かないといけないときなんかがそうですね」「Railsで使うデータベースは、サロゲートキーやidカラムを使うみたいにRailsのルールで作られるんですけど、既存のデータベースは思想が違うのでそういうふうにできていない」
「マルチDBをサポートするgemにもいくつかパターンがあって、Railsが使うメインのデータベースとは別にサブのデータベースをリードオンリーで使えるものもあれば、複数のデータベースをすべて読み書きできるgemもありますね」「」「そしてマルチDBだとたいていマイグレーションがめちゃめちゃハードになるんですねこれが」
permitted_scalar_filter
のアロケーションを削減
Before:
16199 /Users/rschneeman/Documents/projects/rails/actionpack/lib/action_controller/metal/strong_parameters.r
After:
2280 /Users/rschneeman/Documents/projects/rails/actionpack/lib/action_controller/metal/strong_parameters.rb
# actionpack/lib/action_controller/metal/strong_parameters.rb#L926
- def permitted_scalar_filter(params, key)
- if has_key?(key) && permitted_scalar?(self[key])
- params[key] = self[key]
+ def permitted_scalar_filter(params, permitted_key)
+ permitted_key = permitted_key.to_s
+
+ if has_key?(permitted_key) && permitted_scalar?(self[permitted_key])
+ params[permitted_key] = self[permitted_key]
end
- keys.grep(/\A#{Regexp.escape(key)}\(\d+[if]?\)\z/) do |k|
- if permitted_scalar?(self[k])
- params[k] = self[k]
- end
+ each_key do |key|
+ next unless key =~ /\(\d+[if]?\)\z/
+ next unless $~.pre_match == permitted_key
+ params[key] = self[key] if permitted_scalar?(self[key])
end
end
つっつきボイス:「permitted_scalar_filter
?」「こんな機能が元からあったんですね」「scalarってスカラー量のこと?」「パラメータータイプでscalarと言うとたいてい『オブジェクトではない』という意味になりますね」「arrayとかhashとかでない、プリミティブな値ってことですね: ここで言うPERMITTED_SCALAR_TYPES
は、strong parametersに渡してもいい値のリスト↓ってことか!」
PERMITTED_SCALAR_TYPES = [ String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, StringIO, IO, ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile, ]
api.rubyonrails.orgより
「たとえばuser_idが数値を受け取ることを期待しているのにarrayが渡されて素通しされるといろいろヤバいので、そういうのを防ぐ」「渡された値は必ずPERMITTED_SCALAR_TYPES
のどれかになると」「これにないものは明示的に許可しないとrejectされるので、idにうっかりarrayが入ったりしなくなる」「UploadedFile
があることからしてそんな感じですね」「このフィルタ、毎回呼び出されそう」「そのあたりが高速化したということのようだ: ここではキーをgrepするよりeach_key
使った方が速いってことかな」
参考: Action Controller の概要 / 4.5 Strong Parameters | Rails ガイド
関連付けで複数形を指定した場合にもinverse_of
できるように修正
# 同PRより
class Post
has_many :comments
end
class Comment
belongs_to :post
end
つっつきボイス:「これって以前からできてませんでしたっけ?」「このinverse_of的なヤツ↓がいつの頃からかあって、それを使うとよしなにやってくれるんですけど、自分はこういうのあまり信用してないので基本使わない」
# activerecord/lib/active_record/reflection.rb#L614
def automatic_inverse_of
if can_find_inverse_of_automatically?(self)
inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
return unless can_find_inverse_of_automatically?(self)
「これこれ、この記事↓にもあるinverse_of
」「これですかー」「その記事で言うとinverse_of: :commentable
と書くとcommentableからもarticleを参照できるようになる: 改修はこれにplural associationを指定できるようになったってことでしょうね」
「打てなくてもとりあえず打席に立つ感じでRailsウォッチ毎週読んでるんですが、毎回知らないことだらけ」「私もです」「自分たちもウォッチで最初Railsのコミットを追い始めた頃はわけわからないことだらけでしたけど、1年もやってるうちにだんだん既視感が育ってきますね」「そうそう」「自分が覚えてなくてもつっつきに参加した誰かが覚えてたりとか: ウォッチをずっとやってきたメリットのひとつ」
参考: Rails 5 以上 + ActiveRecord での inverse_of オプションの使いどころ - Qiita
aroundコールバックでchanges_applied
が適用されていなかったのを修正
AR::AttributeMethods::Dirty
の修正です。
# activerecord/lib/active_record/attribute_methods/dirty.rb#L167
def _update_record(*)
- partial_writes? ? super(keys_for_partial_write) : super
+ affected_rows = partial_writes? ? super(keys_for_partial_write) : super
+ changes_applied
+ affected_rows
end
def _create_record(*)
- partial_writes? ? super(keys_for_partial_write) : super
+ id = partial_writes? ? super(keys_for_partial_write) : super
+ changes_applied
+ id
end
つっつきボイス:「先週も出てきたDirty
周りですね」「来たなw: Dirty
つらい」「around系コールバックが行われた時点ではもう保存されてdirtyではなくなっているのに、dirty扱いになってたのはバグ」「『should be cleared』はそういうことですね」「after系ではできてたのにaroundではできてなかったと」「この場合aroundというのは…?」「aroundはbeforeとafterをyield
を使って両方いっぺんにやったのと同じ挙動ですね」「そうだったのか!」「そうそう、aroundの場合もyield
の後で状態が変わってないといけない」「ActiveModelにはこの種のコールバックがいろいろあって、それぞれにbeforeやafterやaroundがあります↓」
参考: Active Record コールバック 「利用可能なコールバック」| Rails ガイド
「先週も少し話しましたが、ついでにDirty
も説明: ActiveRecordのattributeを=
で更新してsave
したときに、save
する前の値が取れるというキモい機能」「おぉ」「更新をsave
したはずなのに」「直前の値が取れるというのは何かと便利なんですけど、トランザクションがネストするとわけわからなくなりがち」「saved_changes?
(以前はchanged?
)みたいに更新があったかどうかを保存後に調べられるメソッドもあります」
「…監査ログ的な実装で、管理者が変更すると『xxが更新されました』という通知を出すときに使ったりとか」「うーん、自分はそこではDirty
はあんまり使わないかなー: papertrailとかにやらせてデータベース更新のときに取ればいいじゃん派」「自分はgem使わなくてもafter_create
の後でDirty
で取ればいいじゃん派」「papertrailの方が自動でできるし楽じゃないですか」
「ちなみにpapertrailはデータベースの変更履歴を全部取っておいてくれるgem」「ただしattributeが1つでも変わると1レコード追加されるので、これで保存したテーブルは死ぬほどでかくなる: まあひたすらINSERTするだけなんで、重いのはSELECTするときだけなんですけど」「…がっつり監査ログを取りたいというよりは、日本語的な意味でログを出したい: 『xxさんがパスワードを変更しました』通知をメールで出すみたいな」「そういう軽めの処理にはDirty
が向いてますね: とりあえずsaveした後にchanged?
チェックすればさっとやれる」
ActionPackのcaching/fragments.rbのアロケーションを削減
こちらはコミットリストから見繕いました。
# actionpack/lib/abstract_controller/caching/fragments.rb#L88
def combined_fragment_cache_key(key)
head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
[ :views, (ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]), *head, *tail ].compact
cache_key = [:views, ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"], head, tail]
cache_key.flatten!(1)
cache_key.compact!
cache_key
end
つっつきボイス:「flatten!(1)
って何やるんだっけ…ああ深さの指定か↓」「Rubyを使っていて感激するメソッドのひとつですね: PHPでこういうのやろうとするとダルい」「これはプルリクメッセージにあるとおりかな」「ですね: headとtailをsplatの*
で取るより深さ1でflatten!(1)
する方が速いよと」
# docs.ruby-lang.orgより
# 平坦化の再帰の深さを指定する例。
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(1) #=> [1, 2, 3, [4, 5]]
参考: instance method Array#flatten
(Ruby 2.5.0)
「こういう最適化してくれないJITしょぼいな」「まあまあ、C++みたいなコンパイル言語ならこのぐらいの最適化はやるでしょうけど、Rubyの場合オーバーライド可能ですし大変だと思いますよ」「フラグメントキャッシュは呼び出しすごく多いから、こういう最適化は効きそう」
参考: Rails のキャッシュ: 「フラグメントキャッシュ」| Rails ガイド
番外: attendance: #present?
を高速化するgem
- リポジトリ: schneems/attendance
#10539で一度はRailsにコミットされたものの、#29400で議論の末Railsから削除されたので、Schneemsさんがgemとして復活させたようです。
# #29400より
USING BLANK?
DEBUG -- : Comment Exists (0.1ms) SELECT 1 AS one FROM "comments" WHERE "comments"."post_id" = ? LIMIT ? [["post_id", 1], ["LIMIT", 1]]
USING BLANK?
DEBUG -- : Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 1]]
つっつきボイス:「LIMITを付けることで高速化できるみたいな話: 前にこのあたりのやりとりを見たことがある気がする」「改修するとメモリに全部読み込まれてしまうので削除されたという流れみたい」「キャッシュから読んだほうが速いこともあるだろうし」
「ところでこのattendance
gemの最適化前の"users".*
↓って何だかヤバい感」「おぉw、LIMITのあるなしとこれの違いが大きそう」
# 同gemより
# gemなし
User.where(github: 'schneems').present?
User Load (1.5ms) SELECT "users".* FROM "users" WHERE "users"."github" = $1 [["github", "schneems"]]
=> true
# gemあり
User.where(github: 'schneems').present?
User Exists (1.2ms) SELECT 1 AS one FROM "users" WHERE "users"."github" = $1 LIMIT $2 [["github", "schneems"], ["LIMIT", 1]]User.where(githu
Rails
名付けて「Event scout」ルール
イベントソーシングやイベント駆動設計の話です。Arkencyはイベント駆動関連の記事が多いので、コマンドソーシング記事も含めてイベント駆動布教の一環のようです。
つっつきボイス:「確かにイベントソーシングをアプリに適用するのは有効な手段」「こういうふうに、cancelのコールバックで処理するのではなくてpublish_event
化する形でやると」「これ自体はService Objectのようなので、Service Objectの中をイベントソーシング的に設計するということなんでしょうね」「コールバックでやるとどんどん読みにくくなるから、イベントソーシングでやろうというのはわかりみある」
# 同記事より
class CancelOrdersService
def call(order_id, user_id)
order = Order.find_by!(
customer_id: user_id,
order_id: order_id,
)
order.cancel!
publish_event(order)
end
private
def publish_event(order)
event_store.publish(
OrderCancelled.new(data: {
order_id: order.id,
customer_id: order.customer_id,
}),
stream_name: "Order-#{order.id}"
)
end
def event_store
Rails.configuration.event_store
end
end
そもそもScout ruleって何だろうと思ったら、ボーイスカウトやガールスカウトの「来たときよりも美しく」のことらしく、それをイベント化でもやろうということのようです。
スカウトルールとは: コードに触ったら、必ず何か小さな改善を施す。単にコードを読んだときやチラ見したときであっても小さな改善を施す。改善はネーミングだったり構造だったりささやかなリファクタリングだったりメソッド切り出しだったり。改善はがっつりやらず、次にそのコードに触る人が少しでも気持ちよくいられるよう心がける。次というのは1か月後かもしれないしもっと後かもしれないが。
同記事より抜粋
「来たときよりも美しく!」「コードを開いたらちょっとでも改善してから立ち去るという」「心構えの話ですね」「リファクタリングのプルリクは別にしておいて欲しいですけどね」
参考: ボーイスカウト・ルールってご存じですか? - Qiita
Rails以外のWebフレームワーク
- 元記事: Rails… Still?!?!
8月に開催されたEuRuKo 2018カンファレンスでPhusion社が発表したスピーチの紹介です。
Sinatra、Hanami、Trailblazer、Phoenix(これはElixirですが)はこれまでに見かけていましたが、以下は初めて見たので。
- Padrino: Sinatraに近いが、PadrinoアプリはRailsアプリに変換可能。コミット数と★はこの中で最も多い。
- Cuba: Rackベースで、Sinatraより速いらしい。現在はメンテされてない。
- Volt: Opalを使ってクライアントもRubyで書ける。こちらもメンテされてない。
記事では「VoltかSinatraもプロトタイピングでお試しあれ、速度が欲しいならTrailbrazerもね: 古いからといってあなどらないように」と締めくくっています。後半はメタプロのスピーチでした。
つっつきボイス:「関係ないですけど、記事英語タイトルの?!?!
の順序って、日本だと普通!?!?
ですよね?」「あー」「これってたぶん言語や出版社ごとにスタイルが異なるヤツですね: Phusionはオランダの会社なのでもしかするとオランダ風スタイルなのかも?」
そういえばスペイン語は逆さの¿
や¡
という独自の記号がありますが、英文で!
を付けていてもスペイン語訳で¡...!
を付けないことも多いようです(英文で!
が乱用されているだけという気もしますが)。
参考: 逆疑問符 - Wikipedia
参考: 逆感嘆符 - Wikipedia
「PhusionはPassengerの会社なのでついでにその話: PassengerはRailsのWebサーバーで、Ruby 1.8系の時代に一世を風靡したんですが、後に有料化してgemインストール時にバナーを出すようにしたら、あちこちでボコボコに叩かれたという」「そんな歴史があったんですねー」「でも最近は復活してますね: 自分もPassengerのRuby Enterprise Editionとか使ってましたし」
「有料のPassengerはサポートがあるのが強み: というのも昔はRailsサーバーって落ちるのが当たり前だったので」「マジで」「Rails 3をRuby Enterprise Editionで動かしてた頃なんて、リクエスト数がある程度以上になるとメモリを食いすぎて死ぬというのが当たり前に起きてたし: ちなみに皆さんはいつ頃からRubyやRailsを?」「2年前ぐらいから」「4からですかね」「おおっ健康的!いいですね~」
「あの頃はRailsをずっと立ち上げてるとRailsワーカー1個で軽く1GBはいってましたしw、リクエスト数が一定数に達したらワーカーを自滅させるPassengerMaxRequests
というあんまりな設定項目↓ありましたし」「ひえ〜」
参考: Phusion Passenger ユーザガイド, Apache バージョン — PassengerMaxRequests
「unicorn-worker-killer、めっちゃ愛用してますが」「ワーカーがどうせメモリリークしてるなら数リクエストさばいたら死んでくれという諦めの境地」「潔いですね〜」「二百三高地ですか」
「こういうの今でも使われてます?『たとえばGCを止めて』↓、適当に増えたら殺すみたいなの」「今はまず使わないっすね: 昔(Ruby 1.8頃)はOobGC入れないと全然ヤバかったけど」「OobGC?」「Out of…何だっけ?」「bandか」「bounceではなかったw」「」「OobGCは、要はリクエストが完了するまではGCを動かさないようにするという機能」「だってあの頃は半分以上GCがメモリ食ってて明らかにおかしかったし、止めたら倍早くなったし」「当時は普通にやってましたね〜」
参考: 例えば GC を止める・Ruby ウェブアプリケーションの高速化 - 2nd life
「話逸れちゃいましたが、Phusionの記事はというと」「PadrinoとかCubaとかVoltという見慣れないRuby Webフレームワークですね」「VoltってJSにある気がするけど」「ElectronがあるぐらいだからVoltもありそう」「Voltはクライアント側もOpal使ってRubyで書けると言っています」「皆さんOpalはご存知?」「RubyをJavaScriptで動かせるヤツですよね↓」「正解!productionで使うには度胸が要る、なかなかエグいヤツ」「エグいんですね」「RubyKaigiでも確か2年続けてスピーチされてましたね」「Opalは普通にトランスパイルしてる?」「そうですね、変換テーブル使ってて、integerとかはRubyとJSで挙動が違っちゃう」「WebAssemblyで動かすとかそういう楽しい話ではないと」「残念ながらそっち系の楽しい話ではないですね」
標準のCSVライブラリはどうしてコケるのか(Ruby Weeklyより)
# 同記事より
require 'csv'
require 'pp'
begin
CSV.parse( %{1, "2"} )
rescue CSV::MalformedCSVError => ex
pp ex
end
# => #<CSV::MalformedCSVError: Illegal quoting in line 1.>
begin
CSV.parse( %{"3" , 4} )
rescue CSV::MalformedCSVError => ex
pp ex
end
# => #<CSV::MalformedCSVError: Unclosed quoted field on line 1.>
pp CSV.parse( %{"","",,} )
# => ["", "", nil, nil]
つっつきボイス:「CSVは今はそこそこマシになった気がするけど」「どっちかというとCSVの仕様をどうにかせいというボヤキ記事みたいです」「CSVって結局『オレがCSVと言っているものがCSVだっ!』っていう程度のものだし」「マイクロソフトのCSVはそれなりに普及してますけどね」「どんなCSVが好き?と聞いてみるテスト」「…CSVライブラリで読み込めるのがいいCSV」
「クォーテーションやカンマがセルで使われてない場合に省略できるかどうかとか、ほんとどうでもいいルールがいろいろあるし」「…一応RFCに仕様あるんですけど誰も使ってないし」「ひど」「W3CRFCとExcelどっちか選ぶとしたらExcelですよね」
「私はタブ区切りテキスト(TSV)の方がエスケープ楽だし安心感あるんですけど、皆さんCSVを使うのはなぜなんだろう?と思って」「よくはわからないけど、結局業務システムでCSVが使われることが多いからですかね〜: TSVの方が使いやすいけど」「そうそう」
「一応CSVはCharacter Separatedなので、カテゴリ的にはTSVもCSVに一応含まれます」「へー!」「完璧に後付けですけどね」
「TSVならExcelにそのまま貼り付けられるという絶大なメリットあるのにー」「Webのフォームでも『Excelをここからここまでコピーしてそのまま貼り付けてください』っていうのよく使う」
Railsアプリの基本的なセキュリティの注意(Ruby Weeklyより)
つっつきボイス:「割と普通の内容かなと思いましたが」「yamlに式展開↓、普通やらないっすよね〜」「これやっちゃうとhtml_safe
しないと出せないから、i18nというよりはhtml_safe
ヤメレという話」
# 同記事より
# en.yml
en:
hello: "Welcome <strong>%{user_name}</strong>!"
「そして解決方法はというと、なになに、yamlのキー名を_html
で終わらせると自動的にエスケープしてくれる↓…だと…?」「やべーこれ知らなかった〜!」「しかもRailsガイドにも載っている…だと?」「これは知らなかった…が、i18nに_html
って書かせたくない感が残るw まあいいけど」
# en.yml
en:
hello_html: "Welcome <strong>%{user_name}</strong>!"
「こういうのもそもそも書かないだろうし↓、記事にあるようにpermitリストを通してからやるべき」「ところでconstantize
は文字列からクラスをnew
できるリフレクション向けの機能」「…機能限定版のeval
」「ですです」「brakemanで絶対怒られるヤツ」「brakemanは静的セキュリティチェックの定番ツールで、こういう情けないレベルの穴はだいたい見つけてくれる優秀なヤツです」
# 同記事より
class FooForm; end
class BarForm; end
form_klass = "#{params[:kind].camelize}Form".constantize # ダメ絶対
form_klass.new.submit(params)
参考: Ruby on Rails 5.2 / String#constantize
— DevDocs
参考: module function Kernel.#eval
(Ruby 2.5.0)
「これ↓はidを取ってるつもりがarrayが来てしまうヤツ」「1つ消すつもりが複数消してしまったりすると」「こういうのを防ぐためにStrong Parametersが導入された」「Strong Parameters使ってれば普通は大丈夫: Ransackとか使うときは要注意かな」
# 同記事より
# POST /delete_user?id=xxx
def can_delete?(user_id)
other_user = User.find_by(id: user_id)
current_user.can_delete?(other_user)
end
user_id = params[:id]
if can_delete?(user_id)
User.where(id: user_id).update(deleted: true)
end
「最後の注意点↓も基本的なものなので当然知っとくべき」「ローカルsshログのリモートコード実行例もちょっと気になりました」「ああこれは割と古典的な手口ですね: 外から持ってきたファイルをinclude("$file");
するとか、まずコードレビューとおらないっしょ」
- Cookieはユーザーが100%変更できる
Referer, User-Agent
ヘッダーなども一般に変更可能X-Forwarded-For
がちゃんと設定されてないとユーザーがIPを詐称可能になる- ローカルファイルも注意(ローカルsshログを使ってリモートコード実行する例)
marginalia: ActiveRecordのSQLクエリにコメントを付けられるgem(Ruby Weeklyより)
- リポジトリ: basecamp/marginalia
# 同リポジトリより
Account Load (0.3ms) SELECT `accounts`.* FROM `accounts`
WHERE `accounts`.`queenbee_id` = 1234567890
LIMIT 1
/*application:BCX,controller:project_imports,action:show*/
Basecampのgemです。以前翻訳したこの記事↓でも軽く紹介されていました。
つっつきボイス:「あーなるほど!どこからSQLが発行されたかを追えるのか!」「しかもそれをpt-query-digestで追えるとは、これはかなり( ・∀・)イイ!!」「お、また知らないものが」「pt-query-digestは、例のPercona Toolkitのひとつで、高速化とかチューニングによく使います」「ちなみに昔はMaatkitという名前でした」
「pt-query-digestは、MySQLから出力されたでかいログを食わせると、期間内にどんなクエリがどのぐらいあるかを出してくれます」「並のツールだと1件ずつのスロークエリは調べられても、よく似たたくさんのクエリが少しずつ遅いみたいなN+1的なクエリだと調べきれないんですが、pt-query-digestはそういう頻度の高い類似クエリを調べることができる」「おぉ~」「まあ今だとnewrelicとか使えばわかるんですが」
「marginaliaを使うとそのpt-query-digestにかけられる形式のコメントが出るってことなんでしょうね」「marginalia、よく見たらBasecamp(Railsの作者DHHのいる会社)のgemじゃん!」「まぁBasecampならnewrelicとか死んでも使わなさそうではある」「」「」
localhost: 自己署名ルート証明書をユーザーごとに生成する開発用gem
- リポジトリ: socketry/localhost
# 同リポジトリより
require 'socket'
require 'thread'
require 'localhost/authority'
# Get the self-signed authority for localhost:
authority = Localhost::Authority.fetch
ready = Thread::Queue.new
# Start a server thread:
server_thread = Thread.new do
server = OpenSSL::SSL::SSLServer.new(TCPServer.new("localhost", 4050), authority.server_context)
server.listen
ready << true
peer = server.accept
peer.puts "Hello World!"
peer.flush
peer.close
end
ready.pop
client = OpenSSL::SSL::SSLSocket.new(TCPSocket.new("localhost", 4050), authority.client_context)
# Initialize SSL connection:
client.connect
# Read the encrypted message:
puts client.read(12)
client.close
server_thread.join
つっつきボイス:「localhostっていうgem名が凄すぎ」「ヤメレw: require "localhost"
とか書きたくないし」「gem 'localhost'
で入るってことはネームスペース空いてたのね」
「このgemは自己署名証明書をローカルで開発用に立てられるということですけど、ときどき必要になる感じでしょうか?」「ですね: SSL/TLSがないと使えない機能があるとか」「Rackで使えるSSLとか使う手もありますが」「ローカルのVirtualHostが証明書を発行できればそれでいいのにと思ったりはしますが」「自分の手元のターミナルでopen ssh
して手元のNginxあたりに設定すればいいんじゃね?という気も」「今はDockerがあるからそれで十分ですしね: でも全部Rubyでやりたい人たちがいるんですよきっと」
google_sign_in: GoogleaアカウントでRailsにサインイン(GitHub Trendingより)
- リポジトリ: basecamp/google_sign_in
# 同記事より
# app/controllers/logins_controller.rb
class LoginsController < ApplicationController
def new
end
def create
if user = authenticate_with_google
cookies.signed[:user_id] = user.id
redirect_to user
else
redirect_to new_session_url, alert: 'authentication_failed'
end
end
private
def authenticate_with_google
if flash[:google_sign_in_token].present?
User.find_by google_id: GoogleSignIn::Identity.new(flash[:google_sign_in_token]).user_id
end
end
end
非常に新しいですがissueは2017年だったりするので社内で使ってたのかも。
つっつきボイス:「これもBasecampですね」「OmniAuthは絶対使いたくないとかあったりして」「BasecampってDevise使ってるんだろうか…?」「OmniAuthってそもそも抽象度が高すぎるんですよね〜: OmniAuthでOAuth2認証すると、プロバイダごとにデータ構造なんかが全然違ってたりしますし」
RailsのGraphQLでページネーションする(RubyFlowより)
- 元記事: GraphQL pagination in Rails — なぜかその後サイトが見えなくなってました
つっつきボイス:「少し前のウォッチでもページネーションの話しましたが、Google APIで何か実装したことってあります?」「まだです〜」「あの手のAPIはだいたい50件ずつぐらいしか取れないんで何らかの形でページネーションが必要になってくる: 何の工夫もしなくてもページネーションはできちゃうんですが、ちゃんとやるなら次のページに進んでいる間にデータの件数が増えたりする場合にも対応しないといけなくなる」「でGoogleのはさすがによくできていて、最初のページを取ってきたときに、そういう点にも配慮したnext page urlも一緒に返してくれるのがありがたい」「ページネーションの整合性が取れるんですね」「で、GraphQLのページネーションでもたぶんそういうところをケアしないといけないんでしょうね」
StimulusJSとActionCableにSidekiqを少々(RubyFlowより)
import cable from 'actioncable';
let consumer;
export default function (...args) {
if (!consumer) {
consumer = cable.createConsumer();
}
return consumer.subscriptions.create(...args);
}
つっつきボイス:「これは普通の非同期記事かな」「StimulusJSって何だっけ」「これもBasecampです」「そうだった: Turbolinksと相性がいいとか何とか」
RubyとEmacsのヒント集(RubyFlowより)
つっつきボイス:「VimmerからEmacsへの風評被害は最近落ち着いたのかなw」「」「」「Vimmerはネタに走りすぎ感」
(突然のエディター大喜利による音声輻輳)「Vim」「Emacs」「開発環境?それともターミナルでファイルを変更するとき?」「JetBrains IDE」「Sublime」「Atom」「VSCode」「VSCodeは最近快進撃っぽい?」「TypeScriptのお膝元だからかな」
「そうそう、EmacsでVimキーバインドをエミュレートするその名もEvil↓っていうのがありますヨ」「これはw」「凶悪」
値ベースのページネーション
つっつきボイス:「これは何がしたいのかな?」「あー、OFFSETでページネーションするとDBの内部処理が発生して遅くなるので、インデックス化されているカラムを使ってWHEREで絞り込もうよってことか: めちゃくちゃでかいテーブルだとOFFSETの速度低下が顕著に出ますね」「それってRailsに限った話じゃなくね?って思うけど」「そういえばfind_each
ってこんな感じの動きしますよね?」「そうそう、idベースでやってるし:activerecord-importとかもそんなのやってたかも」
# 同記事より
# ./models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
class << self
def start_at(id: 1, timestamp: Time.now, column: :created_at, limit: 10)
params = parsed_params(id, timestamp, column, limit)
where("#{table_name}.#{params[:column_name]} < :value OR\
(#{table_name}.#{params[:column_name]} = :value AND id > :id)",
value: params[:timestamp], id: params[:id])
.order(column => :desc)
.limit(params[:limit])
rescue ArgumentError
order(created_at: :desc).first(params[:limit])
end
...
参考: Ruby on Rails 5.2 / ActiveRecord::Batches#find_each
— DevDocs
RSpecは何を参考にするか
システムの不具合で通知メールは飛んでないかもしれませんが、とりあえずアップデートのお知らせです!最新版をダウンロードしてみてください〜。
システムスペックに関するページを新たに追加!Everyday Railsをアップデートしました – give IT a try https://t.co/0KZSgpqtUr— Junichi Ito (伊藤淳一) (@jnchito) September 5, 2018
つっつきボイス:「RSpecは、本を読むよりも誰かが書いたRSpecを参考にできると嬉しいと思う」「その誰かは誰にすればいいでしょうか?」「みんながまともと呼んでいるプロジェクト」「」「同僚がいない場合はどうしましょう?(ひとりでやってるの〜)」「それはつらそう: オープンソース系のプロジェクトを参考にすることになるけど、いきなりレベルの高すぎるRSpecを見ても難しすぎてよくわからないという」「素振りに手頃なテストコードを知りたい気持ちです」「そうそう、このぐらいユルくてもまずは書いてくれればいいよみたいなの: それこそこういう本を参考にするのがいいかな」
「ちなみに自分はlet
キライ派」「なぬっ、ワイはlet
しか使わない派w」「こうやって戦争が始まるのか」「shared_examples
は悪みたいなのは最近広まったかな?」「share_examples
も使ってるですよこれがw: 使わないとコピペアレルギーが出る〜」「share_examples
は3つまでは許せるけど〜」「てな感じになるわけですよ」「これが宗教戦争というヤツですねおっかさん」
「…テストあんまり真面目に書いてないし」「いっそRSpecをやめるというのは?みんなminitestでassertion使えば宗教が起きない、きっと」「テストコードのリファクタリングとか始めると宗教になりそうだな〜」「メソッドのリファクタリングならいいんですけど、凝りまくった器用なマッチャーとか書いて『これがテストのリファクタリングだ』とドヤ顔で言われても〜」「」「」「英語っぽい自然なテストが書きたいんじゃないんだけどな〜」
「まあとにかく、RSpecはこういう本を参考にして、あんまりスゴイのを書くようにしなくても十分じゃないのって個人的には思うわけですよ」「…きっとassertだけでいいと思うし: イコールも== true
みたいなのでいいと思ってるし」「」「自分もRSpecではほとんどeq
でやってますね〜」「」「RSpecのテストコードがちゃんと動いているかどうかが気になってくると本末転倒感ある」
Ruby trunkより
まだスパムissueが続いているようです。
提案: C APIの公式なドキュメントを作ろう
つっつきボイス:「一応あるはあった気がするけど公式ではない?」「↓これがそれに近いらしいですが、足りないものもあるようです」
参考: The Ruby C API
「確かにRubyのGILやFiberとか、モジュール読み込みのancestors周りとかも含めて公式のドキュメントがあるとありがたいという気持ちはワカル: Rubyの進化にどこまでドキュメントが追いつけるかというのはあるけど」「…わかっている人には要らないのかもという気はする」「そこまで潜らないといけないことは普段はそうそうありませんけどね」
keyword_init
を指定せずにStruct使うと動作がおかしい => 却下
Info = Struct.new(:name, :country) # キーワード引数を有効にしていない
c = Info.new(name: "myname", country: "Japan") # キーワード引数でインスタンス化される
Info = Struct.new(:name, :country, keyword_init: true) # これは動く
c = Info.new(name: "myname", country: "Japan")
p c #=> #<struct Info name="myname", country="Japan">
つっつきボイス:「自分でも動かしたらそうなりました」「ホントだ」「ハッシュとして最初の引数に全部入っちゃうと」「キーワード引数じゃない場合って、引数足りなくても動くんでしたっけ?」
↓やってみたら、キーワード引数であってもなくても引数足りない場合に動きました。
[1] pry(main)> Info = Struct.new(:name, :country)
=> Info
[2] pry(main)> a = Info.new(name: "myname")
=> #<struct Info name={:name=>"myname"}, country=nil>
[3] Info = Struct.new(:name, :country, keyword_init: true)
=> Info(keyword_init: true)
[4] pry(main)> a = Info.new(name: "myname")
=> #<struct Info name="myname", country=nil>
「自分はStruct.new
ってあまり使わないけど、kazzさんはValue Objectで割と使ってましたっけ?」「最近はそんなに頻繁には: Struct
意外に難しくて、いろいろ足していくうちに普通にクラス書く方がよくね?っていう感じになっていったり」「確かに、クラス作るのが面倒だからと思ってStruct
でやろうとすると意外に思ったとおり行かなかったりしますね」
Ruby
LinuxデスクトップアプリをRubyでがっつり作った(Ruby Weeklyより)
やっぱりGTK+でやってます。かなり長い記事ですが、こんなに詳しく解説しているのは珍しいと思って。
つっつきボイス:「RubyのGUIアプリって、Railsが流行る前には結構ありましたね: 自分も初めて触ったRubyはGUIだったし」「この記事のは結構ガッツリ作ってる方かしら?」「このぐらいのは普通にありましたね」「…大抵の言語にはGTKのバインディングあるし、昔は流行ってたけど最近はあんまり流行ってない」「Ruby何だかんだで年いってる言語だし」
参考: GTK+ - Wikipedia
Rubyをテーマにした論文リスト(Ruby Weeklyより)
つっつきボイス:「思ったより論文あるなと思って」「結構ありますよ」「知ってる著者はあっても、知らないカンファレンスがいっぱい」
ProcがCallableより遅い件について(Hacklinesより)
# 同記事より
Comparison:
callable no arg: 10095848.2 i/s
callable with arg: 9777103.9 i/s - same-ish: difference falls within error
callable 3 args: 9460308.0 i/s - same-ish: difference falls within error
callable splat args (0): 6773190.5 i/s - 1.49x slower
proc no arg: 6747397.4 i/s - 1.50x slower
proc with arg: 6663572.5 i/s - 1.52x slower
proc 3 args: 6454715.5 i/s - 1.56x slower
callable splat args (1): 5099903.4 i/s - 1.98x slower
proc splat args (0): 5028088.6 i/s - 2.01x slower
callable splat args (3): 4880320.0 i/s - 2.07x slower
proc splat args (1): 4091623.1 i/s - 2.47x slower
proc splat args (3): 4005997.8 i/s - 2.52x slower
つっつきボイス:「Callableってこの場合?」「↓PORO(素のRubyオブジェクト)のcall
メソッドを呼ぶことみたいです」「callがいくつもあると早口言葉みたい」「トートロジー」「Procの方が遅い?」「Procが遅いのはもうしょうがない: その場で解決しないといけないし」
calling a PORO’s call method — that is, a callable object
Rubyコミュニティのおすすめリソース(RubyFlowより)
strings-ansi: 文字列のANSIエスケープを検出/サニタイズするgem(Ruby Weeklyより)
- リポジトリ: piotrmurach/strings-ansi
# 同リポジトリより
Strings::ANSI.sanitize("\e[0;33;49mHello\e[0m")
# => Hello
つっつきボイス:「ANSIエスケープって何だっけと思って」「そうそう、\e[30m \e[40m
みたいにターミナルの色を変えたりするときに使いますね」「そしてよくバグる」「自分のターミナルのPowerlineでもよく出力がおかしくなったりするし: screenrcとかいじるのは楽しいけどねっ」「自分もついやっちゃう」
参考: ANSIエスケープシーケンス チートシート - Qiita
Sider社がRuboCopのスポンサーに(Hacklinesより)
つっつきボイス:「Siderは日本のCIの会社です」「そういえばRubyKaigi 2017でもRuboCopの日本人コントリビュータが発表してましたね」「RuboCop、もうちょっと人情味があってもいい気が: デフォルト設定だと厳しすぎっ」「慣れると『へーそんな書き方あるんだー』『勉強になったなぁー』って心境になれる」
その他Ruby
- 元記事: 4 Ruby Conferences You Should Attend in Fall 2018 — すごく字がでかい(RubyFlowより)
- 元記事: Closures in Ruby: Blocks, Procs and Lambdas | AppSignal Blog(RubyFlowより)
ファームウェア開発にRubyが活用されているという理由で次のプリンタはEPSONのにしようと思う(プリンタ自身にはRubyは搭載されていません)
— Yukihiro Matsumoto (@yukihiro_matz) September 6, 2018
つっつきボイス:「確かIIJのルーターもmrubyで書かれてるって聞いた気がする」
参考: 軽量Rubyへの取り組み | IIJの技術 | インターネットイニシアティブ(IIJ)
rubygems orgのエラー画面はじめてみた。Unicorn…? pic.twitter.com/kjew4smgNJ
— (@y_yagi) September 5, 2018
つっつきボイス:「ささいなようだけど、エラーページをこのぐらいいい感じに作っておくだけで和みますよね」「和んだ〜」「この間札幌大学のサイトが落ちたときのエラーページにクラーク先生の御姿があってこれも和んだ」「Railsデフォルトの赤いアレよりは遊び心あるのが( ・∀・)イイ!!」「TechRachoもそういうエラーページ出せばいいのに」「WordPressが安定してるので出番がなかなかないかなー」
参考: ウィリアム・スミス・クラーク - Wikipedia
クラウド/コンテナ/インフラ/Linux/Serverless
tcpdump101.com: パケットキャプチャ設定支援(WebOps Weeklyより)
つっつきボイス:「tcpdumpのコマンドビルダーだそうです」「101ってどういう意味だろう?」「Wireshark(旧Ethereal)もGUIよくできてるしそっちでいいかなー」
マイクロソフトがGoogleアカウントでシングルサインオンに踏み切る
Today's New's (you might wanted to be seated for this one!): #AzureAD B2B Collaboration now supports signing in with Google ID's! How phat is that? We're making seamless collab a reality. Learn more here: https://t.co/VcD9XLoE44 #MindBlown #SurprisedYouDidntWe pic.twitter.com/LLwznObiRU
— Alex Simons (@Alex_A_Simons) August 28, 2018
参考: マイクロソフト、GoogleアカウントでWindowsやOffice 365へのシングルサインオンを可能に。Azure Active Directoryの新機能をプレビュー公開 - Publickey
つっつきボイス:「ほほー?」「これはいい文明?」「MSアカウントはマジ残念なこと多すぎるしなぜか使うたびにサインインを求められるのは気のせい?」「…結構気難しいんですよねMSアカウント: 日によってEdgeでないと入れなかったりChrome Canaryじゃないと入れなかったり、でだいたい3つめで入れる」「難しいってそれってアカウントとしてどうよ」「レインボーカーソルのくるくる具合がおかしいときなんか、強制リロードしないとログインできなかったり」「ちなみにツイートで言ってるのはAzure ADの方ですね」「あそっちか」
参考: Azure Active Directory (Azure AD) とは | Microsoft Docs
vegeta: HTTP/2に対応した負荷ツール(WebOps Weeklyより)
つっつきボイス:「そのまんまベジータ画像を堂々と使っちゃってるんで記事に引用できないー」「ちょさっけん的にアウトじゃん」「ど真ん中でアウト」「しかもターゲットがgokuだし」「ベジータから悟空に攻撃するんだよやっぱ」
# 同記事より
GET http://goku:9090/path/to/dragon?item=ball
GET http://user:password@goku:9090/path/to
HEAD http://goku:9090/path/to/success
「しかしこれ、欲しいオプションはひととおりあるし、負荷テストツールとしては結構よさそうだし」「あとはマルチスレッド性能とか、どのぐらい凄いトラフィックを作れるかかな」「★9000近いし人気は抜群ですね」
「この種の負荷ツールは、単体でどれだけエグいトラフィックを作れるかというのも重要な指標」「やっぱ戦闘力の高さが大事なんですね」「エグい負荷を出せないと負荷測定にならないので」「これはRuby?」「えっと、Go言語でした」
その他クラウド
【マンガ更新】第1話:数分以内にホームページを立ち上げろ!(1/4) »https://t.co/jAPeu7HWJ4#AWS マンガシリーズ『なな転び八起のAWS開発日記』をアップ!新米プログラマー・八起ななこは張り切って出社した初日、経験がないホームページを構築しろと言われて・・・?#AWS開発日記 で投稿しよう! pic.twitter.com/O8aPj5DgVQ
— AWS / アマゾンウェブサービス (@awscloud_jp) September 3, 2018
SQL
PostgreSQLのログ先行書き込み(WAL)が肥大化する理由(Postgres Weeklyより)
つっつきボイス:「WAL: write ahead log」
litetree: ブランチできるSQLite(DB Weeklyより)
- リポジトリ: aergoio/litetree
PRAGMA branch=<name>.<commit>
つっつきボイス:「へぇえー?SQLiteのスナップショットを取ってブランチできる?」「ちょっと珍しいかなと思って」「最近のAWS Auroraにあるスナップショット機能みたい」「お、既にそういうのあったんですね」
参考: Amazon Aurora(MySQL、PostgreSQL 互換のリレーショナルデータベース)|AWS
JavaScript
NodeWeeklyというニュースサイトがあることに今頃気づきました。
Babel 7がリリース(JavaScript Weeklyより)
- 元記事: Babel 7 Released · Babel — これも字がでかい
- リポジトリ: babel/babel
主なbreaking changes:
- Node.js 5以下のサポート打ち切り
@babel
名前空間の導入(babel-core
は@babel/core
に変わる)- 年を含むpresetを廃止(
preset-es2015
など) - stage presetを廃止
変更量めちゃめちゃ多いです。
CSS/HTML/フロントエンド/テスト
手描きスケッチをHTMLコード化
かっこいい "マイクロソフト、手描きスケッチからHTMLコードを自動生成する「Sketch2Code」 – CNET Japan" https://t.co/ddC726BFei
— azu (@azu_re) September 5, 2018
つっつきボイス:「SketchといったらWeb屋はふつうこっち↓を指すだろうって」「名前はともかく機能的にはよさそうなんですけどね」「MSが戦い挑んでる」
参考: 現役WebデザイナーがデザインツールをSketch一択にした理由 – Cntlog
セキュリティ/ハッキング記事サイト
Chromeのlazyload属性
<iframe src="ads.html" lazyload="on"></iframe>
つっつきボイス:「そうそうこれ最近出てましたね: lazyload="on"
付けるだけでレイジーになってくれる」「へぇえー!」「まだChromeだけか…」
参考: Chromeの新機能がすごい便利!imgやiframeにlazyload属性を加えるだけでLazyLoad対応に | コリス
言語よろずの間
TIOBEランキングでPythonがC++を抜く
参考: 「Python」が初のトップ3入り、「Julia」上昇--TIOBE - ZDNet Japan
bat: シンタックスハイライトつきcat
(GitHub Trendingより)
- リポジトリ: sharkdp/bat
Rustで書かれています。exaというRust版のls
もあるそうです。
つっつきボイス:「catからbatへ」「『翼の生えたネコ』ってあるから明らかに狙ってるし」「にゃ~ん(ΦωΦ)」「UnixコマンドをRustで書き換えるの最近よく見かけますね」
私もripgrep(やはりRust製)を最近愛用してます。
rockstar: 100% Rubyで書かれた動的型言語(GitHub Trendingより)
- リポジトリ: dylanbeattie/rockstar
poetic licenseを目指してるとか、何だか相当なクセ球の予感。新しいのに★4000超えてます。
参考: poetic licenseの意味・使い方 - 英和辞典 Weblio辞書
Modulus takes Number and Divisor
While Number is as high as Divisor
Put Number minus Divisor into Number
(blank line ending While block)
Give back Number
(blank line ending function declaration)
Limit is 100
Counter is 0
Fizz is 3
Buzz is 5
Until Counter is Limit
Build Counter up
If Modulus taking Counter, Fizz is 0 and Modulus taking Counter, Buzz is 0
Say "FizzBuzz!"
Continue
(blank line ending 'If' Block)
If Modulus taking Counter and Fizz is 0
Say "Fizz!"
Continue
(blank line ending 'If' Block)
If Modulus taking Counter and Buzz is 0
Say "Buzz!"
Continue
(blank line ending 'If' Block)
Say Counter
(EOL ending Until block)
つっつきボイス:「自然言語っぽいプログラミング言語を目指してる感」「コメントはご法度だそうです」「poetic licenseって何だろうと思ったら『詩的許容』というやつでした」「どことなくVBっぽい匂いもする」
その他
英語辞書Chrome拡張
つっつきボイス:「これスピード速くてすごくいいんですが、手持ちの辞書はほとんど読み込めないので私にはまだ使いみちがない」
Electronで動くWindows 95
- リポジトリ: felixrieseberg/windows95
つっつきボイス:「やっぱりレガシーゲーム用?」「DOOMとかね」
番外
一発ネタ
「HTTPS 化でポート番号が約5倍に!」 のグラフ好きすぎて乱用してしまう https://t.co/AtEBsNHbNM
— Takafumi ONAKA (@onk) September 5, 2018
どうしてそうなった… https://t.co/Nq1GZnIHBg
— syuu1228 (@syuu1228) September 3, 2018
戦時中生まれ
24年前、WindowsNTを生んだデイブ・カトラーは、御年76歳でAzureを引っ張り続ける現役プログラマ(NTリリース時は52歳)
この凄い戦歴を知ってたら、35歳プログラマ引退説とかあり得ない
…で、40歳を過ぎて思うこと…年々、思った通りのプログラムが、より速く作れるようになっていく感覚だよ https://t.co/Po4348go98
— piacere (@piacere_ex) September 3, 2018
Rob Pikeより15歳も年上でした。
つっつきボイス:「『闘うプログラマー』好きでしたよね?」「…好きです、目の前の本棚のどこかにあったはず」「後で探そうっと」
「今週は以上です」「お疲れさまでしたー!」
バックナンバー(2018年度後半)
- 20180820 Railsで構築されたサイト40選、Deviseはつらいよ、ARのスコープとクラスメソッドの使い分けほか
- 20180813 Rails 5.2.1リリース、sanitize_sql_arrayは5.2からpublicだった、Dev.toがRailsアプリのソースを公開ほか
- 20180806 Rails 5.2.1.rc1リリース、Railsガイド日本語版が5.1に対応、Regexp#match?ほか
- 20180723 Railsdm Day 3 Extremeを後追い、PSDにはZeplin.io、好みの分かれるJSX、負荷テストツール比較ほか
- 20180709 Rails Developers Meetup Day 3 Extreme今週末開催、RailsのSTI/キャッシュ/添付ファイル/Redis/PDF出力、ECMAScript 2018、プロフェッショナルIPv6ほか
- 20180702 Ruby 2.2メンテ正式終了、Ransackがつらくなるとき、書籍『Domain-Driven Rails』、GitHubの高可用MySQLほか
- 20180622 Railsの需要未だ巨大、Unicode 11.0リリース、WebDriverがW3Cで勧告、Flutter.io、2封筒問題ほか
- 20180615 TTY gemとHTTPClient gemは優秀、Rubyの謎フリップフロップ、ちょいゆるRubyスタイルガイドほか
- 20180608 特集「RubyKaigi 2018後の祭り」、
Enumerable#index_with
は優秀、コントローラから@
を消し去るほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。