- Ruby / Rails関連
週刊Railsウォッチ(20180420)NGINX Unit正式リリース、Rubyをメモリリークさせてみる、美しいコード宇宙ほか
こんにちは、hachi8833です。記事を絞ろうと気張るのを諦めて単に絞ることにしました。
昨日のつっつきは、BPSの福岡拠点であるウイングドアの皆さまとZoomで画面共有しながら行いました。おかげさまでさらに盛り上がりました。ありがとうございます。
今日のTechRachoの中の勉強会楽しかったー。中身が濃いのでもっとrailsの勉強しないとなぁ。
— osamu arita (@osamu_arita) April 19, 2018
ところが何ということでしょう、録音を忘れていた私でした...😢今週のつっつき成分は少なめです。
というわけで、季節の変わり目のウォッチ、いってみましょう。
各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
⚓Rails: 今週の改修
Rails 6になるmasterブランチから見繕いました。
先週取り上げたようなsplat外し的修正が目立ちます。86cafe7なんかもそうですね。
⚓RedisCacheStore#delete_matched
でブロックが発生してタイムアウトしていたのを修正
- commit: #ef2af6 Redis cache store: avoid blocking the server in
#delete_matched
- issue: #32610 RedisCacheStore#delete_matched blocks and causes timeouts
# commitより
def delete_matched(matcher, options = nil)
instrument :delete_matched, matcher do
case matcher
when String
redis.with { |c| c.eval DELETE_GLOB_LUA, [], [namespace_key(matcher, options)] }
else
raise ArgumentError, "Only Redis glob strings are supported: #{matcher.inspect}"
end
end
end
つっつきボイス: 「Lua言語が使われてる部分があったんだ...」
参考: Lua - Wikipedia
⚓javascript_include_tag
ヘルパーにnonce: true
オプションを追加
# actionview/lib/action_view/helpers/asset_tag_helper.rb#L
def javascript_include_tag(*sources)
options = sources.extract_options!.stringify_keys
path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
@@ -90,6 +95,9 @@ def javascript_include_tag(*sources)
tag_options = {
"src" => href
}.merge!(options)
+ if tag_options["nonce"] == true
+ tag_options["nonce"] = content_security_policy_nonce
+ end
content_tag("script".freeze, "", tag_options)
}.join("\n").html_safe
つっつきボイス: 「nonce
って前にもつっつきで扱った気が」「number used onceのことだったんかー↓」「同じようなCSP属性があったけど何だったかな」「ところで今ぐぐって見つけていただいたreference.hyper-text.orgってちょっといい感じのリファレンスサイトですね」
nonce
nonce 属性は、CSP(Content Security Policy)によって、文書内に読み込まれた script 要素や、style 要素の内容を実行するかを決定するために利用される nonce(number used once / ワンタイムトークン) を指定します。
reference.hyper-text.orgより
参考: nonce 属性 | HTML5 タグリファレンス | W3 Watch Reference
参考: CSP: script-src - HTTP | MDN
⚓Content Security Policyでリクエストごとのnonceを1つだけにする
これもnonce
ですね。
# actionpack/lib/action_dispatch/http/content_security_policy.rb#L232
- def build_directives(context)
+ def build_directives(context, nonce)
@directives.map do |directive, sources|
if sources.is_a?(Array)
"#{directive} #{build_directive(sources, context).join(' ')}"
+ if nonce && nonce_directive?(directive)
+ "#{directive} #{build_directive(sources, context).join(' ')} 'nonce-#{nonce}'"
+ else
+ "#{directive} #{build_directive(sources, context).join(' ')}"
+ end
elsif sources
directive
else
...
⚓APIドキュメントの修正3種
# activemodel/lib/active_model/validations/inclusion.rb#L21
# class Person < ActiveRecord::Base
- # validates_inclusion_of :gender, in: %w( m f )
+ # validates_inclusion_of :role, in: %w( admin contributor )
# validates_inclusion_of :age, in: 0..99
# validates_inclusion_of :format, in: %w( jpg gif png ), message: "extension %{value} is not included in the list"
# validates_inclusion_of :states, in: ->(person) { STATES[person.country] }
今どきgenderが男と女だけというのは古臭い感じかもですね。
そういえばだいぶ昔は「クライアント/サーバー」と言わずに「マスター/スレーブ」って言ってたんですよね。「主人と奴隷」はさすがに200年遡る感じです。
つっつきボイス: 「へー、LGBTコンシャスというか」「そういえばこの間はてブであがってたISO 5218が、まさにこうした用途のための国際規格ですよ」「知らなかったー!」
0
= not known(不明)1
= male(男性)2
= female(女性)9
= not applicable(適用不能)
ブクマにyuguiさんのコメントを見つけました:
システムで「性別」の情報を扱う前に知っておくべきこと - Qiita
- [gender]
- [DB]
「入力して何の役に立つの?」という最重要ポイントを読み落とさないでほしい。医療かマーケか戸籍処理か本人確認か、用途に応じて入力させるべきかも提示選択肢も入力欄ラベルも自ずと定まり、難しいことはない
参考: システムで「性別」の情報を扱う前に知っておくべきこと - Qiita -- これ必読ですね
遠い昔、子どもの頃の遠足で訪れたお寺で他の子が「観音様って男?女?」と質問すると、お寺の管理人さんが「観音は 男にあらず 女にあらず」と迷いなく答えたのをふと思い出しました。典拠を探そうと思ってググると新興宗教系サイトがわらわら出てきた...
# actionview/lib/action_view/context.rb#L10
# Action View contexts are supplied to Action Controller to render a template.
# The default Action View context is ActionView::Base.
#
- # In order to work with ActionController, a Context must just include this module.
- # The initialization of the variables used by the context (@output_buffer, @view_flow,
- # and @virtual_path) is responsibility of the object that includes this module
- # (although you can call _prepare_context defined below).
+ # In order to work with Action Controller, a Context must just include this
+ # module. The initialization of the variables used by the context
+ # (@output_buffer, @view_flow, and @virtual_path) is responsibility of the
+ # object that includes this module (although you can call _prepare_context
+ # defined below).
つっつきボイス: 「クラス名としてはActionController
だけど名称としてはAction Controllerが正式ってことなんでしょうか?」「んー、というより冒頭にAction Viewって書いてあるから単にそれと書式を合わせたってことなんじゃ?」「あなるほど、ドキュメントのローカルレベルでの統一というか」
くっついてる方が検索しやすいかなとちょっぴり思ったりしました。
# guides/source/_welcome.html.erb#L18
<% end %>
<p>
The guides for earlier releases:
+<a href="http://guides.rubyonrails.org/v5.2/">Rails 5.2</a>,
<a href="http://guides.rubyonrails.org/v5.1/">Rails 5.1</a>,
<a href="http://guides.rubyonrails.org/v5.0/">Rails 5.0</a>,
<a href="http://guides.rubyonrails.org/v4.2/">Rails 4.2</a>,
つまりRuby on Rails 5.2 Release Notesが正式になったということですね。Railsガイドの翻訳の優先順位上げます。ご期待ください。
⚓サーバーIP指定時のHOST
環境変数のサポート廃止
#
- ENV.fetch("HOST", default_host)
+
+ if ENV["HOST"] && !ENV["BINDING"]
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Using the `HOST` environment to specify the IP is deprecated and will be removed in Rails 6.1.
+ Please use `BINDING` environment instead.
+ MSG
+
+ return ENV["HOST"]
+ end
+
+ ENV.fetch("BINDING", default_host)
SuSeSUSEでは$HOSTがデフォルトで設定され、$HOSTNAMEと等しくなっている。
https://www.suse.com/documentation/sled11/book_sle_admin/data/sec_adm_variables.html
従って、デフォルトではlocalhostではなくhostnameにバインドされる。これはデフォルトの振る舞いとしてはふさわしくないように思える。
この環境変数名の利用を避けるために、環境変数をHOSTからBINDINGに変更する。
同コミットより
つっつきボイス: 「お、これ大事な修正ですね: Rails 6.1からはHOSTS
環境変数のサポートが削除されるのでBINDING
環境変数を使うように、と」
「話逸れますが(逸れてばっかり)、昔いた会社のヨーロッパ系社員がSuSeSUSEを「ズーゼ」ってドイツ語っぽく発音してて、最初何のこと?って思っちゃいました」「へー、SuSeSUSE Linuxって日本ではなぜかそれほど知名度ないけど、ヨーロッパでは長い間ずっと主流ですね」「シンボルカラーが緑色だったのだけ覚えてます: 今もそうなのかな?」
⚓storage
フォルダに.keep
ファイルを追加する条件を修正
# railties/lib/rails/generators/rails/app/templates/gitignore.tt
<% unless skip_active_storage? -%>
# Ignore uploaded files in development
/storage/*
-
+<% if keeps? -%>
+!/storage/.keep
<% end -%>
+<% end -%>
+
<% unless options.skip_yarn? -%>
/node_modules
/yarn-error.log
最初にRailsを触ったときに、空のフォルダに入っている.keep
って何だろう?と思ったのを思い出しました。
つっつきボイス: 「ははぁ、.gitignore
に/storage/.keep
登録しちゃってたのか: そりゃ直さなきゃ!」「空ディレクトリにファイルが何もないとディレクトリがGitに登録されないんで、.keep
が置かれてるんですね」「そうそう、前に教えてもらって知りました」
⚓Rails
⚓Action Policy: Ruby/Rails向けauthorizationフレームワーク
authorizationの訳語でいつも悩んでます。「認証(authentication)」と対にして「認可」「承認」とされることが多いのですが、認可でも何かこうしっくりこない...リソース管理とかリソースのアクセス権の扱いなんかがauthorizationなんですよね。
authorizationの訳語は「認可」が普通だと思います。
それにしてもこの量と質で毎週出しているというのは本当にすごいです
— すぎむら (@sugitk) April 20, 2018
つっつきボイス: 「これもEvil Martiansさんがスポンサーになってる: Evil MartiansさんのブログはTechRachoの翻訳記事にときどき使わせてもらってるんですが、こうやってちょっと先を行くようなgemのスポンサーになっているのをちょくちょく見かけるので」「action_policy gemはEvil Martiansのリポジトリとは別の場所なのか: それにしてもevil-seedとかevil-clientとか、RailsのGemfileとかで見かけたらドキーッっとしそうw」「徹底しているというか、旗色は鮮明ですね」
# 同リポジトリより
class PostPolicy < ApplicationPolicy
# everyone can see any post
def show?
true
end
def update?
# `user` is a performing subject,
# `record` is a target object (post we want to update)
user.admin? || (user.id == record.user_id)
end
end
「で、このaction_policyはコントローラ側に寄せた設計のようだ」「以前から悩んでるところなんだけど、authorizationってPundit式にモデルに寄せるべきか、cancancan式にコントローラというかURL側に寄せるべきか、どっちだと思う?」「そうなんすよねぇ...モデル側の方がライブラリとしておさまりはいいのかなと思ったりもしますが、複雑になってくるとつらくなってくるし、果たしてモデルの責務なんだろうかという疑問も残るし」「自分は何となくだけど、コントローラ側の方が自然な気がするんだけどなー」「cancancanは機能が多すぎて逆にツライ: コントローラでauthorize!
ってできればもうそれでいいのっ!w」「住処が定まらない感じですね」
⚓NGINX Unit正式リリース
おー、ついにきた!
こっちの記事↓にも詳しいのでおすすめです!https://t.co/kX7JBdKz4xNGINX Unitが正式リリース。PHP、Go、Pythonなどに対応した軽量アプリケーションサーバ - Publickey https://t.co/QgaZfCXPWE
— かつひささん (@katsuhisa__) April 16, 2018
つっつきボイス: 「どうも思い違いされていることが多いみたいなんですが、NGINX UnitはNGINXとは別物なんですよねー」「どちらもNGINX社の製品なのにそうなんですね: 紛らわしい...」
⚓社内Slackより: 悪例サンプルコードづくりは難しい
SOLID Principles #4 - Interface Segregation Principle | Netguru Blog on Ruby/Ruby on Railsを翻訳したときに、サンプルコードについて社内Slackでかなり議論になりました。
私も訳していて、原著者が非常に苦しみながら書いていることを痛感しました。
# 同記事の悪例コード
class Computer
def turn_on; end
def type; end
def replace_cpu; end
def change_user_password; end
end
class ComputerUser
def initialize
@computer = Computer.new
end
end
class Programmer < ComputerUser
def write_code
@computer.turn_on
@computer.type
end
end
class Administrator < ComputerUser
def update_user
@computer.turn_on
@computer.change_user_password
end
end
class Technician < ComputerUser
def fix_computer
@computer.replace_cpu
@computer.turn_on
end
end
記事として練り直しを考えているところです。Slackでの指摘をまとめると以下のような感じでした。
- サンプルコードの修正前と修正後の差が大きすぎて、ISPにフォーカスしにくい
- そもそも修正前のコードがいろいろひどすぎて、そっちに気を取られてしまう
- 可能なら修正したいところだけど、 ユースケースが見えない
推測ですが、教科書にありがちな哺乳類だの何だのという浮世離れしたクラスではなく、何とかして現実的なクラスにしようとしたように思えます。
ISPを説明するのに向いたサンプルコードがあれば著者もぐっと楽になりそうです。手頃な素材がどこかにないものでしょうか。
⚓RailsでのExplicit Contract
# 同記事より
class StudentsController < ApplicationController
# ...
def pull
pulled_student_list = third_party_contract.fetch_students['students']
pulled_student_list.each do |pulled_student|
student = Student.new
student.name = pulled_student['name']
student.age = pulled_student['age']
student.save!
end
end
private
def third_party_contract
Rails.configuration.x.third_party_contract
end
end
つっつきボイス: 「third party contract? どうやら法律用語から来てるっぽい?わからんけど」「httpartyっていうHTTPクライアントgem使ってますね: ★5,000近い」
- リポジトリ: jnunemaker/httparty
# 同リポジトリより
# Use the class methods to get down to business quickly
response = HTTParty.get('http://api.stackexchange.com/2.2/questions?site=stackoverflow')
puts response.body, response.code, response.message, response.headers.inspect
# Or wrap things up in your own class
class StackExchange
include HTTParty
base_uri 'api.stackexchange.com'
def initialize(service, page)
@options = { query: { site: service, page: page } }
end
def questions
self.class.get("/2.2/questions", @options)
end
def users
self.class.get("/2.2/users", @options)
end
end
stack_exchange = StackExchange.new("stackoverflow", 1)
puts stack_exchange.questions
puts stack_exchange.users
「httpartyで思い出したけど、herっていうgemもなかなかよくできてますヨ(前にも話したけど)」
# 同リポジトリより
User.all
# GET "https://api.example.com/users" and return an array of User objects
User.find(1)
# GET "https://api.example.com/users/1" and return a User object
@user = User.create(fullname: "Tobias Fünke")
# POST "https://api.example.com/users" with `fullname=Tobias+Fünke` and return the saved User object
@user = User.new(fullname: "Tobias Fünke")
@user.occupation = "actor"
@user.save
# POST "https://api.example.com/users" with `fullname=Tobias+Fünke&occupation=actor` and return the saved User object
@user = User.find(1)
@user.fullname = "Lindsay Fünke"
@user.save
# PUT "https://api.example.com/users/1" with `fullname=Lindsay+Fünke` and return the updated User object
⚓ChromebookでRailsが動く?
参考: ChromebookのFile Systemへの書込み制限を解除する方法 ― Write-Protect-Screwの外し方 C300MA編 | Chrome速報
Chromebrew
(crew
コマンド)というのを入れると様々なシステムを簡単にインストールできる。EmacsもNodeも簡単にインストールできた。Sinatraも使えたのでWebアプリ開発もできてしまう。頑張ればRailsも動きそうである。(crew
だとコケたが個別インストールすれば大丈夫そう)
つっつきボイス: 「ポイントは、Chromebookのフタを外してプロテクトスイッチを解除することみたいです」「DockerがChromebookで動けばいいんじゃね?そしたらもう何でも動くよ♥」
⚓その他記事など
#gocon railsへの言及が何件かあったのが気になって、例えばrailsに寄せるための努力とgoでやるメリットを比較したときにgoを選ぶことが本当に正しいのかと思った
— KI (@kinoshita_22) April 15, 2018
"At GitHub, we restart our application server maybe every 10 minutes. It's not because we have to restart it every 10 minutes, it's because we're deploying code maybe every 10 or 15 minutes" 衝撃的なデプロイ頻度だ…
— k0kubun (@k0kubun) April 15, 2018
感想ありがとうございます!「Railsから入ったけどRubyはあんまり」という人がターゲットなので、まさにドンピシャですね😆 / “『プロを目指す人のためのRuby入門』 はRailsエンジニアになったばかりの人は絶対読むべき。…” https://t.co/MFyb3bD6dr
— Junichi Ito (伊藤淳一) (@jnchito) April 16, 2018
AzureでRailsアプリを運用されている皆様に朗報です。
assets:precompile実行で自動的にAzureBlobにアセットを保存させることができるようになりました〜。AssetSyncでAzure BlobにRailsの静的ファイルを自動的に保存する - devひよこのあしあと https://t.co/hoRK35V3Cu
— d-tasaki (@devchick99) January 4, 2018
つっつきボイス: 「AssetSyncはAWSのS3と同期するgemだけど、Azureにも対応したのか」
参考: Microsoft Azure Cloud Computing Platform & Services
⚓Ruby trunkより
⚓IRBのパーサーをRipperにした
⚓===
がmatch?
より遅い
- 元記事: Bug #14695: [2.5.1] `===` is 1.77x slower than `match?` - Ruby trunk - Ruby Issue Tracking System
# 同issueより
# ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
require 'benchmark/ips'
def run_benchmark(title, **benchmarks)
puts '', title, '=' * title.size, ''
# Validation
benchmarks.each do |benchmark_name, benchmark_fn|
puts "#{benchmark_name} result: #{benchmark_fn.call()}"
end
puts
Benchmark.ips do |bm|
benchmarks.each do |benchmark_name, benchmark_fn|
bm.report(benchmark_name, &benchmark_fn)
end
bm.compare!
end
end
regex = /foo/
# => /foo/
string = 'foobarbaz'
# => "foobarbaz"
run_benchmark('=== vs match? - 2.5.1',
'===': -> { regex === string },
'match?': -> { regex.match? string }
)
=== vs match? - 2.5.1
=====================
=== result: true
match? result: true
Warming up --------------------------------------
=== 173.435k i/100ms
match? 233.124k i/100ms
Calculating -------------------------------------
=== 3.174M (± 1.6%) i/s - 15.956M in 5.029027s
match? 5.626M (± 2.5%) i/s - 28.208M in 5.016991s
Comparison:
match?: 5626170.1 i/s
===: 3173659.6 i/s - 1.77x slower
つっつきボイス: 「まず===
とmatch?
って同一なんだっけ違うんだっけ?」「ほむほむ、match?
は位置を指定できるのと、例の特殊変数を更新しないところが違う、と↓」「特殊変数を更新してたらその分遅くなりそうですね」「$~
とか使うとRubyがPerlチックになるんで好きじゃないなー」「私も」
Regexp#===
: 文字列 string との正規表現マッチを行います。 マッチした場合は真を返します。string が文字列でもシンボルでもない場合にはfalse
を返します。このメソッドは主にcase文での比較に用いられます。Regexp#match?
: 指定された文字列str
に対して 位置pos
から自身が表す正規表現によるマッチングを行います。 マッチした場合true
を返し、マッチしない場合にはfalse
を返します。また、$~
などパターンマッチに関する組み込み変数の値は変更されません。
Rubyリファレンスマニュアルより
⚓Windowsで削除の制御文字が期待どおりに動かない
ruby -e 'puts "Hello world!\e[D\e[D\e[K\nWhat is up?"'
ruby -e 'puts "Hello world!\e[D\e[D\e[0K\nWhat is up?"'
ruby -e 'puts "Hello world!\e[D\e[D\e[1K\nWhat is up?"'
# 期待
Hello worl
Whats up?
Hello worl
Whats up?
!
Whats up?
# 実際
d!
What is up?
d!
What is up?
d!
What is up?
つっつきボイス: 「普段Web開発しているとほとんどやらないけど、Windowsの生の環境でRubyを使ってる人って、実は結構いるんじゃないかしら: 社内業務改善の手作りツールとかで」「それ私マジでやってました: Excelがバージョンアップするたびに手作りVBAが動かなくなるのが嫌になって、ExcelをRubyで制御する拡張をインストールして動かしたのがRubyとの最初の出会い」「WindowsユーザーのサポートはRubyのありがたい点」
どうやったかもう思い出せませんが、require 'win32ole'
的にやったのかもしれません。確かRubyのバージョンは1.9だったはず。
参考: Rubyist Magazine - VBA より便利で手軽 Excel 操作スクリプト言語「Ruby」へのお誘い (前編)
⚓rangeの終わりを「無指定」にできるようになる
今日見つけたツイートです。
Ruby 2.6 will have "endless ranges."
ary[1..] # identical to ary[1..-1]
(1..).each {|index| ... } # infinite loop from index 1https://t.co/rqN38zQafa(1..) {|elem, index| ... } # ary.each.with_index(1) { }See https://t.co/zecQl4RkxD in detail.
— Yusuke Endoh (@mametter) April 19, 2018
ary[1..] # [1..-1] と同等
その後#14700で早速バグ上がってました。
⚓Ruby
⚓Rubyでメモリーリークを引き起こす方法(Ruby Weeklyより)
# 同記事より
a = []
b = {}
loop {
sleep(1)
10_000.times { a << "abc" }
puts GC.stat(b)[:heap_live_slots]
}
つっつきボイス: 「おー、漏れてる漏れてる」「sleep(1)
って必要なんだろうか?」「単に見やすくしてるんでしょうかね」「C拡張がリークするのは不思議でも何でもないw」「heap_live_slots
か...情報どこかにあるか?」「つ↓」
参考: Understanding Ruby GC through GC.stat
⚓型あり言語からRubyに来た人の心理学
2004年なのですごく古いですが、どうやら有名みたいです。
# 同書き込みより
# こうなりがち
def date=(val)
class="keyword">case val
when Date
@date = val
when Time
@date = Date.new(val.year, val.month, val.day)
when String
if val =~ /(\d{4})\s*[-\/\\]\s*(\d{1,2})\s*[-\/\\]\s*(\d{1,2})/
@date = Date.new($1.to_i,$2.to_i,$3.to_i)
else
raise ArgumentError, "Unable to parse #{val} as date"
end
when Array
if val.length == 3
@date = Date.new(val[0], val[1], val[2])
end
else
raise ArgumentError, "Unable to parse #{val} as date"
end
end
そして筆者の考えるダックタイピングの真髄はこうだそうです。
# year、month、dayメソッドに応答するオブジェクトを取る
attr_accessor :date
つっつきボイス: 「クラスチェックしたくてcase
で分岐しちゃうやつねー」「でもActiveSupportとかでこういう分岐、普通に見かけますよw」「どっひゃー」「if val
行の正規表現はつらそう...」
参考: 静的型と OO というものははじめから… - Oh, you `re no (fun _ → more) -- ここから辿りました
⚓「ゴッドクラス」というアンチパターン
Gobyのst0012さんに教わって知りました。
巷では、OOPでは大量のメソッドを保有する万能クラス (ゴッドクラス) を作ってはいけないらしい。また、1メソッドあたり3行程度であるべきで、長いメソッドを書くのはオブジェクト指向的ではないらしい。そういうコードを書くやつはオブジェクト指向がわかっていないのだそうだ。
Qiita記事より
つっつきボイス: 「↑1メソッドあたり3行!来たなー」「引数縦に並べるとそれだけで3行終わっちゃいます」「自分も5行まで!なんて言ったりするけど基本ジョークジョークw」「20行までなら許して欲しい」「50行は多いかな?」「Rubocopのデフォルトって何行まで許されるんでしたっけ?」「コメント除いて10行みたいです」
⚓🌟Code Galaxies Visualization🌟
Ruby、もちろんあります。美しすぎる。Go Conference 2018で知りました。
つっつきボイス: 「HomebrewやDebianパッケージまであるし」
宇宙船操作マニュアルとか気分出ますね(H
キーで表示できます)。
今週の🌟を贈呈します。おめでとうございます。
⚓rdl: Rubyで型チェック
- リポジトリ: plum-umd/rdl
# 同リポジトリより
file.rb:
require 'rdl'
extend RDL::Annotate
type '(Integer) -> Integer', typecheck: :now
def id(x)
"forty-two"
end
つっつきボイス: 「->
こういう型宣言する関数型言語、あった気がする」「Ruby 3.0だとコメントに記述する形(アノテーション)で型チェックが入りそうなんでしたっけ」「dry-validationみたいなライブラリレベルの型チェックでいい気がする...」
# dry-rb.orgより
schema = Dry::Validation.Form do
required(:name).filled
required(:age).filled(:int?, gt?: 18)
end
schema.("name" => "Jane", "age" => "30").to_h
# => {name: "Jane", age: 30}
schema.("name" => "Jane", "age" => "17").messages
# => {:age=>["must be greater than 18"]}
⚓その他記事など
RubyKaigi 2018 is calling for lightning talk proposals! Go submit and get a limited 5 minutes slot! 🔜 https://t.co/IVluR2KlCt #rubykaigi
— RubyKaigi (@rubykaigi) April 13, 2018
いい試み - RubyKaigi 2018 に学生さんをご招待します https://t.co/1oFWx0xxGp
— willnet (@netwillnet) April 19, 2018
rubyでredoって書くとjumpインストラクションに変換されて他のraiseとかと比べてメチャ軽いということを発見したので読みづらいgotoとして積極的にabuseしていくぞという意気込みを得た
— 7594591200220899443 (@shyouhei) April 17, 2018
つっつきボイス: 「redo
って確かYARVがらみで見かけた気が」
追伸: いわゆるJUMP命令ってパイプラインはstallするけど1 instructionなのでそりゃ早いみたいな話でした(morimorihoge)。
参考: YARV: Yet another RubyVM / Instruction Table
⚓SQL
⚓PostgreSQLで大規模データを処理する(Postgres Weeklyより)
つっつきボイス: 「まだ中身読んでなかった」「ふむふむ、parallelismにパーティショニングにVACUUM FREEZEにFDW...、普通にぽすぐれででかいデータを扱う記事ですね」「(ぽすぐれで計算処理やらせるのかとおもた...)」
⚓PostgreSQL 11に入る「Covering Index」
-- 同記事より
=# CREATE TABLE new_example (a int, b int, c int);
CREATE TABLE
=# INSERT INTO new_example
SELECT 3 * val, 3 * val + 1, 3 * val + 2
FROM generate_series(0, 1000000) as val;
INSERT 0 1000001
=# CREATE UNIQUE INDEX new_unique_idx ON new_example(a, b)
INCLUDE (c);
CREATE INDEX
=# VACUUM ANALYZE;
VACUUM
=# EXPLAIN ANALYZE SELECT a, b, c FROM new_example WHERE a < 10000;
QUERY PLAN
-----------------------------------------------------
Index Only Scan using new_unique_idx on new_example
(cost=0.42..116.06 rows=3408 width=12)
(actual time=0.085..2.348 rows=3334 loops=1)
Index Cond: (a < 10000)
Heap Fetches: 0
Planning Time: 1.851 ms
Execution Time: 2.840 ms
(5 rows)
つっつきボイス: 「え?Covering Indexってぽすぐれになかった?: MySQLにはずうっと前からあるのに」「ほんとだ、ググるとMySQLばっかり出てくる」
参考: インデックスのみのスキャン: テーブルアクセスを避ける
インデックスのはたらきによって、テーブルアクセスしなくても良かった場合のことを、 カバリングインデックスと言います。これは、インデックスの機能であるかのような響きがあるので、誤解されやすい用語です。インデックスのみのスキャン、という言い方の 方が、実行計画の操作であることを明白に示しています。
上記ブログより
つっつきでMERGE JOIN
の話にもなったのですが展開思い出せず...
⚓EdgeDBって何じゃろう
Some pretty big claims in here, and it has a lot to prove, but I've been praying for something like this to come along. How big a grain of salt should I take with it?https://t.co/rk7F6i9xVB
— Rich Harris (@Rich_Harris) April 15, 2018
Rich Harrisさんって有名な人みたい。
⚓JavaScript
⚓async/awaitヘルからの脱出(JavaScript Weeklyより)
// 同記事より
async function selectPizza() {
const pizzaData = await getPizzaData() // async call
const chosenPizza = choosePizza() // sync call
await addPizzaToCart(chosenPizza) // async call
}
async function selectDrink() {
const drinkData = await getDrinkData() // async call
const chosenDrink = chooseDrink() // sync call
await addDrinkToCart(chosenDrink) // async call
}
(async () => {
const pizzaPromise = selectPizza()
const drinkPromise = selectDrink()
await pizzaPromise
await drinkPromise
orderItems() // async call
})()
// Although I prefer it this way
(async () => {
Promise.all([selectPizza(), selectDrink()]).then(orderItems) // async call
})()
⚓TypeScriptの記法を理解する(JavaScript Weeklyより)
interface Array<T> {
concat(...items: Array<T[] | T>): T[];
reduce<U>(
callback: (state: U, element: T, index: number, array: T[]) => U,
firstState?: U): U;
···
}
つっつきボイス: 「TypeScriptはいいと思う: ただねー、環境の準備がめんどいw」「誰か準備してくれるならTypeScriptにしたい」「そういえばこの中にひとり、TypeScript勢いませんでしたっけ?」「ワイ?| ゜Θ゜)<そうでもないよ」
参考: TypeScript - JavaScript that scales.
⚓これで全部終わらそうかという勢いのオンラインドキュメント: Front-End Developer Handbook 2018(JavaScript Weeklyより)
JS/CSS/HTML...と、新しいフロントエンド絡みのドキュメントを親の仇のように集約しています。
つっつきボイス: 「先週のrubyreferences.github.ioといい、このフォーマットのドキュメントテンプレ流行ってるのかなと思って」「というよりみんなGitHub Pages使ってるからじゃないすか?」「あそっか」「ともあれ、どこまできちんと書かれているかはちゃんと読むまでわからないですけどねw」
追伸: フォーマットの話はGitBookの方ですね。 github.io ドメイン使ってる場合はGitHub Pages連動もしてるでしょうが(morimorihoge)。
「お、とってもいい地図見つけた↑」「サイトの作りというか、フロントエンドはこれをこういう順に学べという道案内ですね」「同じページの『↓これは学ぶなリスト』にCoffeeScriptが...😢」「SASSも!?」
A short word of advice on learning. Learn the actual underlying technologies, before learning abstractions. Don't learn jQuery, learn the DOM. Don't learn SASS, learn CSS. Don't learn HAML, learn HTML. Don't learn CoffeeScript, learn JavaScript. Don't learn Handlebars, learn JavaScript ES6 templates. Don't just use Bootstrap, learn UI patterns.
「SASSじゃなくて素のCSSにしろと言われてもなー」「PostCSSあたりはどうだろう?」
こちらにも星あげたい気持ちしてきました。
追伸: 落ち着いて読み直してみたら、基礎を学んでから応用のCoffeeScriptなりを学べという文脈でした。
⚓CSS/HTML/フロントエンド
⚓Unicodeコンソーシアムの絵文字募集フォーム
- 送信フォームと要項: Submitting Emoji Character Proposals
- これまで受け取った絵文字: Emoji Requests
Turing Complete FMの文字コードの回でも、絵文字の寿司にバリアントがいっぱいあるのにピザがそうじゃないのはどうよとか楽しい話があった気がします。
つっつきボイス: 「次は2020年に採択されるそうです」「文字だけのリストだとわかりにくいなー」「TechRachoのシンボルマークしれっと出したら案外通ったりして?」「(爆)」
⚓出会えてうれしいCSSベスト3
出会えたことに感謝したいCSSベスト3
1位 display: flex;
2位 box-sizing: border-box;
3位 height: 100vh;— スダ氏 (@sudarexyz) April 7, 2018
1位:height:100vh;
2位:font-size:4vw;
3位:calc (100vh - 100px );高さの調整はありがたいよなー。#出会えたことに感謝したいCSSベスト3 https://t.co/ofkOhWNe0d
— 平尾誠@ARUTEGA.Inc (@Makopontass) April 7, 2018
1. display: flex;
コリスでこれが紹介されてたあたりでCSS始めた。floatを後から覚えた。
2. font-family
フォントがフォールバックに対応していたおかげでYakuHanJP作れた。
3. transform: translate(-50%, -50%);
自分のサイズの半分だけずらす発想に感動。— クラク (@Qrac_JP) April 7, 2018
Rubyのメソッドなんかでもこういうのやってみようかな。
つっつきボイス: 「flexboxが人気」「calcも多いですね」
⚓Service Workerとは
⚓Go言語
⚓grapi: gRPC APIサーバー&ジェネレーター
- リポジトリ: izumin5210/grapi
つっつきボイス: 「Go Conference 2018でgRPCの登場率高かったです」「gRPCのようなミドルウェア的なものはGoが得意そうっすね」
⚓Go言語がWebAssemblyをサポートへ
Gobyちゃんがブラウザでするっと動く日が来るかなと思って。ちなみにこの記事の情報源は基本的に#18892でした。
⚓Goで学ぶTCP/IPスタック
話はそれますがGoでTCP/IPスタックを実装しているGoogle謹製のコードがあって、死ぬほど勉強になるので読みましょう https://t.co/7Y0bbij5HL
— Moriyoshi Koizumi (@moriyoshit) April 15, 2018
- リポジトリ: google/netstack
つっつきボイス: 「そうそう、Goに限らずTCP/IPスタックのコードは一度は読んでおくと勉強になりますヨ」
// 同リポジトリより
// GetTCPProbe returns the TCPProbeFunc if installed with AddTCPProbe, nil
// otherwise.
func (s *Stack) GetTCPProbe() TCPProbeFunc {
s.mu.Lock()
p := s.tcpProbeFunc
s.mu.Unlock()
return p
}
// RemoveTCPProbe removes an installed TCP probe.
//
// NOTE: This only ensures that endpoints created after this call do not
// have a probe attached. Endpoints already created will continue to invoke
// TCP probe.
func (s *Stack) RemoveTCPProbe() {
s.mu.Lock()
s.tcpProbeFunc = nil
s.mu.Unlock()
}
⚓Go格言集とGo Conference 2018
- 元記事: Go Proverbs
先週紛れ込んだGo Conference 2018で知りました。元記事には詳しい説明へのリンクがあります。雑に訳してみました。
- メモリ共有で通信するのも、通信でメモリ共有するのもまかりならぬ
- コンカレンシーは並列(parallelism)にあらず
- チャンネルは協調動作(オーケストレーション)のためのもの、ミューテックスはシリアライズのためのもの
- インターフェイスが肥大化するほど抽象化の度合いが落ちる
- ゼロ値を有用なものにせよ
interface{}
それ自身は何の情報ももたらさないgofmt
のスタイルを好きなやつなど誰もいない、だからこそgofmt
は好かれる- 依存をわずかでもこしらえるくらいなら、コピーしてしまえ
- syscallは常にビルドタグで保護しなければならぬ
- cgoは常にビルドタグで保護しなければならぬ
- cgoはGoにあらず
- 安全でないパッケージを使ったが最後、何の保証もありはしない
- 巧みなコードを書くより、明確なコードを書くがよい
- リフレクションが明確になることなどありえぬ
- エラーとは値のことであり、それ以外の何ものでもない
- エラーをチェックするだけでは足りぬ、丁重に処理せよ
- アーキテクチャを設計し、コンポーネントに命名し、詳細をドキュメントに書け
- ドキュメンテーションはユーザーのためのものである
panic
は使うな(「うろたえるな」のダジャレ)
こういうのって言語の思想を手っ取り早く知るのに便利ですね。
つっつきボイス: 「Goの格言、( ・∀・)イイ!!こういうの大事だし、"Concurrency is not parallelism."とかごもっとも」
「ところでこのページのGopherくんの絵、このユルさがもうたまらないw」「この雑なライトセーバーみたいなやつ↓、測ってないけど45度としか思えないw」
今日は #gocon か。いいなぁ。
— mattn (@mattn_jp) April 15, 2018
Go Conference 2018をすごーく手短にまとめると、以下が印象に残っています。多すぎてここには到底盛り込めないので。
- Goの
map
(Rubyで言うハッシュ)は本質的にスレッドセーフにならないし、しない - Go界隈ではマイクロサービスの普及がだいぶ進んでいる(少なくともRails Developers Meetupでの挙手数と比べれば)
- 一方モノリスのよさも見直されつつあったりするらしい: GCPといえども下手にサービスを割るとオーバーヘッドにつながるとか
- Goは公式資料がエクストリームに充実しているので、野良ブログより先にこちらを最初にあさるべし
- GoでORMするならActiveRecordのことは忘れること -- 「ActiveRecordの完成度はやっぱり凄い」という率直な感想も
参考: Go Conference 2018 Spring - 資料一覧 - connpass
⚓その他
⚓同人誌「現代Webフロントエンドデザインパターン」
これを解消したくて「現代Webフロントエンドデザインパターン」書いているけど、とてもSPA/SSRまではたどりつかない。(それ以前の部分で、僕の書く同人誌としては、十分のボリュームになっている。) https://t.co/BSMQwPRxfP
— ぎゃばん@手洗い (@ledsun) April 16, 2018
つっつきボイス: 「BPSのアプリチームには技術書典の常連がいるらしいという噂」「どかっと積み上げてくれるのかな( ^ω^)ワクワク」
⚓大物の独自路線: Microsoftの独自LinuxカーネルとAmazonの独自ブラウザ
- 元記事: Microsoft built its own custom Linux kernel for its new IoT service | TechCrunch
- 元記事: Amazon launches a ‘lite’ Android web browser app in India | TechCrunch
つっつきボイス: 「あーこれねw」「Amazonの独自ブラウザの名前がInternetって...」「誰に挑戦してるんだろうか」
参考: Amazonが容量わずか2MBの軽量版インターネットブラウザ、その名も「Internet」をリリース - GIGAZINE
⚓GCP BigQueryの東京リージョン開始
つっつきボイス: 「お、今まで東京リージョンなかったのか」
クラウド業界でAWSのサービス名の命名センスが他にも広がってるような気が個人的にしています。
⚓その他のその他
いいね / “Kubernetesで実際のメモリを超えるコンテナアプリを動かすと、どうなるか? - あさのひとりごと” https://t.co/NrNEBZdH89
— matsuu (@matsuu) April 14, 2018
コンパイラ作るとね
型の指定が後から現れる(a:int)ことがどんなに嬉しいことか
わかるんだよ— uint256_t (@uint256_t) April 11, 2018
⚓番外
⚓英国BBCのGitHubリポジトリ
- リポジトリ: BBC-News
つっつきボイス: 「仕事中にたまたま見つけてくれた人がいたので」「本物なんですね」「BBCはこういうのをけっこうちゃんとやってますね」
↓動画は直接BBCとは関係ありませんが。
https://www.youtube.com/watch?v=SRpgUV4lHyg
⚓手計算だったし
惑星の公転軌道が真円ではなくて楕円であることは今でこそ広く知られていますけれど、火星の公転軌道と同じ離心率0.093の楕円を見て一目で真円じゃないと思いつける人はそういらっしゃらないと思いますのよ。ブラーエとケプラーはヤバイですわ。 pic.twitter.com/e9Pmvz1pX1
— 宇宙物理たんbot🌏☄️学術系VTuber (@astrophys_tan) April 17, 2018
⚓そこまで精度上がったか
イスラエルの研究者が考案した電力線経由でデータを盗む技術https://t.co/J43wTMDdKy
あらかじめ仕込んだマルウェアが電源制御乗っ取って電力変動でデータ送る。同じオフィスにある機器で拾う。
転送速度超遅いけどネット繋がってないPCからでもデータを盗める。ほぼPLC pic.twitter.com/CI4kWezSPX
— ゆきまさかずよし (@Kyukimasa) April 16, 2018
ビルの窓ガラスの振動を外からレーザー光線で測定して音声を盗聴するという技術を思い出しました。
つっつきボイス: 「おお、この手の技術は実は結構前からあるんですよ」「PLCって?」「まさに電力線搬送通信(Power Line Communication)で、屋内の電源コードを使ってデータ通信する技術」「へー!」「ちなみにPLCやるときはデータをPLC経由では屋外に出せないんですよ」「出せないっていうのは、法律的に?」「そう: 厳しく制限されている」「そっかー、日本は電波法厳しいし」
参考: 電力線搬送通信 - Wikipedia
参考: 電波法 - Wikipedia
⚓複合原子層作製システム
参考: 東大、シート状の原子層を自在に積み重ねるロボットシステムを開発 | マイナビニュース
⚓日本沿岸で全世界数百年分のレアメタル鉱床が見つかる
つっつきボイス: 「どうやって掘り出すかが問題ですからねー」「何しろ海の底なんで」
今週は以上です。
バックナンバー(2018年度)
- 20180413 RailsConf 2018、Form Objectの昔と今、rubyreferences.github.ioのドキュメントがスゴイ、GitHubが10歳にほか
- 20180406 ruby-sass gemが非推奨に、Roda gem、paiza.ioは便利、Linuxは/procで遊ぼうほか
- 20180330 春のリリースラッシュ: Rails 5.1.6/5.0.7とRuby 2.5.1など、Ruby 2.2は3月でメンテ終了ほか
- 20180312 Rails 5.2.0 RC2リリース、「サーバーレスなRubyが欲しい」、capybara風JSテストフレームワークCypressほか
- 20180316 Rails 5.2のドキュメント更新中、Value Objectの使い方、RubyがTIOBEトップテン復活、Rails「雪だるま」エンコーディングほか
- 20180309 RubyGems.orgのTLS 1.0/1.1接続非推奨、2年に1度のRailsアンケート、DockerのMoby Project、Ruby拡張をRustで書けるruruほか
- 20180302 Ruby 2.6.0-preview1とWebpack 4.0リリース、爆速検索APIサービスAlgolia、Clowneでモデルをクローンほか
- 20180223 Ruby25開催、Rails6のパラレルテスト、書籍「RSpecによるRailsテスト入門」更新ほか
- 20180216 Rails 5.1.5リリース、DHHのYouTubeチャンネルは必見、Ruby Toolboxが運営再開ほか
- 20180209 RubyにMJIT初マージ、高速JSON API gem、Railsにparallel-testingブランチほか
- 20180202 Rails 5.2.0 RC1と5.1.5.rc1リリース、Rails 6開発開始、メソッド絵文字化gemほか
- 20180126 Bootstrap 4登場でbootstrap_form gemが対応、PostgreSQLやnginxの設定ファイル生成サービスほか
- 20180119 derailed_benchmarks gem、PostgreSQLをGraphQL API化するPostGraphile、機械学習でモック画像をHTML化ほか
- 20180112 update_attributeが修正、ぼっち演算子
&.
はObject#try
より高速、今年のRubyカンファレンス情報ほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。