こんにちは、hachi8833です。今日のGitHubは何だか不調ですね。
- 各記事冒頭にはでパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを社内有志でつっついたときの会話です
- 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください
臨時ニュース
PostgreSQL 11が正式リリース
つっつきの後でニュースが飛び込んできました。PostgreSQL 10リリースをウォッチでお伝えしたのが2017/10/06なので、わずか1年という驚きのメジャーアップデートですね。
参考: PostgreSQL 11が正式リリース。ハッシュパーティショニングやJITコンパイルによる高速化、ストアドプロシージャでのトランザクションサポートなど - Publickey
Ruby 2.5.3が追加リリース(Ruby公式ニュースより)
Hello Rubyists, as I announced in https://t.co/FCRDMVpsgc, I have released ruby-2.5.3. https://t.co/Ju4mzUwWyg This is just for fixing packaging issue. Sorry for repeated releases.
— nagachika (@nagachika) October 18, 2018
2.5.2のパッケージングの問題(#15232)のみを2.5.3で修正したそうです。
TechRacho記事にも反映しました↓。
Rails: 先週の改修(Rails公式ニュースより)
今回公式の更新情報がなかったので直近のコミットから見繕いました。ドキュメント(Railsガイド)の更新が目立ちます。
ActiveRecord#respond_to?
のアロケーションを削減
- PR: ActiveRecord#respond_to? No longer allocates strings by schneems · Pull Request #34197 · rails/rails
#34227と関連しています。
# activerecord/lib/active_record/attribute_methods.rb#L261
def respond_to?(name, include_private = false)
return false unless super
- case name
- when :to_partial_path
- name = "to_partial_path"
- when :to_model
- name = "to_model"
- else
- name = name.to_s
- end
# If the result is true then check for the select case.
# For queries selecting a subset of columns, return false for unselected columns.
# We check defined?(@attributes) not to issue warnings if called on objects that
# have been allocated but not yet initialized.
- if defined?(@attributes) && self.class.column_names.include?(name)
- return has_attribute?(name)
+ if defined?(@attributes)
+ if name = self.class.symbol_column_to_string(name.to_sym)
+ return has_attribute?(name)
+ end
end
true
end
つっつきボイス:「Active Recordのrespond_to?
ってそもそも使ったことないけど何に使うんだろか?」「改修そのものは:to_partial_path
でStringをアロケーションしてたのをやめたという単純な内容で、アロケーションと速度が少し改善したと↓」
# 同PRより
Before: Total allocated: 752009 bytes (6527 objects)
After: Total allocated: 743921 bytes (6325 objects)
Diff: (752009 - 743921) / 752009.0 # => 1.05%
「respond_to :to_partial_path
とかrespond_to :to_model
とか知らないし: ちょっと追ってみよう(IDEを起動)」
参考: ActiveRecord::AttributeMethods::ClassMethods respond_to?(name, include_private = false)
name
属性を持つPerson
オブジェクトにはperson.respond_to?(:name)
やperson.respond_to?(:name=)
やperson.respond_to?(:name?)
するとtrue
を返す。また、属性メソッドが生成されていなければ定義する。
APIドキュメントより大意
class Person < ActiveRecord::Base
end
person = Person.new
person.respond_to?(:name) # => true
person.respond_to?(:name=) # => true
person.respond_to?(:name?) # => true
person.respond_to?('age') # => true
person.respond_to?('age=') # => true
person.respond_to?('age?') # => true
person.respond_to?(:nothing) # => false
「ふむぅ、APIドキュメント↑に書いてあることはわかるんだけど、to_partial_path
やto_model
が何なのかだな〜こいつらはメソッド呼び出しじゃないし」「↓このあたりの記事を見るとActiveModelに前からto_partial_path
があるのか」「日本語記事にはto_partial_path
をオーバーライドできる↓って書いてるし」
# o.inchiki.jpより
class User < ApplicationRecord
def to_partial_path
if user.admin?
"users/admin_user"
elsif user.guest?
"users/guest_user"
else
"users/user"
end
end
end
参考: ActiveRecordのto_partial_pathをオーバーライドしてパーシャルを文脈によって使い分ける [俺の備忘録]
参考: Rendering Collections in Rails — Thoughtbot blog
「このpartialはビューのパーシャルなんですよね?」「ですね: render
にActive Recordオブジェクトを直接渡すとパーシャルに展開してくれるメソッドがto_partial_path
」「改修の話と離れてきたのでとりあえずこの辺で」
参考: ActiveModel::Conversion to_partial_path()
「ところで、コントローラには?
なしのrespond_to
というとっても紛らわしい名前のメソッドがありますね」「あーそういえば!」「述語メソッドじゃないから?
は付かないんだけどホント紛らわしい」
参考: ActionController::MimeResponds respond_to(*mimes)
def index
@people = Person.all
respond_to do |format|
format.html
format.js
format.xml { render xml: @people }
end
end
Active SupportのChars#reverse
とChars#grapheme_length
をリファクタリング
# activesupport/lib/active_support/multibyte/chars.rb#L115
def reverse
chars(Unicode.unpack_graphemes(@wrapped_string).reverse.flatten.pack("U*"))
- chars(@wrapped_string.scan(/\X/).reverse.join)
+ end
...
def grapheme_length
- Unicode.unpack_graphemes(@wrapped_string).length
+ @wrapped_string.scan(/\X/).length
end
つっつきボイス:「これも含めて今回はUnicode/マルチリンガル関連の改修が目立ちました: Rubyのマルチリンガル機能がよくなってきたからActive SupportよりRubyのメソッドを使おうという流れみたいです」「あ〜、確かにそれは正しい方向」「reverse
はともかくgrapheme_length
?ぐらふぇめ?」「graphemeは確か言語学方面の用語ですね↓日本語だと『書記素』…」「今はscan(/\X/).length
で取れるようになったと」
参考: 書記素 - Wikipedia
Ruby 2.5.3 + Rails 5.2.1のコンソールで試してみました。
'क्षि'.mb_chars.length #=> 4
'क्षि'.mb_chars.grapheme_length #=> 2
'क्षि'.scan(/\X/).length #=> 2
以下のプ
は見た目ではわかりませんが半濁点が分離しています(は゜
のように分離が見えるものとは異なります)。
a = "プ"
a.mb_chars.length #=> 2
a.mb_chars.grapheme_length #=> 1
a.mb_chars.scan(/\X/).length #=> 1
# normalizeするとmb_chars.lengthは1になる
b = ActiveSupport::Multibyte::Unicode.normalize(a, :c)
b.mb_chars.length #=> 1
b.mb_chars.grapheme_length #=> 1
b.mb_chars.scan(/\X/).length #=> 1
mb_chars.length
はnormalizeで変わりましたが、mb_chars.grapheme_length
は変わりませんでした。
参考: Unicodeのgrapheme cluster (書記素クラスタ) | hydroculのメモ
scaffoldでフィールドに:references
を指定するとindexページやshowページでidではなくメモリアドレスが表示される問題を修正
#29200の修正です。
# railties/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt#L18
<% attributes.reject(&:password_digest?).each do |attribute| -%>
- <td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
+ <td><%%= <%= singular_table_name %>.<%= attribute.column_name %> %></td>
<% end -%>
つっつきボイス:「これはもろバグ」「attribute.column_name
にしたかったのにattribute.name
だとモデルオブジェクトを取っちゃう」「実はscaffoldで:references
を指定する人がほとんどいなかったりして」
「ところで最後にscaffold使ったのっていつですか?」「scaffold、ほぼ使わないっすね: rails g
ですらマイグレーションにしか使わないし」「やっぱり〜」「scaffoldって初心者アイテムなんでしょうか?」「というより、ある程度以上複雑なRailsアプリを書いているとscaffoldでは追いつかないですね」
「コントローラだけならscaffoldでもよさそう?」「scaffoldだと余分なものが作られがちなのであまりしないけど、先にモデルを作ったときなんかにscaffoldすることはたまにあるかな」「ボク全部手で書いてますけど」「さすが職人!」「わかりみ: 書く量も大したことないですしね」「むしろscaffoldのオプションを覚える方が面倒」
「ちなみにRubyMineではscaffoldも一応GUIでできて↓、アクション名とか名前空間も指定できる: ま使わないけど」
「Railsのscaffoldって名前空間があると急に使いづらくなってくるところがある」「名前空間を指定してscaffoldすることは可能みたいですね」「できるけど微妙にかゆいところに手が届かなくて、たとえばモデルだけ名前空間を変えたいみたいな指定ができなかった気がする: 何しろ普段scaffoldしないので」「そこで考えるぐらいだったらとっとと普通にファイル作って書いた方が早い」「scaffoldだとアクションのURLコメント↓を自動的に付けるけど、コードが変わったときに自動更新してくれるわけでもないからそんなに意味ないし」
# POST /users
# POST /users.json
def create
...
「そういえば最近のscaffoldはstrong parametersも自動的に付けるんじゃなかったかな↓」「strong parametersのテンプレ、いらね〜」「お、scaffoldのテンプレを開くとparams.fetch
とparams.require
が使い分けられてるし」「ちょうど今日のチームミーティングでfetch
とrequire
をどう使い分けるかって話になりましたね」「この2つは要件に応じて使い分けるべき」
# rails/generators/rails/scaffold_controller/templates/controller.rb.tt
...
private
# Use callbacks to share common setup or constraints between actions.
def set_<%= singular_table_name %>
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
end
# Only allow a trusted parameter "white list" through.
def <%= "#{singular_table_name}_params" %>
<%- if attributes_names.empty? -%>
params.fetch(:<%= singular_table_name %>, {})
<%- else -%>
params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
<%- end -%>
end
end
<% end -%>
「ところで上はscaffold用だからstrong parametersのテンプレがあるけど、通常のコントローラをgenerateするときのテンプレートにはstrong parametersはないはずですよね?」「お、言われてみれば確かに↓たったこれだけしかない」「意外とシンプルっすね」「そしてこっちにはURLコメントのテンプレは含まれてないな」
# rails/generators/rails/controller/templates/controller.rb.tt
<% if namespaced? -%>
require_dependency "<%= namespaced_path %>/application_controller"
<% end -%>
<% module_namespacing do -%>
class <%= class_name %>Controller < ApplicationController
<% actions.each do |action| -%>
def <%= action %>
end
<%= "\n" unless action == actions.last -%>
<% end -%>
end
<% end -%>
「定数読み込み順と名前空間」地獄とrequire_dependency
require_dependency
から、名前空間と定数読み込み順の話題に大きくシフトしました。
「お、上のテンプレでrequire_dependency
を使ってるし」「へー、名前空間があるとrequire_dependency
を付けるのかー」「普通のrequire
とは違うみたいですけど、これって何のおまじないでしたっけ?」
「むむ…うろ覚えだけど、確かletter_openerっていう本番以外でメールを飛ばさないようにするgemでどハマったときに見たのを思い出してきたぞ」「自分も同じようなところでハマったことあり」
「たとえば以下のようにHoge
モジュールの下にPiyoController
があるとするじゃないですか、するとHoge::ApplicationController
と、トップレベルからの::ApplicationController
という2とおりの探索パスが存在することになるんですよ」「この2つは、そのままだと先に見つかったものが使われるんです」「読み込み順は必ずしも一定じゃないので」
module Hoge
class PiyoController < ApplicationController
end
# 上のようにネストで名前空間を作ると、以下の2つの探索パターンが形成される
# Hoge::ApplicationController
# ::ApplicationController
参考: 定数の自動読み込みと再読み込み — 7 require_dependency | Rails ガイド
「ところがこれでは、Hoge::ApplicationController
を指定して取りたくても、先にトップレベルの::ApplicationController
が見つかるとHoge::ApplicationController
が取れなくなってしまうんですよ」「それを回避するために、欲しい名前空間をrequire_dependency
で確定しておく必要があるという」「ほぁ〜」
「RailsのModule#autoload
って定数の読み込みに「失敗したとき」(const_missing
)でないと動き出さないので、定数が既に読み込まれちゃっていると動いてくれないんですよ」「あー、定数がもう埋まっちゃってるから発動しないのか」「letter_openerでも回避のためにrequire_dependency
を追加したコミットが確かあったと思います(たぶん#82)」
参考: 定数の自動読み込みと再読み込み — Module#autoload
が関与しない場合| Rails ガイド
「今の例はApplicationController
だから動かなくなればすぐ気づけるだけまだマシな方: これが名前空間化されたモデルへのアクセス中に発現すると致命的な問題になる可能性があるのがコワイ」「ぎょぎょ!」
「たとえば、コントローラのアクションでCustomer.find(params[:id])
のようにモデルにアクセスするとして、モデルがAdmin
で名前空間化されていると::Customer
とAdmin::Customer
のどちらかが使われてしまうんですが、こういう場合えてしてAdmin::Customer
の方がはるかに権限が強いので、::Customer
のつもりで書いていたのがAdmin::Customer
から取ってきてしまったり、逆にAdmin::Customer
のつもりなのに::Customer
から取ってきてしまうと(こっちの方がありそうかな)トンデモナイことになる」「何というお漏らし…」
「回避方法としてはrequire_dependency
もあるけど、やっぱり名前空間べた書きですかね」「そっ: 自分もこれでハマって以来Customer.find(params[:id]
じゃなくて必ず::Customer.find(params[:id]
みたいに::
を明示的に書くようになったし↓」「何だかすっごく不便…」
# require_dependency
module Admin
class PiyoController < ApplicationController
# Admin::ApplicationController
# ::ApplicationController
def show
@customer = ::Customer.find(params[:id])
# Admin::Customer
# ::Customer
end
end
end
「でなかったら、そもそもネストじゃない方法で名前空間を作ることでしょうね」「同意: 自分も名前空間はこうやってネストなしで書くようにしている↓」「これなら名前空間が揺れようがないし」「階層も浅くなるし」
# morimorihoge like
class Admin::PiyoController < Admin::ApplicationController
...
end
「ただ、流派としてはどちらのやり方もあるみたい」「自分は今のclass Admin::PiyoController
がいいと思います!」「自分も」
「ちなみにこれはRailsエンジンを書くときにも注意しなければいけないハズ(某案件でそういう目に遭ったし)」「そうそう、エンジンなんかは特にそうだけど、想定外の名前空間掘り下げにはホント要注意: サードパーティのモジュール内で発生すると地獄を見る」
「現象としては、動いているはずのないモジュールのメソッドがなぜか呼ばれる」「しかもそのモジュールをいくら調べても原因がわからなくて、::
を付けて呼び出すとなぜか解消するという」
「もうひとつの現象としては、たとえばdevelopmentモードだと正しく動くのにproductionだと動かなくなる(あるいはその逆)」「読み込み順が環境で変わることがあるのか…」「productionだと全部読み込んでから開始するけど、developmentだと使おうとして見つからないときに初めて読み込まれるから」「letter_openerはdevelopmentでしか使わないgemだから、まさにdevelopmentでだけ動かないという現象を引き起こしました」
「この問題を一度踏めば『二度と踏みたくない!』って気持ちになるから、無精しないで名前空間をきちんと書くようになりますよ」「踏んだことないと、何が起こったのかすらわかりませんからね…自分も踏んだのは今年になってからでしたし」
「今思えば、自分はずっと前からclass Admin::PiyoController
みたいに名前空間べた書きにしてたんでこの問題を踏みようがなくて、逆に気づく機会がなかったんですよ」「それがたまたま誰かが他の書き方したか何かでネストになった箇所でrequire_dependency
し忘れたりして、それで初めて遭遇しました」
「ネストしない書き方ならこの問題は起きないんでしょうか?」「ネストしない書き方なら完全にグローバルスコープになるので起きませんね: さっきの例で言うと、Customer
と書いたときに必ずグローバルなCustmer
だけを見に行くし、Admin::
名前空間に入らないのでそもそも探索が発生しない」「なるほど!速度的にもよさそう」
「すごく詳しい説明!ありがとうございます」
ActiveSupportのUnicode関連メソッドが続々変更・deprecation
- PR: Deprecate Unicode#downcase/upcase/swapcase. by frodsan · Pull Request #34123 · rails/rails
- PR: Deprecate Unicode#normalize and Chars#normalize. by frodsan · Pull Request #34202 · rails/rails
使われなくなったActiveSupport::Multibyte::Chars.consumes?
がdeprecateになって今後はString#is_utf8?
を使い、ActiveSupport::Multibyte::Unicode
の#downcase
、#upcase
、#swapcase
がdeprecateになって今後はString
のメソッドを直接使うようにとのことです。
また、Unicode#normalize
やChars#normalize
もdeprecateになり、今後はRubyのメソッドを使うことになるようです。
つっつきボイス:「RubyでできるようになったからRubyでやろうぜってことみたいです」「なるほど、Rubyが変わるとこういう改修が入りますね: #upcase
や#downcase
もRubyでやれるようになったのか」「マルチリンガルでできるということでしょうね」
「#capitalize
もRubyでやれるようになってるのかな…なってるし↓!」「Rubyはこういうのに対応しててエライな」
参考: instance method String#capitalize (Ruby 2.5.0)
なお、Rubyの#10085ではen
やtr
などで言語を指定する形になっていましたが、現在はオプションなし以外は:ascii
、:turkic
、:lithuanian
、:fold
のみとなっています。また、置き換え方法はエンコーディングにも依存します。大文字小文字の変換はマルチリンガルになると単純にはいかないので苦労が偲ばれます。
参考: instance method String#downcase
(Ruby 2.5.0)
「#normalize
って何だったかな」「えっと、ひらがなやかたかなの濁点や半濁点が本体の文字と泣き分かれになってるときなんかに使いますね: MacとWindowsでファイル交換するとファイル名でよく起きるヤツ」「あぁそれね」「アルファベット語圏だと文字とアクサンが分離しているときにも使うみたいです」「normalizeってUnicodeだとそういう文脈なんだ〜: normalizeっていろんな意味があるし: 特にコンピュータサイエンスの文脈だと」「確かに」
UnicodeのnormalizeはNFD/NFC/NFKD/NFKCとありますが、分離したものも再合成されたものもそれぞれ正当です。さらにMacのファイル名正規化は独自仕様が含まれるらしいので困ったことです。処理対象に複数の正規化形式が入り混じってしまうと厄介なので変換の際はnormalizeを心がけたいですね。
[Rails5] Active Support Core Extensionsのマルチバイト系メソッド: String#mb_charsとis_utf8?
モデルattribute accessorのメソッド名を改善
# activemodel/lib/active_model/attributes.rb#L29
private
- def define_method_attribute=(name)
- safe_name = name.unpack1("h*")
- ActiveModel::AttributeMethods::AttrNames.set_name_cache safe_name, name
-
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
- def __temp__#{safe_name}=(value)
- name = ::ActiveModel::AttributeMethods::AttrNames::ATTR_#{safe_name}
- write_attribute(name, value)
- end
- alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
- undef_method :__temp__#{safe_name}=
- STR
+ ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
+ generated_attribute_methods, name, writer: true,
+ ) do |temp_method_name, attr_name_expr|
+ generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def #{temp_method_name}(value)
+ name = #{attr_name_expr}
+ write_attribute(name, value)
+ end
+ RUBY
+ end
end
つっつきボイス:「リファクタリングかな?」「あー、属性のアクセサメソッドをメタプログラミングで動的に定義しちゃうとバックトレースで名前が出てこないことがあるから、attr_name.ascii_only? && DEF_SAFE_NAME.match?(attr_name)
の条件がtrue
ならそのままの名前で定義するってことか」「上のコードの↓この部分で名前を明示的に宣言するように変わってる: それ以前はmodule_eval
で無名メソッドを作ってからalias_method
してたけど、その場合バックトレースにはエイリアスではなくオリジナルの__temp__
が出てしまう」「確かに__temp__
で塗りつぶされちゃうと追いにくいですね」
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
generated_attribute_methods, name, writer: true,
)
「define_attribute_accessor_method
って、define_method
の属性アクセサ版みたいなものかしら」「わがんね」「attribute_methods.rbに今回追加されたクラスメソッドがこのdefine_attribute_accessor_method
ですね: 直接使うことはまずなさそうだけど」
# activemodel/lib/active_model/attribute_methods.rb#L499
def self.define_attribute_accessor_method(mod, attr_name, writer: false)
method_name = "#{attr_name}#{'=' if writer}"
if attr_name.ascii_only? && DEF_SAFE_NAME.match?(attr_name)
yield method_name, "'#{attr_name}'.freeze"
else
safe_name = attr_name.unpack1("h*")
const_name = "ATTR_#{safe_name}"
const_set(const_name, attr_name) unless const_defined?(const_name)
temp_method_name = "__temp__#{safe_name}#{'=' if writer}"
attr_name_expr = "::ActiveModel::AttributeMethods::AttrNames::#{const_name}"
yield temp_method_name, attr_name_expr
mod.send(:alias_method, method_name, temp_method_name)
mod.send(:undef_method, temp_method_name)
end
end
参考: instance method Module#define_method
(Ruby 2.5.0)
Rails
clean-rails.org: Railsのきれいなコードについて日本語で議論するコミュニティ
- Discourse: clean-rails.org
- サイト: clean-rails.org | clean-rails.github.io
以下の記事で知りました。
参考: Rails開発で技術的負債を増やさないために知っておきたいこと - ログミーTech(テック)
つっつきボイス:「あーこれか: 以前誰かがこういうサイトやろうぜって話してた気がする」「上の記事に登場する前島真一さんが始めたみたいです」「知ってる顔が多いかも」「中級者以上が集う感じなので人数が多くないのは致し方ないかな」「中級者以上がそもそも少ないですし」
「実は中級者以上の設計上の悩みを説明するのってすごく大変なんですよ: 社内みたいにコンテキストがある程度共有されていればまだしも、そうでないと説明が恐ろしく長くなりがち」「確かに説明を書いているうちにダルくなりそう」「請負開発案件の悩みだったりすると、ソースコードをそのまま貼ったらNDAに違反するからソースを作り直さないといけないし」「ソースを貼らなくても前提条件の説明だけでNDAに抵触するかもしれないので、案件から切り離した前提を考えるのも大変」
「設計って最終的に好みが分かれるものだし、どこまでやるか/これはやりすぎかみたいなのも悩ましいし」「そういう感じで純粋に設計上の話をするならこのclean-railsはいい場なんじゃないかと思いますね」
Rails 6.0の新機能をRailsコントリビュータがひたすら記録するサイト(Ruby Weeklyより)
つっつきボイス:「このbogdanvlvivさんはRailsのコントリビュータで、彼が収集したRails 6.0の新機能が上の記事にとってもきれいにまとまってます」「これまでウォッチで扱ってきたからだいたい見覚えある」「Changelogから抜いてきた感」「でもChangelogよりずっと見やすいですね」
「へー!#31944でdelegate
にprivate: true
オプションが追加↓ですって」「えっナニソレ?」「これはウォッチで扱ってなかったか…」
# 31944より
class Foo
# ...
delegate :foo, :bar, to: :baz
delegate :car, :dar, to: :daz, private: true
# ...
end
foo = Foo.new
foo.foo
foo.bar
foo.car # => NoMethodError: private method `car' called for #<Foo:0x000000015e8b10>
foo.dar # => NoMethodError: private method `dar' called for #<Foo:0x000000015e8b10>
「ここしか見ずに言うと、delegate
したメソッドをあたかもdelegateしたかのように自分のクラスでだけ呼び出したいときに使うんだろうな: かつpublicにはしたくないと」
「そもそもRubyのprivateメソッドってdelegateできるものでしたっけ?あるいはdelegateはできるけどprivateにしかできないとか?」「Rubyのprivateメソッドはdelegateできないはず」
「だから上のコードはcar
やdar
はそのメソッドをFooクラスの中でprivateにするという指定なんだろうと理解してる」「delegateはする側とされる側の関係がややこしい」
SQLインジェクションを防ぐ正規表現がRailsに導入?
- 元記事: Rubyで安全な文字列リテラルかどうかを判別したい - かみぽわーる
- PR: Disallow raw SQL in dangerous AR methods by mastahyeti · Pull Request #27947 · rails/rails
- PR: “Dangerous query method” deprecation warning matches `random()` function call · Issue #32995 · rails/rails
#27947はcloseされているので改修ではありませんが。#32995も現在openです。
つっつきボイス:「最近はてブで話題になったkamipoさんの記事です」「そういえばこの記事読んだ」「Post.order(params[:order])
みたいにorder
の中に直接paramsを置くとアブナイよというヤツ: order
に限らず、ActiveRecordのwhere
とかgroup_by
とかに直接文字列を突っ込むのは基本的に怪しみを感じるべき」「」「シンボルとかハッシュで定義しないと怪しみが残る」
「で#27947を見に行ったらcloseされてました」「正規表現でチェックってw」「でもそうするしかないだろうな…」
「その#27947のホワイトリストは↓のようになってて、これ以外のものは突破できないようにするってことか: たいていこうなるから自分は別に構わないっすけど」「いやいや油断は禁物、MySQLはSELECTしてないカラムでorderingできるんですよ」「あーそうだったかも」「だから関数カラムでもorderingできるはず」
# Regexp whitelist. Matches the following:
# "#{table_name}.#{column_name}"
# "#{table_name}.#{column_name} #{direction}"
# "#{column_name}"
# "#{column_name} #{direction}"
「たしか標準SQLではSELECTしたカラムでないとorderingできないことになってるので、関数を使ったカラムはいったんAS なんちゃら
して、それに対してorderingする必要があった」「それがMySQLはそこんところが残念というかアグレッシブで、SELECTしてなくてもorderingできる: しかもこれがMySQLであまりにも普通に使われてるせいで、DBMSが変わると動かなくなる」
「あ、今はもしかするとMySQLもstrictレベル上がって修正されてるかもしれないけど?」「でも後方互換性を維持しているなら今でもできちゃいそう」「少なくとも以前のMySQLはそうでしたね」
「#27947のこの正規表現↓って、スペースではない文字に+
を付けてるってことかな…?」「正規表現の\w
は語の境界を取るときに使いますね: だから\w+
が1つの語を表す」「\w
による語の境界はスペースでも区切られるし、「:」とか「_」みたいな記号でも区切られるヤツ:日本語の漢字熟語の区切りは判定しようがありませんが」
COLUMN_NAME_ORDER_WHITELIST = /\A(?:\w+\.)?\w+(?:\s+asc|\s+desc)?\z/i
「ともあれ、この書き方はひたすら語をチェックしているだけで、それが実際のSELECTやカラム名かどうかまではチェックしてないってことですかね」「SQLインジェクションを防ぐのが目的だからそこまでは頑張ってなさそう」「だからMySQLでしか通らないクエリも通って幸せ」「幸せっちゃ幸せですが」「そしてPostgreSQLに投げるとエラーになると」
ちなみに(?:)
はキャプチャを抑制する記法で、少々うざい代わりに高速化されます。普通に()
でグループ化すると常にキャプチャされます。
「明らかに安全だと思うリテラルまでRailsに危険とみなされるとつらい人もいるってkamipoさん記事にありますね」「そうそう、この改修が入るとDiscourseが5.2にあげようとするとつらいって言ってますね」「Discourseってまさにさっきのclean-railsが置かれているサイトですよね」「まあそれは元の書き方がそもそもよくないから直せって思うけどなっ」「直せるなら、ね」
ActiveSupport::StringInquirer
のマジック(RubyFlowより)
# 同記事より
class StringInquirer < String
private
def respond_to_missing?(method_name, include_private = false)
(method_name[-1] == "?") || super
end
def method_missing(method_name, *arguments)
if method_name[-1] == "?"
self == method_name[0..-2]
else
super
end
end
end
つっつきボイス:「すとりんぐいんくわいやー、使ったことないなー」「自分もないけどRailsの内部で使ってるんですかね」「あ、string_inquirer.rbのAPIドキュメントにそのまんま書いてある: Rails.env == 'production'
っていうダサい比較をしなくてもRails.env.production?
で判定できるようになる、いつも使ってるヤツだ」「いかにもメタプロですね」
参考: ActiveSupport::StringInquirer
参考: ActiveSupport::StringInquirer を使って、ステータスを active? みたいに管理する
「これはRailsのconfigでもよくRails.configuration.なんちゃら?
みたいに使われてるやつですね」「そして中身はrespond_to_missing?
とmethod_missing
でやってる: そうするしかなさそうだし」「ハッシュに’staging’とかが入っててもメソッドが生えてくるのはこいつのおかげでしたか」
「StringInquirer
って、名前から想像が付きにくい機能」「英語圏では自然な名前なんだろか?」「inquireってaskやqueryに近いけどもっと堅苦しくて、広い意味では『調査』ですけど、手元の串刺し検索辞書で見ると警察などによる公の調査というニュアンスもあるみたいです」「method_missing
するまで捜査するみたいな」
映画「市民ケーン」では、主人公のケーンが世論操作に使う架空の新聞がその名も「The New York Inquirer」だそうです。皮肉も入っていると思いますが。
ActiveSupportのArray#extract!
メソッド
link: Rails Active Support Array Extract! https://t.co/Ukk0jk1HZq
— Bogdan (@bogdanvlviv) October 18, 2018
webpack-serveはdeprecatedになった
- リポジトリ: webpack-contrib/webpack-serve: [DEPRECATED] A lean, modern, and flexible webpack development server
「ついこの間Webpackerの記事を出したときに調べたら、本命だったはずのwebpack-serveがいつの間にかdeprecateになってて、元のwebpack-dev-serverを使ってくれとのことです」「マジでー?」「webpack-serveがメンテナー不在になったらしく」「ひどい: webpack-serveとwebpack-dev-serverって実装は別だった気がするけど」「結局その間webpack-serveを使わなかった人が優勝ってことじゃないすか」「」「もうコントか何かみたいに振り回されて」
「古い情報が半端に残ってると今後も踏み続ける人が出る予感」「はい、以前出した『Webpacker公式ドキュメントの歩き方』↓や『Rails 5: Webpacker公式README』の訳注で『今後はwebpack-serve』と書いていたので、もちろんこのことを追記しておきました」
その他Rails
- 元記事: Rubysec — Nokogiriで複数の脆弱性報告(Ruby Weeklyより)
- サイト: Rails Assets — Railsのアセットを一元管理するサイト
source 'https://rails-assets.org' do
gem 'rails-assets-bootstrap'
gem 'rails-assets-angular'
gem 'rails-assets-leaflet'
end
つっつきボイス:「Railsのこういうアセット一元管理って一度はみんな考えそうかなと思って」「ああ昔こういうの流行りましたね: ここはrails-assets.orgにホスティングしてるようですが、もう今はWebpackerでやるし」「やらないとマサカリが飛んでくるし」
Ruby trunkより
Ruby 2.5.2/2.4.5/2.3.8リリース
記事そのままですが。
提案: OpenStruct
でハッシュオブジェクトを再帰的にOpenStructオブジェクトに変換する機能
つっつきボイス:「ちょうど先週のウォッチでもOpenStruct
が話題になりましたね」「OpenStruct
使うつもりないし」
Ruby
Rubocopをパフォーマンス改善ツールとして使う(Ruby Weeklyより)
翻訳記事でもお世話になっているschneemsさんのブログです。
array = ["a", "b", "c"]
array.compact.flatten.map { |x| x.downcase } # compact, flatten, mapでarrayがアロケートされる
つっつきボイス:「duplicate array allocationのチェックにRubocopを使う、そういうルールを使えば確かにできるな」「もともとRubocopってそういうものだし」
CLI版「12 Factor CLIアプリ」(Ruby Weeklyより)
つっつきボイス:「12 FactorといえばThe Twelve-Factor Appですけど、そのCLI版ってことみたいです」「どことなく自称感漂う」
「あー、1.のヘルプの出し方といえばJavaが頭に来る」「というと?」「Javaだけ-help
」「-
が1個だけ!」「やめて欲しいわ〜」
「4.のストリームを重視、これはUNIXの基本ですし」
「6.の↓こういうメタな文字を入れるのはちょっとな〜、コピペすると化けたりするし」「Powerlineで頑張りすぎてそういう目に遭ってます」「こうやっていい感じにして、そして重くなるという」「カラーリング頑張りすぎるのもね、たまにVT-100みたいなむちゃ古い端末でssh rootすると文字化けまくったりするし」
「RubyKaigiか何かでこんな感じにできるCLIのgemについて発表してた人がいた気がする」「んー、ググってもそれらしいのが見つからない…」
Rubyのメソッド探索、RubyVM.stat
、グローバルステート(Ruby Weeklyより)
つっつきボイス:「Rubyのパフォーマンスチューニングでお馴染みのNoah Gibbsさんの記事です」「メソッドキャッシュがいつできるか、みたいなお話」「Global Constant Stateなんてのもあるのね」
Ruby 1.8〜2.5のString
の進化(Ruby Weeklyより)
つっつきボイス:「Rubyに限らず、String
って一番使われるだけあって結構変遷があるんですよね」「2.1から2.5はそれほど変わってないのか」「バージョンごとのベンチも取ってますね↓」
「何やかやで、RubyのString
は手厚くてよくできてるなって思う」「JavaScriptのはつらいな〜」「つかRubyのString
が強すぎる!ホント何でもできる」「万能感ありありですね」「String
のメソッドめちゃめちゃ多いですし、正規表現使わなくてもかなりのことができますよね」「正規表現も必要ならさっと呼べるし、楽すぎる」
monotime: 単調増加クロックgem(Ruby Weeklyより)
- リポジトリ: Freaky/monotime
# 同リポジトリより
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
do_something
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
Rustにインスパイアされたそうです。
つっつきボイス:「名前でもろわかるように、ちゃんとCPUクロックから時間を取ってくるヤツですね」
EndohさんがRubyを「簡潔ビットベクトル」で高速化
Rubyの実行速度を非線形から線形に改善した話をクックパッド開発者ブログに書きました。
簡潔ビットベクトルでRubyをlog N倍速くした https://t.co/hhOwa9SPT3
— Yusuke Endoh (@mametter) October 17, 2018
つっつきボイス:「これも話題になってましたね」「簡潔ビットベクトル!」「英語で何て言うんだろう」「TracePoint化での速度を改善するのか」「かなりコアな部分の改造っぽいですね」「めちゃニッチ」
簡潔ビットベクトルは「succinct bit vector」だそうです。
参考: 簡潔データ構造 - Wikipedia
参考: 簡潔データ構造超入門III ~簡潔ビットベクトルで転置インデックスを効率的に実装する~ - EchizenBlog-Zwei
「こういうふうにテーブルから引っ張ってくるシチュエーションって、プログラムのあらゆるところに数えきれないぐらいありますね: それこそJavaScriptのイベントハンドラなんかもこんな感じでできているし、あとOSの割り込みベクタテーブルなんかもそうだし」
参考: JavaScriptのイベントハンドラ一覧|イベント|JavaScript/DOM|PHP & JavaScript Room
参考: 割り込み
Matz手ずからのRubyスタイルガイド
- 元記事: Matzにっき(2004-10-06)
2004年です。
つっつきボイス:「とっても短いです」「おーシンプルなスタイルガイド」「kind_of?
やis_a?
を使わずにダックタイピングする」「末尾が!
のメソッドはなるべく作らない…今とだいぶ違うなー」
「これ↓って何?…あー、ライブラリファイルをそのまま呼び出すとサンプルプログラムとかが走るってことか」「あーなるほど!」「ライブラリとして使うと何も起きないのね」「$0
は実行中のRubyスクリプト名を取れる特殊変数か」「スタイルというよりハックっぽいな〜」
ライブラリファイルの末尾には
if __FILE__ == $0
で囲んで テストケース(かサンプルプログラム)を書いておくとよい。
rubyist.netより
「Matzもちゃんと書いてる: 未来の自分が混乱しそうと思ったことは躊躇せずコメントするって」「これは大事」
その他Ruby
Ruby25周年記念小冊子を公開しました https://t.co/e4LcxBmf6V
— Ruby Association (@rubyassociation) October 17, 2018
クラウド/コンテナ/インフラ/Linux/Serverless
ELBSecurityPolicyとは
つっつきボイス:「社内Slackに投下してもらったやつですが、ELBSecurityPolicyって何だったかなと思って」「このセキュリティポリシーは、SSLやTLSでサーバーとハンドシェイクをするときに、どういう暗号化方式を使える/使ってよいかという情報を最初に交換するんですよ」「サーバーはこれこれの暗号化方式を使ってよいというリストを渡して、クライアントはその中から暗号化方式を選べます」「あーなるほど!」「そのときに選べるのがこのELBSecurityPolicy↓」
「あんまり新しい暗号化方式を選ぶと困ることとかあった気がする」「古代のガラケーなんかでは新しい暗号化方式に対応できなかったりするので、ポリシーを厳しくしすぎてたとえばAES256-*
系を禁止したりするとTLS通信がコケることがある」「DES-CBC3
もめちゃ古いな〜」
「ELBSecurityPolicyは基本的にデフォルトのポリシーを選びます(今は「2016-08」)が、実は今のデフォルトポリシーではTLSv1やTLSv1.1が許可されているのであまりよくない」「あー」「AES128やAES256も今は時間をかければ突破できますし」「通信でサポートする環境にもよりますが、デフォルトより強くしたければ、もっと強いポリシーを選択する必要がある」「ちなみにELBのLoad Balancer(確かClassic)だとセキュリティポリシーは自分で定義することもできるはず」「なるほど!」
参考: Classic Load Balancer での事前定義された SSL のセキュリティポリシー - Elastic Load Balancing
「GitHub Actions」とは
まだ本格稼働はしてない様子です。
つっつきボイス:「つい最近発表されたようです」「あーこれねGitLab Pipelinesのいただきっぽいやつ」「あ、そっちに前からあるんですね」「↓こうやってaction
で書けるところとかもGitLab Pipelinesみたい」「この辺はGitLabの方が進んでます」「とは言え、GitHubがあんまりこの辺を自前でやるとCircleCIとかがボヤくかもしれませんが」
参考: Introduction to pipelines and jobs | GitLab
参考: gitlab.com で いますぐCI してみよう - Qiita
「GitLabといえば、morimorihogeさんが今年の夏書いたGitLab記事↓のビューが凄く伸びてるんですけど、もしかするとマイクロソフトがGitLabを獲得したのと関係あるのかなと思って」「そんなに伸びてる?みんなどういう部分を読んでるのかな」「そのGitLab記事ってどんな内容ですか?」「GitLabサーバーを自前で立てる話です」「とするとタイミング的にはありそうですね」
「記事にもありますけどBPSのGitLabサーバーはユーザー数が多いんですよ↓: これをGitHubでやろうとすると大変」
「GitHub Actionsの料金体系ってどうなるんだろう?」「まだベータだからかもしれませんが値段表が見当たらない感じです」
TwilioがSendGridを買収
つっつきボイス:「ちょうど先週のウォッチでTwilioのことをいろいろ教わったのでタイムリーだなと思って」「しかも今うちらもSendGrid使ってるし」「ちなみにSendGridには日本法人があるけどKDDIではなかったと思う」「構造計画研究所ですね↓」
SQL
データベース接続を効果的に管理するには(Postgres Weeklyより)
つっつきボイス:「これは普通にコネクションプールを作ろうみたいな話かな?」「たぶんそんな感じ」「お、Minimum viable checkoutsなんてのがある」
「コネクションプールって好き派と嫌い派がいますよね」「オレは嫌い」「そういえばMySQLはあまりコネクションプールって作らないですよね、PostgreSQLは割とやるけど」
「MySQLってパッケージ機能があまり強くないからいいんですけど、Oracleみたいにパッケージ機能が強いと(PostgreSQLはパッケージじゃなくてプラグインだけど同じかどうかよくわからない)、コネクションプールを張ったときにコンパイル結果がコネクションごとに乗っかるじゃないですか」「そうそう」「すると何が起きるかというと、ヘビーに使われているJava+Oracleのサイトでパッケージも積極的に使っているところで、コネクションプールを張った状態でパッケージを更新すると、パッケージで何か呼ぶたびにfailしてリコンパイルが走る、しかもそれがコネクションごとに起きるという現象です」「」「」「だから当時、コンパイルが失敗したというエラーメッセージを捕まえて再実行するという悲しいコードをよく書きましたもん」
「それは可哀想すぎる…コネクションプールを自分で管理するとかやりたくない〜」「とは言え、OracleとかPostgreSQLで大規模なことやるとコネクションプールを使わざるを得ないこともありますし」「あとTLS経由のコネクションって往復回数が多くなるからやりたくない: そういうときはコネクションプールをローカルに置ければ接続も早いしオーバーヘッドも小さくできるんじゃないかなと思うし」
「うほ、コネクションプールをさらに束ねるPgBouncerだって↓」「ここまでくるともうDBAの仕事」「大規模になって応答速度とかを改善しようとしたらDBAが管理していかないといけないでしょうね」「コネクションプールの状態を管理して、足りなかったら生成したりとか」
参考: Postgres Plus ユーザーサイト - FAQ — PgBouncerについて
PostgreSQLの正規表現
- 元記事: 9.7. パターンマッチ
# 同ドキュメントより
'abc' SIMILAR TO 'abc' true
'abc' SIMILAR TO 'a' false
'abc' SIMILAR TO '%(b|d)%' true
'abc' SIMILAR TO '(b|c)%' false
POSIX正規表現だそうです。
つっつきボイス:「PostgreSQLで正規表現を書けるというのをたまたま知ったので」「お?MySQLでもこういうの書けますよ」「やや、そうでしたか」「ポスグレはSIMILAR TO
で、たしかMySQLはREGEXP
、なお後者は演算子」「個人的にPOSIXなのが残念」
参考: MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.5.2 正規表現
「そういえばそんなのがあった気がするけど、自分はこういうの超遅くなりそうなんで基本使わないです」「DBMSならパラレルで処理できるからそんなには遅くならないと思いますけどね」「集約関数で使ったらさすがにヤバいだろうけど、普通にカラム名を評価するぐらいなら大丈夫だろうし、事と次第によってはLIKE
より速いこともあるんじゃないかなという気がしてきた」「文字数が確定する正規表現なら速くできそう」「+
とか*
を使わないのがポイントですね」「インデックス化もできますかね?」「さすがにそれは苦しいのでは」
CSS/HTML/フロントエンド/テスト
TLS 1.0/1.1無効化の動き
参考: Apple、Google、Microsoft、Mozillaが各社のブラウザでTLS 1.0/1.1のサポートを2020年前半に終了すると発表。 | AAPL Ch.
つっつきボイス:「さっきのELBSecurityPolicyは、このbabaさんが投下したこの記事の続きとしてSlackに貼ってたヤツですね」「ですです」「とは言え古いスマホもまだ残ってますけどね」
言語よろずの間
Zig言語とは
Zig言語ってなんか気になる。デザインの思想も共感できるし、作者のAndrew Kellyさんの気合いの入り方がよいというか、本気でCを置き換えるつもりでやってるぽいのがよい。
— Rui Ueyama (@rui314) October 14, 2018
- サイト: The Zig Programming Language
- リポジトリ: ziglang/zig
つっつきボイス:「究極だからZで始まる?」「C言語を置き換えるってw」「めちゃ鼻息荒いです」「D言語でやっとくれ」「そういえばあった!D言語って」
参考: D言語 - Wikipedia
PCRE2の仕様
- 元記事: PCRE2 specification
つっつきボイス:「これもたまたま見つけました」「PCREに2がある?!いつの間に」「つかPCREにちゃんと仕様があるっていうのが驚きPerlの正規表現ぐらいにしか思ってなかったけど」「実は2で初めて仕様を作ったりなんかして」
参考: Perl Compatible Regular Expressions - Wikipedia
その他言語
お菓子をくれないとmalloc(sizeof(32))するぞ!
— 加藤公一(はむかず) (@hamukazu) October 17, 2018
つっつきボイス:「」「」「このおかしみを知りたくて」「あ、malloc(sizeof(32))
の流れを知らなかったんですねついこの間はてブでも上がってたこの記事↓を受けたツイートです」「あ、そういうことか」「ちゃんとハロウィンらしく季節感出してるし」
参考: 侍エンジニア塾のC言語のサンプルがヤバすぎる。 - Qiita
「良い子のみんなはmalloc(sizeof(32))
しちゃダメだよ: 32
は数字じゃなくてシンボルとして解釈されるから」「32
だと期待どおりにならないのはわかる: 普通はsizeof(int)
とか書くヤツですよね」「数字でも書けるけどどれかのシンボルになっちゃう」「ついでに言うとC言語のsizeof
は演算子です: 関数じゃないからねっ」
参考: sizeof演算子
Nintendo Switchもlldに移行しようとしているんだ。知らなかった。このセッションは聞きに行かないと。 https://t.co/lPUsZHltZ0
— Rui Ueyama (@rui314) October 12, 2018
つっつきボイス:「Nintendo SwitchでLLD…ま使うよね動くんなら」
その他
オープンソースのISA「RISC-V」
つっつきボイス:「ISAってぱっと見で昔のISAバスかと思ったら、Instruction Set Architectureの方でした」「確かにISAって言いますね」「しかしRISCか」「今はLLVMがあれだけ流行ってるぐらいだし、中間言語で動くようになってしまうとエンドのCPUの種類ってあまり関係なくなってくるところがありますね」
「このRISC-Vは実装ではないようなので、つまりARMみたいなものか」「というと?」「ARMはCPUではなくて命令セットでありライセンスなんですね: だからARMのCPUというものはなくて、ARM社は命令セットを持っていてそのライセンスで収入を得てるということ」「知らなかった〜」
「このRISC-Vはオープンソースだから命令セットがオープンということか」「記事によると研究者がオープンな命令セットを長年欲していたらしいです」「確かにクローズドだと研究もままならないし」
番外
今から備えるか
各種業務への影響もでかそうな気が。
つっつきボイス:「そうそう、10連休で銀行系が青ざめてるらしいじゃないですか」「え、来年10連休?」「やべー」「やべー」「ガチのゴールデンウィークじゃないですか」「ガチすぎる」「厄介なのはたとえば給与支払日がここにかかっちゃうと労働基準法あたりの『月に1度支払うべし』とかに引っかかる可能性があることかな: あ、今は銀行が24時間365日で振込できるようになったからだいぶマシか」「ついこの間からでしたね」
参考: 9日から24時間365日「即時振込」のサービスが開始、それを可能にしたモアタイムシステムとは
今回は以上です。
バックナンバー(2018年度後半)
週刊Railsウォッチ(20181015)Rails初心者と一発でバレる書き方、次のVue.js構想、RubyのOpenStruct、Twilioほか
- 20181001 Railsアップグレード記事と各種支援ツール、CLI向けRubyワンライナー集、Rubyアプリをワンバイナリ化ほか
- 20180925 Rails大規模支払サービス開発のノウハウ、RailsのMySQLがutf8mb4に移行、Rpush gemほか
- 20180918 ビューテンプレート探索が高速化、mini_scheduler gem、レガシコントローラのリファクタリングほか
- 20180910 公開つっつき会#2、RSpecは何を参考にするか、イベントソーシング、marginalia gem、負荷テストツールvegetaほか
- 20180903 次世代アップローダーgem「Shrine」、RSpecをどこまでDRYに書くか、Rubyのmainオブジェクトの秘密、GitLabのCookie利用許諾機能はエライほか
- 20180827 Ruby Prize 2018募集開始、Interactor gemとReader Object、書籍『Real World HTTP』、Basecampのヒルチャート機能ほか
- 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など)です。