- 開発
週刊Railsウォッチ(20190924-1/2前編)Railsのconcernsを考える、Netflixのヘキサゴナルアーキテクチャ、Railsのアロケーション削減ほか
こんにちは、hachi8833です。RailsチュートリアルのRails 6対応翻訳をひとまず終えました🍵。お目見えはもう少し先になると思います。
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
- 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください
⚓週刊Railsウォッチ「公開つっつき会」第15回のお知らせ(無料)
第15回目公開つっつき会は、10月5日(木)19:30〜にBPS会議スペースにて開催されます。Railsウォッチのコンテンツにいち早く触れるチャンスです!皆さまのお気軽なご参加をお待ちしております🙇。
⚓Rails: 先週の改修(Rails公式ニュースより)
6-0-stableブランチが少し静かになったようなので、6.xマイルストーンなども覗いてみました。
つっつきボイス:「お、6.xなんてマイルストーンがあるし」「どう使い分けてるのかな?🤔」「6.1.0にも乗らないissueが6.xに乗るのかも」「新機能は6.xに入れるとか?」「そのうちやるToDo的なものも6.xに入ってるっぽいです😆」
⚓(6.0)render :text
とrender :nothing
オプションは削除完了と5.1アップグレードガイドに追記
ビューで
render :text
を使っている場合は動かなくなる。MIMEタイプをtext/plain
にしてテキストをレンダリングする新しいメソッドとしては今後render :plain
を使うこと。
同様にrender :nothing
も削除されるので、ヘッダーのみを含むレスポンスを送信するには今後head
メソッドを使うこと。たとえばhead :ok
とするとbodyなしでレスポンス200を送信する。
同PRより大意
つっつきボイス:「render :text
ってもう動かなくなってたか😳」「ついに消えた」「そのことを忘れて古い方を使っちゃったりしますし😅」「今後はhead
を使ってくれだそうです」「render :nothing
ってヘッダーだけ返してたのね」「renderしてないのにrender
を使うよりはhead
の方がいいかも🤣」「たしかに🤣」
参考: render
-- ActionController::Renderer
参考: head
-- ActionDispatch::Integration::RequestHelpers
なお、つっつき後にRailsガイドにも反映しました(#890)
⚓はみ出し
「ところでrender :plain
って、毎回plainの綴りで一瞬迷うんですよね😆」「そうそう、plainだっけplaneだっけみたいな😆」「調べるの面倒だし、どうせデバッグだからってついrender :text
にしてみちゃったり😆」「plainとplaneって発音違ってたかな...?🤔」
発音は同じでした↓。
参考: Plain vs. Plane: How to Choose the Right Word
そういえば映画『マイ・フェア・レディ』で発音の特訓に使われた『スペインの雨は主に平野に降る』という早口言葉もありました。
参考: マイ・フェア・レディ (映画) - Wikipedia
⚓(master)マイグレーションでDatabaseConfig
オブジェクトを直接使うようにした
コネクション設定については、あちこちで直接引き回されている
Hash
ではなく、DatabaseConfig
をもっと積極的に使おうという方針に移行しつつある。
ここではDatabaseTasks
とdatabases.rake
でデータベース設定オブジェクトを使うように変えている。以下はメモ。
DatabaseTasks
のcharset_current
やcollation_current
のpublicメソッドのテストがなかったのでそれも足してある。schema_up_to_date?
の引数のうち重複してて紛らわしい部分を非推奨化した。うち1つ(environment
)は以前使われていなかったが、現在はspec_name
でdb_config (DatatabaseConfig)
オブジェクトを直接取れてしまう。
同PRより大意
# activerecord/lib/active_record/tasks/database_tasks.rb#L342
- def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary")
+ def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = nil, spec_name = nil)
+ db_config = resolve_configuration(configuration)
+
+ if environment || spec_name
+ ActiveSupport::Deprecation.warn("`environment` and `spec_name` will be removed as parameters in 6.2.0, you may now pass an ActiveRecord::DatabaseConfigurations::DatabaseConfig as `configuration` instead.")
+ end
+
+ spec_name ||= db_config.spec_name
+
file ||= dump_filename(spec_name, format)
return true unless File.exist?(file)
- ActiveRecord::Base.establish_connection(configuration)
+ ActiveRecord::Base.establish_connection(db_config)
return false unless ActiveRecord::InternalMetadata.table_exists?
ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
end
つっつきボイス:「冗長な書き方を整理する感じでしょうか?」「なるほど、わざわざ変換しなくても元オブジェクトを渡せばいいんじゃね?って話か」「わざわざhashにしなくてもええと」「もしかするとテストのときはhashの方がやりやすかったみたいなことが当時あったのかもしれませんけど☺️」「割と修正範囲広いな〜」「必須引数を増やすとついこうなりがちですよね😆」
「ところで元のコードはどういう経緯でhashを使う設計にしたんだろう?🤔」「永続化したかったとか?🤔」
⚓(master)ActiveRecord::DatabaseConfigurations
のto_h
とto_legacy_hash
を非推奨化
# activerecord/lib/active_record/database_configurations.rb#L81
def to_h
- configs = configurations.reverse.inject({}) do |memo, db_config|
- memo.merge(db_config.to_legacy_hash)
+ configurations.inject({}) do |memo, db_config|
+ memo.merge(db_config.env_name => db_config.configuration_hash.stringify_keys)
end
-
- Hash[configs.to_a.reverse]
end
+ deprecate to_h: "You can use `ActiveRecord::Base.configurations.configs_for(env_name: 'env', spec_name: 'primary').configuration_hash` to get the configuration hashes."
つっつきボイス:「なぬ、Active Recordのto_h
とto_legacy_hash
を非推奨化?」「あ、タイトルのドラフトはしょりすぎでした😅」『ActiveRecord::DatabaseConfigurations
の』が正しい😎」
「to_legacy_hash
↓ワラタ😆」「移行パスのためっぽい匂いを感じる🌷」
# activerecord/lib/active_record/database_configurations/database_config.rb#L41
- def to_legacy_hash
- { env_name => configuration_hash.stringify_keys }
- end
「そういえばARにto_h
ってありましたっけ?手元でuser.to_h
とかするとそんなのねえって言われる😭」「あ、ハッシュはattributes
で取れるんだったか😆」
参考: attributes
-- ActiveRecord::AttributeMethods
参考: RailsでActiveRecordのデータをhashにする方法 - Qiita
⚓(master)6.0でincludesとjoinsを併用するとjoinしたクエリの順序が変わる問題を修正
# activerecord/lib/active_record/associations/join_dependency.rb#L73
+ def base_klass
+ join_root.base_klass
+ end
+
# activerecord/lib/active_record/relation/query_methods.rb#L1103
def build_joins(manager, joins, aliases)
buckets = Hash.new { |h, k| h[k] = [] }
unless left_outer_joins_values.empty?
left_joins = valid_association_list(left_outer_joins_values.flatten)
buckets[:stashed_join] << construct_join_dependency(left_joins, Arel::Nodes::OuterJoin)
end
+ if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
+ buckets[:stashed_join] << joins.pop if joins.last.base_klass == klass
+ end
+
joins.map! do |join|
if join.is_a?(String)
table.create_string_join(Arel.sql(join.strip)) unless join.blank?
else
join
end
end.compact_blank!.uniq!
while joins.first.is_a?(Arel::Nodes::Join)
join_node = joins.shift
if join_node.is_a?(Arel::Nodes::StringJoin) && !buckets[:stashed_join].empty?
buckets[:join_node] << join_node
else
buckets[:leading_join] << join_node
end
end
joins.each do |join|
case join
when Hash, Symbol, Array
buckets[:association_join] << join
when ActiveRecord::Associations::JoinDependency
buckets[:stashed_join] << join
when Arel::Nodes::Join
buckets[:join_node] << join
else
raise "unknown class: %s" % join.class.name
end
end
build_join_query(manager, buckets, Arel::Nodes::InnerJoin, aliases)
end
つっつきボイス:「JOINの順序維持問題は@kamipoさんが以前も似たようなことを言及してたのを見たような気がしますね」「そういえば既視感あると思ったら、以前Arelの話題で取り上げた#36805↓が上と近い問題でした(ウォッチ20190819)」
参考: Preserve user supplied joins order as much as possible by kamipo · Pull Request #36805 · rails/rails
「@783cafeのコミットメッセージ↓でも#36805に言及してますね」「こういうのは見つけてつぶしていくしかなさそう🙏」
リレーションに
eager_load
とstringのjoins
だけがある場合、#36805によってstringのjoins
が最初のjoins
とみなされ、従来と挙動が変わる。
joinの順序を従来どおりにするために、stringのjoins
より前にjoinのeager loadingを先にチェックする。
@783cafeより大意
「お〜、こういうふうにjoins
に生SQLを書く形でテストするのね↓」
# activerecord/test/cases/associations/inner_join_association_test.rb#L82
+ def test_eager_load_with_string_joins
+ string_join = <<~SQL
+ LEFT JOIN people agents_people ON agents_people.primary_contact_id = agents_people_2.id AND agents_people.id > agents_people_2.id
+ SQL
+
+ assert_equal 3, Person.eager_load(:agents).joins(string_join).count
+ end
参考: joins
-- ActiveRecord::QueryMethods
⚓(master)amatsudaさんのアロケーション削減
- commit: Reduce Array allocations · rails/rails@0fa8c0a
- commit: Reduce Hash allocations · rails/rails@5c07e1a
- commit: Reduce object allocations in Journey · rails/rails@2db4c02
# activesupport/lib/active_support/parameter_filter.rb#L59
def self.compile(filters, mask:)
return lambda { |params| params.dup } if filters.empty?
- strings, regexps, blocks = [], [], []
+ strings, regexps, blocks, deep_regexps, deep_strings = [], [], [], nil, nil
filters.each do |item|
case item
when Proc
blocks << item
when Regexp
- regexps << item
+ if item.to_s.include?("\\.")
+ (deep_regexps ||= []) << item
+ else
+ regexps << item
+ end
else
- strings << Regexp.escape(item.to_s)
+ s = Regexp.escape(item.to_s)
+ if s.include?("\\.")
+ (deep_strings ||= []) << s
+ else
+ strings << s
+ end
end
end
つっつきボイス:「お〜、この地道な修正はまさにこの間の銀座Rails#13でamatsudaさんが話してたトピックのひとつですよ😋」「😀」「このときのスライド見たいんですけどね...」「探したけど見つかりませんでした🥺」
明日の銀座Rails 1周年記念回で、Railsのパフォーマンスに関するちょっとマニアックかも知れないお話をします。先ほど席を増やしてもらったので、今からご登録いただいてもまだ間に合うかもしれません。
興味のある方とか銀座で飲みたい方はぜひどうぞ! https://t.co/RqTvJD45lV— Akira Matsuda (@a_matsuda) September 11, 2019
「ベンチマークをがっと出してメモリ消費量をリストアップして、『ここが多そう』と当たりをつけては修正してはまたベンチ回すという感じでメモリアロケーションを減らしているそうです💪」「すげぇ〜!」「@5c07e1aのコミットメッセージにつぶやきが↓」「苦労が偲ばれる🙇」
「@2db4c02の修正↓を見ると、map
よりeach
の方がアロケーションが少ないということ?」「修正前はmap
のブロックの中でまたmap
を回してたけど、修正後はどちらもeach
に変えてますね」「つまりメモリアロケーション的にはmap
よりeach
の方が有利ということか😳」「おぉ〜」「あくまでフレームワークの最適化としてですけどね☺️」
# actionpack/lib/action_dispatch/journey/gtg/transition_table.rb#L44
def move(t, a)
return [] if t.empty?
regexps = []
+ strings = []
- t.map { |s|
+ t.each { |s|
if states = @regexp_states[s]
- regexps.concat states.map { |re, v| re.match?(a) ? v : nil }
+ states.each { |re, v| regexps << v if re.match?(a) && !v.nil? }
end
if states = @string_states[s]
- states[a]
+ strings << states[a] unless states[a].nil?
end
- }.compact.concat regexps
+ }
+ strings.concat regexps
end
「map
とeach
だとアロケーション周りの内部実装が違うのかな?」「map
の挙動からしてメモリコピーはやってるでしょうね: ビックリ付きのmap!
だと破壊的なので違いますけど」「そうそう☺️」「APIドキュメント↓によるとeach
の戻り値はレシーバーだから確かにアロケーションは起きませんね」「map
は配列を返すから回すたびにアロケーションすると」
参考: map
-- Class: Array (Ruby 2.6.4)
参考: each
-- Class: Array (Ruby 2.6.4)
「お、上の修正前コードの外側のmap
は生成した結果をわざわざ捨ててるし」「結果のarray使ってなかったのね😳」「each
でやれるところだったのにもったいない」「これは残念なパターン😆」「自分はmap
大好きマンですけど、そのせいかたまにこんな感じでmap
をうっかり繰り返しのためだけに使っちゃったりしますね😅」
「そういえば以前この↓記事でeach
より先にmap
使おうって言ってましたね😆」「メモリアロケーションみたいな最適化は後回しにしたい派だしmap
好きなの❤️」「そういえば『最初から最適化するな』って普段からおっしゃってますよね☺️」「自分はeach
で書いてみる派かな〜😆」「この辺は人による😆」
「あと、map
はcollect
で書く方が集めるというイメージに合ってて好きですね😋」
⚓Rails
⚓スライド: Netflixの「Surrounded by Microservices」
I've published the slides for my @euruko presentation! Thank you all for the wonderful questions and great architecture discussions! https://t.co/rXzm3DE1G2
— Damir Svrtan (@DamirSvrtan) June 24, 2019
つっつきボイス:「これは今年6月にNetflixが発表したRails設計話で、スライドないかと思ったらありました😂」
終盤、彼らのアーキテクチャが("Surrounded by Microservices"な状況において)なぜ素晴らしいかというのを、"Bobおじさん"の「優れたアーキテクチャの目的は意思決定を遅らせることである」という言葉を引き合いに説明する場面も良かった。必要な情報が出てくるまで待てる構造を作るのを心がけたい。 https://t.co/D1D6owcuIG
— (やさいち|yasaichi) (@_yasaichi) September 11, 2019
「やさいちさんのツイートのまとめがわかりやすいです↑」「ヘキサゴナルアーキテクチャ↓ですか!」「Netflixといえばカオスエンジニアリング💪」「強い」「Hanamiの話も出てきてる🌸」
参考: Netflix 驚異的なトラブル対応 カオスエンジニアリングとは、何か?
「今Netflixのスライドを見てみると、割と写真中心ですね😆」「おしゃべりの背景用かな😆」「動画の方がメインかな😅」
動画はよく編集されていて字幕も見やすくなっています😋。
「ツイートに『優れたアーキテクチャの目的は意思決定を遅らせることである』とありますね」「気持ちわかる」「わかる😂」「YAGNIはやめとけと」
「EuRuKoってEuropean Ruby conferenceなのね」「conferenceなのにKo?」「ヨーロッパだとKで書く感じの地域が割とありますね(ドイツとかチェコとかロシアとか)」
そういえば、ヨーロッパ系の人はcompanyを「コンパニー」みたいに発音する傾向がどことなくある印象です。
EuRuKoのまとめ記事: EuRuKo 2019: A recap
既に来年のeuruko2020.orgのドメインもできてますね😋。
⚓スライド『Concernsに関する懸念』でconcernsを考える
つっつきボイス:「ruby-jp Slackで見かけたスライドです」「@willnetさん!」
「concernsというと、だいたいよくない使われ方の方をよく見かけますね😆」「そうそう😆」「『関心事』とは果たして何ぞやと😆」「concernsはピュアなRubyのモジュールという印象」「実際そうですし」
「『初心者が取り扱うのは難しい』、ほんとそう!」「やめといた方がいい😆」「適切なconcernsってそうそう作れませんし、基本的にはconcernsってほぼ使わないな〜☺️」「自分は割とconcerns好きなのでちょいちょい使ってますけど😆」
「concernsをRailsで使う意味がどこまであるかですよね: concernsでメソッド生やしてもいいけど、includeしたときにconcernsで生やしたものが全部ちゃんと動くように設計できるのか?って思ったりしますし」「まあそれはありますね」「ちゃんと設計しておかないと、こっちのモデルにはconcerns生やすと動くけど、あっちのモデルでconcernsすると動かないとか、そういうものがきっと残る😇」
「それで言うとRubyのEnumerableはeach
を定義してincludeすれば必ず動くからキレイですよね✨」「たしかに!」「concernsもそんなふうに『このconcernsをincludeしていい条件はこれとこれだよ』というのが明らかになってないと気持ち悪い😓」
参考: module Enumerable
(Ruby 2.6.0)
「あと、ソースコードの行数を減らすためだけにconcernsを使っている残念なパターンも見かけますよね😆」「おぉ、ちょうどスライドにもその事例が↓😆」「Postsでしか使ってないモジュール😇」「これはマジでやめて欲しい😤」「それ普通にPostsに書けばええやんって思いますし」「ほんに」「でもやりたくなっちゃうとき、あるんですよね〜😅」
「こういう形でconcernsを使われると困るのは、ファイルが分かれてしまうからどこでincludeされているかまで考えないといけなくなることがまず1つ」「うんうん」「2つ目は、こういうPostでしか使わないつもりのコードがconcernsになっていると、それを他の人が見て『お、concernsに入っているこれ使えるじゃん❤️』って勝手に他で入れようとする事案が発生すること😇」
「スライドにもあるけど、concerning
で名前空間を分けるだけならわかる↓」「concerning
ってのがあるんですね😳」「concerning
も一応同じように書けます😎」
参考: concerning
-- Module::Concerning
参考: Rails 4.1.0 で追加された Module#concerning と関心事の分離 | TECHSCORE BLOG
「そうそう、rubocopのClassLength
で怒られないためにconcerns使うのヤメレと↓😆」「『行数多すぎ』ってヤツですね」
参考: Metrics/ClassLength
-- Metrics Cops - RuboCop: The Ruby Linter that Serves and Protects
「とはいうものの、concernsだと一見それっぽくできちゃったりするんですよね〜😅」「RubyMineの右クリックリファクタリング的な感じの単なるコピペになりがち😆」「たしかに意味変わらないんだけどそれをconcernsでやらないで〜って😭」
「スライドに引用されているDHHのコードのconcernsの量がヤバい↓🤣」「🤣」「しかも# Depends on Readable
とかがずらっと並んでるあたりconcerns地獄感ある😈」
(Note: I'm showing this out of pride, not shame. Ruby mixins is on my top 5 of favorite features of the language ❤️).
— DHH (@dhh) February 15, 2018
「concernsによほどいい名前が付けられていれば別だけど、この書き方は好きじゃないな〜😅」「Copyable
とかReadable
とかって、ライブラリの機能ならともかく業務コードでその機能使う?って気持ちになりますし😆」「でもPrintable
だったらありかな、というかこれは他でも使われてるちゃんとしたconcernsという気がする」「そんな感じしますね」
「あとconcernsは読み込み順序も絡んでくるのがマジ面倒」「あ〜前後関係ありますね!」「スライドにもあるけど、concernsは最終的に1つのクラスに集約されちゃうから大変😭」「😆」「methods
してgrep
するとヤバいことになってる😇」「メソッド名がかぶると死にますし😇」「名前空間を分ける、はホントに大事」
「DHHはこれをいいと言うけど、結局ここに行き着くという↓🤣」「わかる〜🤣」「バンドが解散する理由ってたいていこれですよね🤣」
「フックをconcernsにする↓のもたまに見かけるし: コントローラのconcernsにbeforeなんちゃらを書いてincludeするヤツ、自分はあんまり読みやすいと思わない😆」「これがよほど特殊な計算で複数の場所で使うならconcernsもワンチャンありかなという気がしますけど、この例だと単にTime.zone.now
してるだけだからconcernsにする意味がまったくないな〜って思いますし😆」
「コントローラの認証のコードをconcernsにしてincludeするとかなら、わかる」「それならわかりますね☺️」「ネストしたURLの末尾idチェックをconcernsにしてbefore_action
で動かすとかもやりますね」「concernsの中でのbefore_action
ってリダイレクトしたときどうなるんだっけ?」「あ、before_action
はレンダリングするとリダイレクトしないでそこで終わっちゃうので、むしろきれい😆」「それはそれで、しれっと書かれたincludeにはじかれるという悲しいことが発生するという😆」「そう、だからやりすぎ注意😅」
「これ↑もね、とてもよくわかる😆」「わかるわかる〜!😆」「そういえば例の肥大化したActiveRecordモデル記事↓でも言ってましたね」
「@willnetさんのスライドとてもためになる❤️」「つらいconcernsをたくさん見てくるとわかってくる😭」
「concernsディレクトリってデフォルトで作らなくてもいいのに、という気もするけど、たぶんここはDHHの思想なんだろうな...」「あれは要らないっすね〜😅」「悪い使い方を誘発しがちというか」「ゴミ置き場になりやすい」
「modelsディレクトリの直下のconcernsじゃなくて、そこからもうひとつ名前空間を掘ったところに置くconcernsなら、あっていいと思う」「そうそう!」「それなら『このconcernsはこの下でしか呼ばれない』ということが伝わるから😋」「それなら関心が分離されてる感ありますね」「逆にcontrollersの直下のconcernsに20個ぐらいあったりすると、その治安の維持は相当難しいと思うし😇」「そのconcernsはシステム全体を横断する関心事なのかと問い詰めたくなりますし😆」
後でDHHがRails 4でconcernsを導入したときの記事を見つけました↓。
参考: Put chubby models on a diet with concerns – Signal v. Noise
⚓テストを不安定にさせる要因
つっつきボイス:「こちらもruby-jpで見かけました」
「CIはたまにこうやってコケる😆」「たまにコケるのやめて欲しい😭」「たまにコケたらrandom seedを固定して何回か回して...と😆」「時刻絡みでコケるとか多いっすね😆」「コケたらとりあえずもう1回回してみると😆」
「必ずORDER BYを付けよう、とか」「あ〜それたまに忘れちゃう😅」「この辺ってDBMSによっても違うことがあって、MySQLだと(ORDER BYがなくても)経験的には入れた順で毎回同じ結果が返ってきたりするんですけど、ぽすぐれはそうとは限らないという」「ぽすぐれのご機嫌次第😆」「でもSQL的には本来ぽすぐれの方が正しい」
参考: MySQLでORDER BYをつけないときの並び順 - かみぽわーる -- InnoDBかMyISAMかで違ってくるそうです
⚓GitHubがRails 6へのアップグレードを完了
つっつきボイス:「これもバズりましたね😋」「Publickeyに先越されましたorz」「わずか9日とあるけど、その前からやってたでしょきっと😆」「そのためにGitHubは2年半かけて独自forkを解消してましたね(ウォッチ20190603)↓」
⚓その他Rails
つっつきボイス:「ちょうど定員越えてる」「よさげなイベントですが、気づくのが遅かった😭」「マルチDBの話もやるのね」「でかいシステム扱ってる人はたいていマルチDBやりますね☺️」
以下はつっつき後に見つけました。
前編は以上です。
おたより発掘
Railsでのconcerns、使い方が難しい。モジュールやクラス間に暗黙の依存関係を持ち込むので、あまり好きではないなぁ。https://t.co/zeJRM0fLMS
— Masafumi Koba (@ybiquitous) September 25, 2019
バックナンバー(2019年度第3四半期)
週刊Railsウォッチ(20190918-2/2後編)RubyPrize 2019候補者発表、GoogleがTypeScript 3.5に熱烈フィードバック、日本語形態素分析kagomeほか
- 20190917-1/2前編 Sidekiq 6.0がリリース、銀座Rails#13と「出張!Railsウォッチ」、るびま0060号、ロックイン回避の落とし穴ほか
- 20190910-2/2後編 buildersconと「20年後のソフトウェアテスト」、はてなブックマークがScalaに移行、「詳解PostgreSQL」、Go 1.13ほか
- 20190909-1/2前編 Rails 6のキャッシュバージョニング、Rubyのキーワード引数周りが変わる、Faker 2がリリースほか
- 20190902 Ruby 2.6.4セキュリティ修正リリース、スライド「All About Ruby in 2019」、Shrine gem 3.0に入る新機能ほか
- 20190826 6-0-stableの更新を見てみる、『Morning Cup of Coding』ニュースレター、Rails TutorialがRails 6対応に動き出すほか
- 20190821-2/2後編 11のgemにバックドア、ruby-jp Slackがとてもアツい、Fullstaq Rubyでチューンアップ、HTTPサービス監視chaoほか
- 20190819-1/2前編 祝: Rails 6がついにリリース、RailsガイドもRails 6に対応、Arelはpublicだったかほか
- 20190806-2/2後編 RSpec CopのLeakyConstantDeclaration、serveoでゼロコンフィグ公開、RuboCopのPerformance/RegexpMatch改修ほか
- 20190805-1/2前編 Rails 6のActive Recordは速くなった、Windows WSL2+VSCodeでのRails開発、Martin Fowler記事ほか
- 20190730-2/2後編 Docker 19.03の新機能に注目、ngrokはスゴい、redis-namespaceほか
- 20190729-1/2前編 Rails 6のリリースは近そう?、Evil MartiansのRails+Docker記事、Railsパフォーマンス測定ほか
- 20190723-2/2後編 Rails 6 rc2がリリース、「MySQLパフォーマンスチューニングTips」が超便利、Aurora Serverlessほか
- 20190722-1/2前編 Rails 6エラー画面の改良点、Dateを四捨五入できるtime_calc、Rackミドルウェアのデザインパターンほか
- 20190717-2/2後編 NFSのよさとは、Linuxカーネル5.2リリース、Puppeteerでメモリリーク検出ほか
- 20190709-2/2後編 strong_password v0.0.7がハイジャックされていた、TerraformとCloudFormation、CSSの設計ミスリストほか
- 20190708-1/2前編 ActiveRecord::FixtureSetがめちゃ強くなってた、MacだとRubyが遅い理由、Puma 4登場ほか
- 20190701 RMagickのメモリ使用量が劇的に改善、インスタンス変数の定義順で速度が変わる?、GitLab CIランナーをローカルで回すほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSなど)です。