- Ruby / Rails関連
週刊Railsウォッチ(20190318-1/2前編)RailsとRubyでセキュリティ修正リリース、Rails 6でinsert_allやupsert_all追加、Webpacker 4登場ほか
こんにちは、hachi8833です。World Wide Web生誕30周年おめでとうございます。
ティム・バーナーズ・リー(左)とヴィントン・サーフ(右)のシャツがすごい。
それぞれ正面は「私はインターネットを創ってないよ」「私はウェブを創ってないよ」になってて、
背中側は「私はウェブを創ったんだ」「私はインターネットを創ったんだ」になってる。二つの違いを知ってるとわかる https://t.co/CJ6cFOesyH
— 堀 正岳 @ めほり (@mehori) March 12, 2019
つっつきボイス:「歴史だ⛩」「そうそう、もう30周年か」「↑このTシャツ素敵すぎ😍」「ふと見渡してみると、今日のつっつきに集まっているのは、お〜うまい具合に20代、30代、40代、50代とWebの歴史を4世代でひととおり網羅してる感😆」「カバレッジは完璧😆」
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
- 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください
⚓週刊Railsウォッチ「公開つっつき会」第9回開催のお知らせ
次回の公開つっつき会は4/4(木)です。皆さまのご応募をお待ちしております!🙇
⚓WWW生誕30周年よもやま話
今回のつっつきでは秘密のゲストがお見えになりました。
「では早速、ネットに最初に触ったのは?」「本格的に使ったのは大学に入った1997年かなー: あの頃はSun OSもあったし」「お〜なるほど!」「高校のときにWindows 3.1をインストールしましたね: フロッピー30枚ぐらいあったかな😆」「私はマカーだったせいでMS-DOSとWin3.1がすっぽり抜け落ちてて、Windows は95から初めて触りました」「自分の高校にはWindows 95入りのPCあった〜、ディスク20枚ぐらいで😆」
「20代だとフロッピーって見たことあります?なんて😆」「ありますっ😆」「お〜、じゃフォーマットしたことは?」「それは🤣」「🤣」「🤣」「フロッピー、家に普通にありましたし」「ファミコンディスクシステム↓とかじゃなくて?🤣」「店頭でディスク書き換えるヤツ🤣」「4世代カバーしていると面白い〜😆」
ファミリーコンピュータ ディスクシステム - Wikipedia
「50代だとやっぱりパソコン通信が最初みたいな?」「ですです: モデムでNiftyServeやってましたし、インターネットは某客先で監禁されてたときにそこの人がモノクロMacでMOSAIC(最初のWebブラウザ)を見せてくれたのが最初でした」「いつ頃?」「思い出した、オウム真理教の大事件の頃でした: あのニュースが大量に流れたせいでそこのサーバーがパンクしたんだった😇」「じゃ1994年か95年頃!」「歴史や...」「30代だけどWindows 95でインターネットに触れたので逆にパソコン通信を知らない😆」「20代の人も知らないよねパソコン通信?」「知らないですー😆」「知ってたらコワい😆」
もう使い道がありませんが、当時の英語圏のパソコン通信((AOLとかCompuServe↓とか)はひっくるめてonline servicesと呼ばれてました👴。当時は海外への電話代が高値だったので、英語圏とチャットするとか当時学生だった自分には到底無理でした。
⚓臨時ニュース3本
⚓1: Railsでセキュリティ修正リリース
- プレスリリース: Rails 4.2.11.1, 5.0.7.2, 5.1.6.2, 5.2.2.1, and 6.0.0.beta3 have been released! | Riding Rails
3つの修正についてはアップグレードの他に緊急用のパッチも提供されています。詳しくは必ずリンク先を参照してください。
後述しますが、つっつき後にもさらにRuby 2.5.5アップデートが来ててんてこ舞いでした😭。私も一応オレオレRailsアプリのRailsとRubyのアップグレードを完了しました。
つっつきボイス:「お、例のRailsセキュリティ修正」「Rubyもアップデート来てます」「3月半ばでbeta3ってことはスケジュール的に順調な方なのかな?」「4月末のRailsConf 2019がファイナル目標ですね↓」「ならbeta4とか5ぐらいまでいくかも😆」
参考: Timeline for the release of Rails 6.0 | Riding Rails
「Railsはだいたいリリースが後ろにずれ込むものなので😆」「もうみんなわかってるし☺️」「リリースを急いでバグ埋め込むよりその方がいいですし☺️」「RC2とかまで進んだところで微妙に機能修正が入ったりなんてこともありえるし😆」「リリース直後のRailsは基本人柱として使うぐらいの勢いで」
追記(2019/03/19)
ペパボさんの以下の記事で、より具体的にセキュリティ問題を追いかけています。
⚓CVE-2019-5418: render file:
の脆弱性
render file:
を使うとAction Viewで任意のファイルが露出する可能性。
class UserController < ApplicationController
def index
render file: "#{Rails.root}/some/file"
end
end
以下のようにすることで回避可能。file:
以外のrender
は影響を受けない。
render file: "#{Rails.root}/some/file", formats: [:html]
つっつきボイス:「render file:
ってそもそもあんまり使わないけど😆、ディレクトリトラバーサル的なことができちゃう脆弱性ってことかな?」「かなと思いました」「任意のファイルって時点でたしかにあかん😇けど、CVE見てみるとcontent disclosureと記述されてる」
「ところで脆弱性関連でcontent disclosureって用語あったかなー?」「あーどうでしたっけ?」「手元でググった感じではこのAction View以外に出てこないようなので、どことなく造語か何かの匂いがする🤔」「ここではおそらくディレクトリトラバーサル的な意味で使われてるっぽい🤔」
後で調べてみると、content disclosureは「情報の(公式な)開示」のような割と一般的かつポジティブな言葉として使われる方が多いようです。コンテンツお漏らしのようなネガティブなニュアンスだと、今思いつくのはleakとかexposureあたりでしょうか。
参考: disclosure content -- コーパスでの用例です
⚓CVE-2019-5419: Action ViewがDOS攻撃を受ける可能性
コントローラで以下のような暗黙のレンダリングが影響を受ける可能性がある。
class UserController < ApplicationController
def index
end
end
つっつきボイス:「説明用のサンプルコード↓がぱっと見ループしそう」「CPUが100%になるということだからDoS攻撃でしょうね: こんなコード書かないけどっ😆」「やってみたらすぐわかるでしょうし😆」
# CVE-2019-5419より
class UserController < ApplicationController
def index
render "index"
end
end
「でもこうやって↓書くとvulnerableじゃないのか!へ〜」「respond_to
がポイントなのかしら」「どっちにしろこんなの書かないし😆」
# CVE-2019-5419より
class UserController < ApplicationController
def index
respond_to |format|
format.html { render "index" }
end
end
end
vulnerable(脆弱な)はセキュリティ方面で多用されている堅苦しい言葉ですが、元々軍事や諜報で昔から使われてるような趣です。やはりラテン語が起源でした↓。自分の場合、一部の心理学だか文化人類学だかで「いじめられっ子オーラ」的なものをvulnerability(攻撃誘発性)と呼んでいたのを見たのが最初でした。
参考: vulnerable | Origin and meaning of vulnerable by Online Etymology Dictionary
⚓CVE-2019-5420: developmentモードで生成された秘密鍵が推測される可能性
秘密鍵が推測されるとリモートコード実行の可能性。Railsをアップグレードするか、config/environments/development.rbに以下を記述することで回避可能。
config.secret_key_base = SecureRandom.hex(64)
つっつきボイス:「まdevelopmentモードだし😆」「よほど下手打たない限りは😆」「上でSecureRandom
を使っているのは、(Rubyの素の)#rand
やRandom
を使うなという、セキュリティ方面でよく言われる話でしょうね」
参考: 2.2 セッションID -- Rails セキュリティガイド - Rails ガイド -- RailsのセッションIDはSecureRandom
で生成されているという解説
参考: What is so “secure” about SecureRandom? – Christian Blais – Medium
Rubyの素の#rand
やRandom
による乱数生成は素朴なので、外部から推測されてしまう可能性があります。お遊び以外では使わないようにしましょう⛔️。
参考: 乱数について CapmNetwork
PDF: デタラメさの効用と、1+1=0の世界
⚓臨時ニュース2: Rubyのセキュリティ修正がリリース
この間のRubyGemsの問題の修正の他にも細かな修正や変更が含まれています。その中にさらっとUNICODE 12対応が含まれていました。
# common.mk#L18
-UNICODE_VERSION = 11.0.0
-UNICODE_EMOJI_VERSION = 11.0
+UNICODE_VERSION = 12.0.0
+UNICODE_EMOJI_VERSION = 12.0
UNICODE_BETA = NO
つっつきボイス:「Ruby 2.6が早くも2.6.2」「早いな〜」「内容はこの間のRubyGems修正を正式に導入した感じですね」「おーUnicode 12も入ってるし😍」「これでRubyで使える絵文字がまた増える😋」
「こういうのはRubyが一番熱心ですよね」「日本人が多い言語だと対応が進みやすい傾向があるかも、なんて😆」
⚓臨時ニュース3: Ruby 2.5.5がリリース
- プレスリリース: Ruby 2.5.5 リリース
- commit: Comparing v2_5_4...v2_5_5 · ruby/ruby
このリリースにはマルチスレッドとマルチプロセス(Process.fork)を利用したアプリケーション(例: puma)でデッドロックが発生することがある不具合の修正が含まれています。
同リリースノートより
⚓Rails: 先週の改修(Rails公式ニュースより)
リリースが近いせいか、以下のようなドキュメントの更新が中心のようです。
つっつきボイス:「小さな修正ですが、painfullyという文言は余計だろうということだそうです」「あ〜なるほど!」
修正前: Setting this up is painfully simple.
修正後: Setting this up is simple.
元をあえて日本語で表すと「嫌になるほどシンプル」みたいな感じでしょうか。
⚓Zeitwerkにカスタムinflectorを追加
- PR: Allow autoloader inflectors to be swaped out by casperisfine · Pull Request #35533 · rails/rails
# activesupport/lib/active_support/dependencies/zeitwerk_integration.rb#L58
def setup_autoloaders
- Rails.autoloaders.each do |autoloader|
- autoloader.inflector = Inflector
- end
Dependencies.autoload_paths.each do |autoload_path|
# Zeitwerk only accepts existing directories in `push_dir` to
# prevent misconfigurations.
next unless File.directory?(autoload_path)
if autoload_once?(autoload_path)
Rails.autoloaders.once.push_dir(autoload_path)
else
Rails.autoloaders.main.push_dir(autoload_path)
end
end
Rails.autoloaders.each(&:setup)
end
つっつきボイス:「Zeitwerkの最適化っぽい: 上の部分が要らないので削除したというか」「オートローダーが変わるとやっぱりいろいろ起きるんだな」
⚓SafeBufferのスライスassingmentをサポート
# activesupport/lib/active_support/core_ext/string/output_safety.rb#L202
- def []=(index, value)
- super(index, html_escape_interpolated_argument(value))
+ def []=(*args)
+ if args.count == 3
+ super(args[0], args[1], html_escape_interpolated_argument(args[2]))
+ else
+ super(args[0], html_escape_interpolated_argument(args[1]))
+ end
end
つっつきボイス:「if args.count == 3
で引数が3つの場合にSafeBuffer
が部分文字列を出すように変わったのか、なるほど」「スライスってそういう意味だったんですね!」「文字列のスライスといえば、だいたい部分文字列の切り出しとか分割ですね🧐」
⚓add_pg_decoderのバグを修正
# activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L242
def initialize(connection, logger, connection_parameters, config)
super(connection, logger, config)
@connection_parameters = connection_parameters
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
@local_tz = nil
- @default_timezone = nil
- 11:08stamp_decoder = nil
@max_identifier_length = nil
configure_connection
add_pg_encoders
add_pg_decoders
@type_map = Type::HashLookupTypeMap.new
initialize_type_map
@local_tz = execute("SHOW TIME ZONE", "SCHEMA").first["TimeZone"]
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
end
...
def add_pg_decoders
+ @default_timezone = nil
+ @timestamp_decoder = nil
+
古くなった
@default_timezone
がdisconnect!
後のreconnect!
でエラーになることがあったのを修正。
同コミットより大意
つっつきボイス:「いかにもぽすぐれ関連の修正: やっぱりkamipoさん?」「ですです🎯」「この謎バグよく見つけたな〜って思うし🤓: さすが『kamipoさんはすごい人』とテンプレにまでなってる人」
本当にありました↓。
ニューラルの方が日本人ぽい #kamipoさんはすごい人 pic.twitter.com/qlJWnOwtEr
— Tatsuro Hisamori (@myfinder) November 16, 2016
⚓新機能: insert_many系メソッドが追加
以下の記事で知りました。
# 同PRより
# Insert multiple records, performing an upsert when records have duplicate ISBNs
# ('Eloquent Ruby' will overwrite 'Rework' because its ISBN is duplicate)
Book.upsert_all([
{ title: 'Rework', author: 'David', isbn: '1' },
{ title: 'Eloquent Ruby', author: 'Russ', isbn: '1' }
],
unique_by: { columns: %w[ isbn ] })
以下が追加されました。
insert_all
insert_all!
upsert_all
つっつきボイス:「おぉ、これは欲しい人いそう❤️」「そういえばこの間activerecord-importでいろいろやってたのを見かけたので、もしかするとそのときに欲しかったんじゃないかなーって😆」
- リポジトリ: zdennis/activerecord-import
「insert_all
もあるし」「upsert_all
もあると確かにうれしい😋」「upsert_all
がRailsのレイヤでサポートされてるとありがたい🙏」
「UPSERTって、UPDATEとINSERTの合わせ技でしたっけ」「なければINSERT、あればUPDATEしてくれるヤツ💪」「知らない世界...🥺」「最初は『へー、そういうのをUPSERTって言うんだ〜』と思ってましたが、あちこちで使われるようになってきたのでそろそろ一般化したと思ってよさそう」
参考: PostgreSQL UPSERT の機能と使い方 - ベストプラクティス| Alibaba Cloud ドキュメントセンター
「そういえばMySQLだとREPLACE文で同じことができる↓」「以前のPostgreSQLだとINSERTとかでWITHを使う↓みたいな感じで、RDBMSによってとにかくやり方がまちまち😅」
参考: MySQLでバルクアップデートを実現するには - Qiita
参考: 7.8. WITH問い合わせ(共通テーブル式) -- PostgreSQL 10.5
「UPSERT的な処理は業務アプリで必ずといっていいほど使うのでうれしい機能🥰: findして見つかったらそれで更新かけるとか死ぬほど書いたし🤓」
⚓番外: Railsのデフォルトログレベルは4.2からdebug
# guides/source/debugging_rails_applications.md#L141
This is useful when you want to log under development or staging, but you don't want to flood your production log with unnecessary information.
-TIP: The default Rails log level is `info` in production mode and `debug` in development and test mode.
+TIP: The default Rails log level is `debug` in all environments.
つっつきボイス:「これは今日のチームミーティングで軽く話題になったやつですね」「ですです: Railsのデフォルトのproductionログレベルって何だっけというお話でしたね: あの後調べたらy-yagiさんが4.2でRailsガイドを更新してくれてました」「productionのログレベルはinfo
だと思ってたらいつの間にかdebug
だったという😆」
「実は日本語版Railsガイドでは少し前までこの部分が更新されてなかったんですが、diffベースで差分翻訳する体制になる前の名残だったので追いきれてなかったという😅: それをここ半年で5.2キャッチアップ翻訳をかけたときに全ページを目で照合してやっと更新を拾い上げました↓」
⚓Rails
⚓Webpacker 4.0がついにリリース(Ruby Weeklyより)
よく見ると、もう4.0.2なんですね。
つっつきボイス:「本家Webpackとのバージョン齟齬がつらかったWebpackerが、やっと4.0になりました😂」「Webpackが4.0になってからWebpackerが4.0になるまでどのぐらい空いたんだろか😆」「今Webpackerのバージョンを上げるといろいろ変わりそうでコワい😨」
「今さらですけど、WebpackerがRails用で、Webpackは汎用みたいな位置付けでよかったんでしたっけ?」「ですね: Webpackerはgemで、WebpackはnpmとかでインストールするJavaScriptのライブラリ」
- サイト: webpack
調べてみると、Webpack 4.0.0リリースは2018年2月↓なのでほぼ1年かかりましたね。そしていつの間にかWebpackは5.0.0のアルファ版がだいぶ進んでいます。
参考: Release v4.0.0 · webpack/webpack
参考: Release v5.0.0-alpha.11 · webpack/webpack
⚓monday.com: タスク管理サービス
RailsとBootstrap 4感出てますね。
参考: 【各社員の業務を見える化】シンプルで使いやすいタスク管理ツール「monday.com」
つっつきボイス:「Chromeのwappalyzer拡張によると、monday.comはどうやらRailsでできてるっぽいのでここに置いてみました: タスクの更新や移動がやりやすくて、BacklogやTrelloよりよさげと言ってたので」「この種のサービスはそれこそ無限にありますから😆」
「タスクやプロジェクトの管理サービスでRailsで書かれているといえば、考えてみたらほら、アレがあるじゃないですか😎」「アレ?」「Basecamp」「あぁ!そういえば😳」「RailsユーザーならDHHのお膝元のコレでしょう🤣」「みんな使えと🤣」「名前しか聞いたことなかった...」「Basecampがどういうサービスなのか今までまるで気にしてなかった😅」
今更のようにサイトをちょっとだけ触ってみると、表示や応答がめちゃ高速ですね。
「改めて説明すると、BasecampはRailsの作者であるDHH↓がいる会社です」「Railsは見ようによっては、DHHがBasecampで欲しい機能をRailsに入れているとも言える😆」「なので、Basecampを見ればRailsにどういう機能があるかがよっくわかる🤣」「🤣」
Finally released my @thestrongweb episode with @dhh It's an inspiring and delightful conversation with someone I truly admire. https://t.co/qdR2i50x40 pic.twitter.com/9reAwEQxED
— Erick Arbé (@erickarbe) March 14, 2019
DHHはレーシングマニアとしても有名です(@dhhracing)。
「Basecamp、日本で使ってる人いるんでしょうか?」「見かけないな〜」「考えてみたらRailsの本家本元なのに、Railsフレームワークと比べてBasecampのサービスって日本だとあまり見かけない感じですね」「英語圏ならきっとプレゼンスそれなりにありそうですけど」「ちょっと試してみたいですね」
(featuresを見ながら)「そうそうBasecampのサービスにはチャット機能なんかも統合されてるんですよ: 自分はSlackにずっぽりだからチャットあまり変えたくないけど」「こうしてみると、Railsらしいモノリシックな作りになってるなと思いますね」
⚓execute_sql: RailsコンソールでSQLを直接実行(RubyFlowより)
- リポジトリ: igorkasyanchuk/execute_sql
前にウォッチで紹介したrails_dbと同じ作者です。
- リポジトリ: igorkasyanchuk/rails_db
つっつきボイス:「pgAdminを立ち上げるのが面倒なときに使うのかな?と思って」「実行だけならActiveRecord::Base
にあるexecute
でできますけどね😎」「それ知らなかった😅」
参考: ActiveRecordを使ってRails consoleからテーブル一覧がほしい - Qiita
「お、でもこのexecute_sqlは結果セットを直接制御できるのか↓: それならわかる😋」「というと?」「ActiveRecord::Base
のexecute
で取る場合は結果セットを自分でさらに展開しないといけないんですが、このgemは図でやってるみたいに:single
ってやれば1行だけ取るみたいなことができると」「なるほど〜」「ま、自分は要らんけど🤣」「🤣」「🤣」
「rails_dbは、MySQLAdmin的なGUIのDB管理ツールをRailsで作ったものですね」
「やや、Windowsノートがまたフリーズ❄️: 今日で何回目だ😇」「でかいモニタにつなぐと起きやすいんでしょうか」「ウォッチをつっつき中に2回というのはなかなかキツイわ〜😭」
⚓RailsのService Objectとactive_interaction gem
つっつきボイス:「TechRacho記事を2本も引用いただいてたので🎉」「古い記事もありますね😆」「もちっと新しいのも一応😆」「記事ではService層というかService Objectとは何ぞやを追求してます」「もう『おまえがService Objectだと思ったものがService Objectだっっっ』でいいんじゃね?🤣」「🤣」「🤣」「ちょうど今日BPSの社内勉強会でもPoEAA本↓の2周目を始めたところで、そこでもいずれこの辺のパターンが出てきます」
「さっきの記事でもちょうどService層を『Commandパターン』にするか『Facadeパターン』にするかということをやってますね」「あー、記事の『全部のせServiceクラス』↓ってFacadeのことなのか」「自分はそう理解してます🤓」
同記事より
「そしてService層では主にCommandパターンとFacadeパターンという2種類の実装方法が広まってて、そのあたりで宗教戦争が起きやすい⚔️」
「ところでまとめの最後にlib/に置くみたいなことが書かれてますけど、lib/に置くときってどんなときでしょう?」「Railsがなくても使えるような汎用的なものをlib/に置くべきでしょうね」「なるほど!」「自分の感覚では、たとえばActive Recordにアクセスするようなコードはlib/には置かない感じですね☺️」
また、同記事でactive_interactionというgemが紹介されていました。
「もしかするとこういうgemっていっぱいあるのかなと思いつつ」「これは.run
で実行するタイプのようなので、Commandパターンを支援するgemなんでしょうね☺️」「READMEが意外に長い🐍」「フレームワークっぽい雰囲気だから長いのかも」「何となくだけど、どことなくオブジェクト指向の過激派っぽい匂いが😆」「すべてはオブジェクトみたいな😆」
# 同リポジトリより
Square.run!(x: 'two point one')
# ActiveInteraction::InvalidInteractionError: X is not a valid float
Square.run!(x: 2.1)
# => 4.41
「先週のBPS勉強会で言ってた『後から引っぺがすのが大変なgem』っぽくもありますね😆」「これで幸せになれるんでしょうか😅」「😆」「思ったんですが、完全にオブジェクト指向に寄せたいならむしろRubyよりJavaとかを使う方がいいのかも🤔: キレイにカプセル化できるし速いし」「どうなんだろう...記法の問題でもないような気もしますが😆」「Rubyでカジュアルにオープンクラスできるのは結構エグい😆」「😆」
「Rubyの場合クラスをどこから開かれるかわからないので、規模が大きくなってくるとつらくなってくる気がするんですけどどう思います?」「いやーRubyをそこまでズブズブに使ったことがまだなくって😅」「Rubyはその辺ほんと自由ですよ🤣」「🤣」「ヤバい書き方をしようと思えばもういくらでもできるし」
⚓Railsコードのリファクタリング
つっつきボイス:「永和システムマネジメントさんの記事で、例の本を読み込んで解説しているので」「お、Martin Fowlerの新しい版の『Refactoring』だ」「去年発売されてましたね」「日本語訳ってあります?」「出たばっかりだしまだ先でしょうね」
If you have a subscription to the Safari online books service, you can access a rough cut of the 2nd edition of refactoringhttps://t.co/JO6AF4O1jO
— Martin Fowler (@martinfowler) August 29, 2018
参考: リファクタリング 第2版が素晴らしい - koicの日記
「第2版ではJavaScriptも扱ってるって言ってましたね」「前はJavaとC#でしたっけ」「第2版、買った気がするんだけどまだ読んでない😇」「😆」「ゴツそうな内容ですね」「まあだいたい同じようなこと書いてるだろうし、そんなに読むのは大変じゃないと思いますが」
「実際Martin Fowlerの本ってとても読みやすいのでいいと思いますよ」「そうかも」「コンピューターサイエンスをやってきた人らしい文章」「そういえば勉強会でもさっきのPoEAAには無駄な記述がないって言ってましたね」「読んでるうちに彼の技術英語の言い回しがだんだん身体に入ってきて斜め読みが効くようになってくるし📖」「脳が彼の英語に最適化されるというか🧠」
⚓Railsの素朴な疑問
個人的に、joinsはキャッシュしないから、同じ処理を何度も繰り返すのであればincludesとか、eager_load使えば早くなるのではと思っているけど、そうはならないから違うのか。
つっつきボイス:「社内の日報で見かけたんですが、これだけだと何とも言えない感じでしょうか?」「あーなるほど、そこで言ってる『joinsはキャッシュしない』というのはおそらくRailsレベルでキャッシュしないということなんだろうけど、クエリキャッシュはあると思うので、少なくとも同じクエリを投げればクエリキャッシュは効くんじゃないかなー?🤔」「おー」「eager_loadは、使えば速くなるというようなものではないし: includesは結構速いけど」
「RailsのJOINってたしかINNER JOINでよかったっけ?」「そのはずです」「クエリ次第ではJOINも速いことがあるんじゃないかなという気がするんだけど🤔、この場ではこのぐらいが限度かな」「急に振っちゃってすみません🙇」
⚓Ruby
⚓ヤバいRubyコード(Ruby Weeklyより)
つっつきボイス:「Ryan BiggさんはDHHとRailsの設計方針でやりあったりしてた方ですね↓」「邪悪なRubyというか」
「おー記事は早速+
メソッドをオーバーライドしてるぞっ😆」「*
も単項演算子の-
も片っ端からオーバーライドしてるし」「その辺は元からできる機能ではあるけど」「こういうのを読み込んで既存のRubyの振る舞いを置き換えたりみたいな😆」
# 同記事より
class Integer
alias_method :old_multiply, :*
def *(num)
m = method(:old_multiply).unbind
m.bind(3).(num / self)
end
end
「JavaScript風のsortですって↓」「こういうバイナリをひっそり紛れ込ませるとアツい🧨」
[-2, -1, 0, 1, 2].sort()
//=> [-1, -2, 0, 1, 2]
module JSSort
def self.included(base)
base.alias_method :old_sort, :sort
end
def sort
self.map(&:to_s).old_sort.map(&:to_i)
end
end
Array.include(JSSort)
「トリプルイコール===
もオーバーライドできるのかー」「へ〜」
class Array
def ===(_)
true
end
end
「これはあの文字列をfreezeさせるショートハンドの-
をオーバーライドしてるし↓」「この文字列freezeの-
記号とunfreeze用の+
って最近のRubyにあるんですけど、ご存じでした?」「いえ〜初めて知りました🥺」「Rubyのfreeze用の-
って、もうちょっとマシな記号ってなかったの?って思っちゃいますよね」「.freeze
だと長くなるしショートハンドが欲しいのはわかるんだけど😅」「初めて見たときにも『はぁ?』と思ったし😆」「記事で日本語の十
(漢数字)をメソッド名に使ってるし😆」
>> a = -"string"
=> "string"
>> a.frozen?
=> true
class Array
def -@
clear
end
end
a.clear
参考: 文字列をfreezeさせるいくつかの方法 - Qiita
「これはもうイタズラ用ですね」「記事の冒頭でもproductionでは絶対やるなと書いてますし」「まあ想像のつく範囲のイタズラかなと☺️」「中学2年生におすすめ✏️」「やられたらびっくりするのは間違いない🎈」
⚓その他Ruby
フクオカRuby大賞で #YassLab 社の取り組み『#Railsチュートリアル×#反転学習』が #AWS 賞を受賞しました! 😻🏆✨https://t.co/nl94qetGQt
引き続き様々な企業やコミュニティとの関わりを大切にしながら、事業としても継続できるカタチを実現していきます! 🤝✨
スライド: https://t.co/f6EA09MIAI pic.twitter.com/VsumKmphWc
— YassLab 株式会社 🏝 (@YassLab) March 14, 2019
つっつきボイス:「AWS賞ですって」「普通にAWSがスポンサーをやってる賞でしょうね☺️」
3/13新刊:ISBN978-4-295-00590-2 インプレス 『スラスラ読める Rubyふりがなプログラミング』 リブロワークス 著 高橋征義 監修 30冊入荷 pic.twitter.com/DXsGPrXHNh
— ジュンク堂書店池袋本店 PC書担当 (@junkudo_ike_pc) March 13, 2019
つっつきボイス:「高橋会長が出した本で、コードにひとつひとつ解説という意味でのふりがなを振ってるということみたいです」「Pythonでも同じような趣旨でふりがなプログラミングの本が出てたから、その流れでRubyでも本を出したのかも」「そっちは知りませんでした😅」
「ふりがなプログラミング、特に教育方面ではあっていいと思う👍」「ですね」「特に今みたいにプログラミング教育の義務化みたいなことになってくると、こういう本って重要になってくるし」「その前に国語の勉強しようねって言いたいけどっ😆」「😆」「あ〜でも本当にそう😆」「この本でプログラミングを理解できるのって、国語の成績がいい子に限られるんじゃないかって思ったし」「言語能力ってそういうことですよね😆」
「国語の成績はいいんだけどプログラミングがどうもわからないという子どもを助けるという意味では、この本が役に立つかも」「『プログラミングって数学ができないとだめなんでしょ?』みたいな苦手意識のある子どもとかに」「1クラスで数人でもこの本で救われたら価値は絶対あるし: 全員は無理だと思うけど」「たしかに〜」
「話逸れちゃうんですけど、最初本のタイトルを見たときにこのRubyってもしかして『ルビを振る』のルビのこと?って考えちゃいました🤣」「なっはっは🤣」「とっても紛らわしいんですけど、どっちも英語のスペルは同じ"ruby"なんですよ😭」「本の帯にはRailsって書いてるし」「まさかRailsまでカバーしてるとか?😆」
参考: ルビ - Wikipedia
「ツイートの写真の左、よく見るとjnchitoさんの直筆ポップじゃん!」「あ〜全然見落としてた!😆」「マニアックすぎる😆」「さすがジュンク堂池袋本店」
チェリー本の新しいAmazonレビューをいただきました。どうもありがとうございます!
>本書のはじめのほうにまつもとゆきひろさんのコメントで「ああ、人の気持ちがわかるとはこういうことなんだなあ」とありました。この本を読み終わった後その言葉の意味がよくわかりました。https://t.co/yx9qdy29HZ— Junichi Ito (伊藤淳一) (@jnchito) April 24, 2018
「ジュンク堂池袋本店といえば、Rubyのコアコミッターが割とお互い近いところに住んでるという話が以下の翻訳記事にあるんですが、どうやら池袋につながる沿線らしくって、一説によると彼らが本気出したら池袋本店の技術書コーナーを1日で空っぽにできるとか😆」「😆」「空っぽにするほど買ってみたい〜」
⚓Ruby trunkより
⚓Ruby 2.6.0で禁止されたシンボルキーと非シンボルキーの混在を2.6.1で再度許した
# test/-ext-/test_scan_args.rb#L99
def test_opt_hash
assert_equal([0, nil, nil], Bug::ScanArgs.opt_hash())
assert_equal([1, "a", nil], Bug::ScanArgs.opt_hash("a"))
assert_equal([0, nil, {b: 1}], Bug::ScanArgs.opt_hash(b: 1))
assert_equal([1, "a", {b: 1}], Bug::ScanArgs.opt_hash("a", b: 1))
assert_raise(ArgumentError) {Bug::ScanArgs.opt_hash("a", "b")}
- assert_raise(ArgumentError) {Bug::ScanArgs.opt_hash("a"=>0, b: 1)}
+ assert_equal([1, {"a"=>0}, {b: 1}], Bug::ScanArgs.opt_hash("a"=>0, b: 1))
end
以下は確かに2.6.2では動くようになっていました。
# #15658より
def foo(opt=nil, **kw)
p opt, kw
end
foo("str" => 42, :sym => 42)
#=> 2.5.3: {"str"=>42}, {:sym=>42}
#=> 2.6.0: non-symbol key in keyword arguments: "str" (ArgumentError)
つっつきボイス:「あ〜これね〜😅」「シンボルキーと非シンボルキーの混在が2.6.0で禁止されて、また戻ってたことに気づいてませんでした💦」「これ変えられちゃったら困るヤツですよね?」「結構困る😇」「実際混在はずっと行われてたし、禁止されたらライブラリがエラーになっちゃうし😢」「とはいえ、Railsでこういう混在した書き方↓されたら後ろから撃ちたくなるけどっ😆」「😆」「😆」
foo("str" => 42, :sym => 42)
そして上の一連の動きは、#14183の「本物のキーワード引数」の議論と関連しているようです。#14183はまだ閉じていませんので、今後どうなるかですね。
k:1
のようなハッシュ引数が{}
で囲まれていない場合はキーワード引数となって**kw
に渡され、{}
で囲まれている場合は末尾の引数としてkw = {}
に渡される、みたいな流れになっているようです。たしかにこれなら明示的に分けられそうですね。
# #14183より
def foo(**kw); p kw; end
def bar(kw = {}); p kw; end
h = {:k => 1}
# base (non-braced) hash arguments passed as keywords
foo(k: 1) #=> {:k=>1} in 2.X and 3.0
foo(:k => 1) #=> {:k=>1} in 2.X and 3.0
foo(**h) #=> {:k=>1} in 2.X and 3.0
bar(k: 1) #=> {:k=>1} in 2.X, ArgumentError in 3.0
bar(:k => 1) #=> {:k=>1} in 2.X, ArgumentError in 3.0
bar(**h) #=> {:k=>1} in 2.X, ArgumentError in 3.0
# braced hash arguments are passed as a last argument
foo({ k: 1 }) #=> {:k=>1} in 2.X, ArgumentError in 3.0
foo({ :k => 1 }) #=> {:k=>1} in 2.X, ArgumentError in 3.0
foo(h) #=> {:k=>1} in 2.X, ArgumentError in 3.0
bar({ k: 1 }) #=> {:k=>1} in 2.X and 3.0
bar({ :k => 1 }) #=> {:k=>1} in 2.X and 3.0
bar(h) #=> {:k=>1} in 2.X and 3.0
「今回の動きは、どうやらRubyの目下の悩みである『**
とキーワード引数をどうする問題』↓と関連してるみたいで、{}
で囲むかどうかで挙動を分けるというアイデアが出されて今審議中のようです」「これはとてもわかる: **
周りの挙動ってマジでわからなくなるし😭」「キーワード引数が期待と違うパラメータに吸い込まれるとコワいです〜🌪」
「この辺のパラメータ渡し問題で一番典型的なのは、Active Supportに昔からあるような古参のメソッドたちで、あれはどうしてそれで動くのか今もってわからない🤪」「form_for
あたりとか?」「とかですね、form_with
↓になって随分よくなったけど、それでもちょっと心配😅」
「この問題が難しいのは、どう修正してもbreaking changesが避けられないところでしょうね」「といって放置するわけにもいかず、苦渋の決断を迫られるという」「トロッコ問題的に『n人までなら殺すのもやむなし』みたいな😆」
今回は以上です。
おたより発掘
https://t.co/aC5qzKL8XP
vulnerable という単語を最初に知ったのはコントラクトブリッジだな。
点数計算がハイリスクハイリターンな状態のことをバル(バルネラブル)と呼ぶ。ラバー(2ゲーム先取)のルールで1ゲーム先行した状態など。— さく (@sakuro) March 18, 2019
すごい。僕もまったく気づいていなかったww > ツイートの写真の左、よく見るとjnchitoさんの直筆ポップじゃん!
週刊Railsウォッチ(20190318-1/2前編)RailsとRubyでセキュリティ修正リリース、Rails 6でinsert_allやupsert_all追加、Webpacker 4登場ほか https://t.co/WMo7Fh83MW— Junichi Ito (伊藤淳一) (@jnchito) March 18, 2019
バックナンバー(2019年度第1四半期)
週刊Railsウォッチ(20190305-2/2後編)PostgreSQL強者から見たMySQL、SEO良記事、分散アルゴリズムChordほか
- 20190304-1/2:前編 Rails 6.0.0 beta2リリース、Ruby 2.7の新しい記法、各種自動レビューツール、ULIDとはほか
- 20190212 EnvoyとIstioに大注目、SQLQLとは、buildkite.comのCI、さよならItanium、PWA vs Androidほか
- 20190204 あってうれしい40のgem、Ruby 2.6.1セキュリティリリース、Hanami v2.0.0.alpha1リリースほか
- 20190128 Rails 6のオートローダーがZeitwerkに置き換わる?Rails 6はRuby 2.5が必須、最近のSQLiteほか
- 20190121 Rails 6.0.0 beta1リリース、Railsは2019年も「あり」か、Jetsでサーバーレス、ES2018の新機能、RSpecの心ほか
- 20190115 Rubyの<=でクラス同士を比較、Rubyの記号の読み方いろいろ、Ruby C API解説サイトほか
- 20190107 Railsのパフォーマンス改善Tips集、Rubyの
&:シンボル
ほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSなど)です。