- Ruby / Rails関連
週刊Railsウォッチ(20200210前編)Railsのベンチマークジェネレータ、長いバックグラウンドジョブと戦う、Timestamp切り詰めの謎、Open APIツールほか
こんにちは、hachi8833です。そういえば明日は祝日ですね。コロナウイルス流行の様子が早速ビジュアライズされたようです。
「まあこれで何かわかったとしても自分らに打てる手は限られてますし😷」「情報の動き激しくて...😅」(以下延々)
参考: CNN.co.jp : 新型ウイルス、潜伏期間中の感染例は「誤り」 独当局
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
- 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください
今回は第19回公開つっつき会を元にお送りします。お集まりいただいた皆さまありがとうございます!
⚓Rails: 先週の改修(Rails公式ニュースより)
今週はコミットログより見繕いました。今週は細かめの修正が多い印象です。
⚓default_scoped
をpublic APIに
Rails link: Expose `klass.default_scoped` as public APIhttps://t.co/heZi7Zuhoa
— Bogdan (@bogdanvlviv) January 27, 2020
# activerecord/lib/active_record/scoping/named.rb#L25
def all
scope = current_scope
if scope
if scope._deprecated_scope_source
ActiveSupport::Deprecation.warn(<<~MSG.squish)
Class level methods will no longer inherit scoping from `#{scope._deprecated_scope_source}`
in Rails 6.1. To continue using the scoped relation, pass it into the block directly.
- To instead access the full set of models, as Rails 6.1 will, use `#{name}.unscoped`,
- or `#{name}.default_scoped` if a model has default scopes.
+ To instead access the full set of models, as Rails 6.1 will, use `#{name}.default_scoped`.
MSG
end
if self == scope.klass
scope.clone
else
relation.merge!(scope)
end
else
default_scoped
end
end
...
- def default_scoped(scope = relation) # :nodoc:
+ # Returns a scope for the model with default scopes.
+ def default_scoped(scope = relation)
build_default_scope(scope) || scope
end
つっつきボイス:「上は実はついさっきkamipoさんがリツイートしたコミットです🐦」「お、unscoped
してしまった後でもデフォルトスコープを取れるのがdefault_scoped
っていうことみたい: 自分はあんまり使わなそうだけどpublicメソッドが欲しい気持ちはワカル☺️」
API: unscope
-- ActiveRecord::QueryMethods
default_scoped
は、スコーピング上デフォルトスコープになっているスコープを強制的に返す唯一の方法であり、マイグレーションでのスコープのリークを回避するのに必要。
同PRより大意
「default_scope
を使わないのが一番なんでしょうか?🤔」「そういうわけにもいかないことがありますし、小さいシステムならdefault_scope
があっても嫌がられないと思いますが、育ってくるとちょっとね...😅」
⚓delegateのeach
を取り除いた
# actionpack/lib/action_dispatch/testing/integration.rb#L80
class Session
DEFAULT_HOST = "www.example.com"
include Minitest::Assertions
include TestProcess, RequestHelpers, Assertions
- %w( status status_message headers body redirect? ).each do |method|
- delegate method, to: :response, allow_nil: true
- end
-
- %w( path ).each do |method|
- delegate method, to: :request, allow_nil: true
- end
+ delegate :status, :status_message, :headers, :body, :redirect?, to: :response, allow_nil: true
+ delegate :path, to: :request, allow_nil: true
つっつきボイス:「見出しに"delegate
allows multiple method names are passed"とあるのは...?」「delegateの内容は変わってないので、each
のループをなくしたということなんでしょうね☺️: タイトルは単にこの部分の挙動をメモった感じかな」「走り書きでしたか😅」「Railsの起動がちょっと速くなりそう☺️」「以前%w()
で書かれてた理由はわかりませんけど😆」
⚓キーワード引数対応: define_method
をstringのevalに変更
- commit: Use string eval instead of `define_method` for integration session me… · rails/rails@1dac170
# actionpack/lib/action_dispatch/testing/integration.rb#L356
%w(get post patch put head delete cookies assigns follow_redirect!).each do |method|
- define_method(method) do |*args, **options|
- # reset the html_document variable, except for cookies/assigns calls
- unless method == "cookies" || method == "assigns"
- @html_document = nil
- end
+ # reset the html_document variable, except for cookies/assigns calls
+ unless method == "cookies" || method == "assigns"
+ reset_html_document = "@html_document = nil"
+ end
- result = if options.any?
- integration_session.__send__(method, *args, **options)
- else
- integration_session.__send__(method, *args)
+ definition = RUBY_VERSION >= "2.7" ? "..." : "*args"
+
+ module_eval <<~RUBY, __FILE__, __LINE__ + 1
+ def #{method}(#{definition})
+ #{reset_html_document}
+ result = integration_session.#{method}(#{definition})
+ copy_session_variables!
+ result
end
- copy_session_variables!
- result
- end
+ RUBY
end
「これもさっきと同じintegration.rbファイルの変更ですね」「今までdefine_method
で定義していたのをmodule_eval
に変えたのね😋」
「『キーワード引数をif options.any?
で扱うのはイケてない』みたいなことが書いてあるのでキーワード引数関連かな🤔: definition = RUBY_VERSION >= "2.7" ? "..." : "*args"
とかありますし、stringのevalにすればdefine_method
経由ではなくなってstringで書けるようになるので、definition
で2.7以降の場合とそうでない場合に...
と*args
を使い分けられるようになったということか😋」「なるほど!」「速度が目的ではなさそうなので、たぶんstringじゃないと2.7対応がやりにくいんでしょうね☺️」
「コミットで引用されてるb7e591aやa43de73を見るとamatsudaさんが**options
引数周りで試行錯誤してますね」「あぁ、Ruby 2.7のキーワード引数変更問題に引っかからないようにするためのやり方を試行錯誤してる感じ: if options.any?
の結果で分岐するか、上みたいにstringでRubyコードそのものにパッチを当てる形で修正するか」「Railsのフレームワークでは複数バージョンのRubyに対応しないといけないので大変😅」
⚓スキーマキャッシュ読み込み時のDB configフォールバック
# activerecord/lib/active_record/railtie.rb#L127
initializer "active_record.check_schema_cache_dump" do
if config.active_record.delete(:use_schema_cache_dump)
config.after_initialize do |app|
ActiveSupport.on_load(:active_record) do
db_config = ActiveRecord::Base.configurations.configs_for(
env_name: Rails.env,
spec_name: "primary",
)
+ next if db_config.nil?
+
filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
db_config.spec_name,
schema_cache_path: db_config.schema_cache_path,
)
if File.file?(filename)
current_version = ActiveRecord::Migrator.current_version
next if current_version.nil?
cache = YAML.load(File.read(filename))
if cache.version == current_version
connection_pool.schema_cache = cache.dup
else
warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
end
end
end
end
end
つっつきボイス:「修正は1行追加だけ」「前回のウォッチでもマルチDBがreplicaじゃなくてprimaryから取ってきちゃう問題の修正があったのを少し思い出しますね🤔(ウォッチ20200203)」「マルチDBも大変そう...」
概要
スキーマキャッシュはデフォルトでprimaryデータベースconfigを読み出す。しかしspec nameがprimaryのデータベースconfigがアプリにない場合、ファイル名探索に失敗する。
ここでは念のためフォールバックを追加した。
その他
スキーマキャッシュのファイル名はハードコードされていたが、Railsではデフォルトパスをオーバーライドできるようになっている。#38348ではオーバーライドを考慮するようにしたが、spec nameがprimary
のデータベースconfigがないアプリの対応が漏れていた。
GitHubにはprimary
という名前のデータベースがないこともわかったので、このActive Recordイニシャライザに依存していないとしても失敗する。
同PRより大意
⚓GitHub ActionsのRailsビルドを数秒短縮
- PR: [GitHub Actions] Save few seconds on every build by JuanitoFatas · Pull Request #38372 · rails/rails
# .github/workflows/rubocop.yml#L21
- gem install bundler:2.1.2
+ gem install bundler:2.1.2 --no-document
つっつきボイス:「ドキュメント生成やめたのね😆」「言われてみればなるほど😆」「ドキュメント生成は結構重いし🏋🏻♀️」「速くなるのわかります😋」
⚓細かな修正系
- PR: Correct test helpers paths in test guides by mibradev · Pull Request #38366 · rails/rails
- PR: Fix the environment.rb file path in the benchmark generator template by bknarendra · Pull Request #38378 · rails/rails
- commit: Fix non-condition `elsif` · rails/rails@db8e957
つっつきボイス:「微修正をまとめてみました」「Railsガイドのパスの間違いとか☺️」
# activerecord/test/cases/migration_test.rb#L211
if current_adapter?(:Mysql2Adapter)
if ActiveRecord::Base.connection.mariadb?
assert_match(/Can't DROP COLUMN `last_name`; check that it exists/, error.message)
else
assert_match(/check that column\/key exists/, error.message)
end
- elsif
+ elsif current_adapter?(:PostgreSQLAdapter)
assert_match(/column \"last_name\" of relation \"people\" does not exist/, error.message)
end
「elsif
の条件が抜けてたとは↑😆」「その下のassert_match
が条件扱いされるからエラーなしで通っちゃってた😆」「RuboCopに引っかからなかったのか👮🏼♀️」
# railties/lib/rails/generators/rails/benchmark/templates/benchmark.rb.tt#L3
-require_relative "../config/environment"
+require_relative "../../config/environment"
「こんなエラー↑が今頃見つかるとは😆」「つかrails benchmark
ってコマンドありましたっけ?」「知らない😆」「そんな機能が入ってたことの方がびっくり😳」
⚓Railsのベンチマークジェネレーター
概要: パフォーマンス最適化を比較するベンチマークを生成する。
デフォルト: method = ips
例:rails generate benchmark opt_compare path_a path_b
上で以下が生成される:
benchmarks/opt_compare.rb
--method
で他のベンチマーク手法を指定できる。有効な手法はips、bm、bmbm
Changelogより
「軽くググると昨年12月13日にベンチマークジェネレーターがmasterに入ってるし↑😆」「Rails 6.1あたりで使えるようになるのかな?」「そんなに複雑なことはやってないと思うけど、ベンチマークって自分でやろうとすると毎回ググるので、ベンチマークのテンプレートをRailsで生成できるならいいかな〜😋」
⚓番外: オプション引数をつぶして回る
- commit: Make `localize` helper takes keyword arguments the same with `I18n.lo… · rails/rails@b803ed0
# actionpack/lib/abstract_controller/translation.rb#L26
- def localize(*args)
- I18n.localize(*args)
+ def localize(object, **options)
+ I18n.localize(object, **options)
end
- commit: Make `translate` helper takes keyword arguments the same with `I18n.t… · rails/rails@6c02fee
# actionpack/lib/abstract_controller/translation.rb#L13
- def translate(key, options = {})
+ def translate(key, **options)
if key.to_s.first == "."
- options = options.dup
path = controller_path.tr("/", ".")
defaults = [:"#{path}#{key}"]
defaults << options[:default] if options[:default]
options[:default] = defaults.flatten
key = "#{path}.#{action_name}#{key}"
end
I18n.translate(key, **options)
end
- commit: Fix `foreign_key_exists?` in `change_table` to allow keyword arguments · rails/rails@6a80902
# activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb#L709
- def foreign_key_exists?(*args)
- @base.foreign_key_exists?(name, *args)
+ def foreign_key_exists?(*args, **options)
+ @base.foreign_key_exists?(name, *args, **options)
end
つっつきボイス:「ああ*args
やoptions = {}
を置き換えるヤツ☺️」「options = {}
みたいなレガシーな書き方がまだまだ残ってた😆」「だいぶ前にbabaさんがキライだって言ってた書き方ですね↓」
「options = {}
は、キーワード引数が登場する前のRuby 1.9とも互換性のある書き方だったと思います」「そういえばキーワード引数が登場したのはRuby 2.0でしたね」
「ところでお集まりの皆さんの中でRuby 1.8あたりを経験された方は?: さすがにいませんね😆」「Rails 4からなので😆」「自分の時代は今は亡きRuby Enterprise Edition↓使ってたので1.8経験しました: サイトは生き残ってるけどやはり1.8.7で止まってるか〜😆」「そういえばここってPassengerの会社がやってたんですね😳」「そうそうPhusion」
参考: Welcome — Ruby Enterprise Edition
「ちなみにRuby Enterprise Editionは一応今でもrbenvにエントリぐらいはあります↓」「おぉっ」「でもさすがにOpenSSLのバージョンが今と違ってるでしょうからビルドは無理じゃないかな〜🤣: 試しに裏でビルドしてみよう」(しばらく経って)「やはりダメか😆」
ree-1.8.7-2011.03
ree-1.8.7-2011.12
ree-1.8.7-2012.01
ree-1.8.7-2012.02
参考: OpenSSLが古すぎてbundle updateできない
「今の時代にやんごとない事情でRuby 1.8を動かさないといけなくなったらDockerコンテナでやるとかになるでしょうね🐳」「Docker Hub見ると1.8コンテナ作ってる人がかろうじているけど、どこまで信用できるかわかりませんし😆」
kwargs非互換対応が不完全なところを直すためにRails全体を読まざるを得なくなったためアクティブレコード以外の今まであんまり興味なかったコンポーネントについてもチョットデキルようになってしまった
— Ryuta Kamizono (@kamipo) February 6, 2020
こういうのどうやって検知してるんですかって言われたことあるけど、単に全部のコミット読んでて僕の好みのスタイルにもプロジェクトのコーディングルールにも反してるから眼のチカラが自動的に発動してるだけです👁https://t.co/k10mlJJa7l
— Ryuta Kamizono (@kamipo) February 6, 2020
つっつきボイス:「上はさっき流れてきたツイートです」「さらっと『全部のコミット読んでる』」「最強すぎ💪」「最後は眼ぢから👁」
⚓Rails
今回は大半がRuby Weeklyのエントリになりました。軽く敗北感。
⚓RailsのTimestampが切り詰められた(Ruby Weeklyより)
# 同記事より
{"created_at"=>2020-01-02 13:36:22.459149334 +0000, "updated_at"=>2020-01-02 13:36:22.459149334 +0000}
{"created_at"=>2020-01-02 13:36:22.459149000 +0000, "updated_at"=>2020-01-02 13:36:22.459149000 +0000}
つっつきボイス:「あ〜マイクロ秒以下が落ちちゃうヤツ↑あるある🤣」「🤣」「reload
すると変わる↓とある」
# 同記事より
before perform: 1577985089.0547702
after perform: 1577985089.0547702
after reload: 1577985089.05477
「Active Recordはsave
メソッドを呼ぶとINSERTなりUPDATEなりが行われるんですけど、DBに実際に保存した値を読み込み直すことまではしないので、save
した直後に値を参照すると、DBに保存された値そのものではなくRuby側で設定したときの値を返します」「後でreload
してみると値が変わってたとは😇」「😳」「めったに踏みませんけど、たまに出くわしますね☺️」
目次より:
- 問題: macOS上のdev環境ではテストが通るのにCIでほぼ失敗する(何とかログは取れた)
- 調査
- 桁落ちを発見
- プリントデバッグでは再現せず、
calendar.attributes['created_at']
でattributeハッシュを直接フェッチすると再現した
- 修正
DateTime
オブジェクトを生成して秒以下を丸め、このオブジェクトでタイムスタンプを明示的に設定した
- 原因
- Active Recordのタイムスタンプが
Time.now
で設定されているがTime
の精度はOSに依存する
- Active Recordのタイムスタンプが
- 疑問(説明求む)
calendar.attributes['created_at']
だとリロードされたのにcalendar.created_at
だとリロードされないのはなぜ?- Linuxと比較してみるとmacOSでの精度は6桁どまりという驚きの結果(7桁目以降は1と2と8と9しか現れない↓)
# 同記事より
10000.times.map { Time.now}.map{|t| t.to_f.to_s.match(/\.(\d+)/)[1] }.select{|s| s.size == 7}.group_by{|e| e[-1]}.map{|k, v| [k, v.size]}.to_h
# MacOS => {"9"=>536, "1"=>555, "2"=>778, "8"=>807}
# Linux => {"5"=>981, "1"=>311, "3"=>1039, "9"=>309, "8"=>989, "6"=>1031, "2"=>979, "7"=>966, "4"=>978}
⚓sequenced: ARモデル向けのシーケンシャルID生成(Ruby Weeklyより)
# 同リポジトリより
class Question < ActiveRecord::Base
has_many :answers
end
class Answer < ActiveRecord::Base
belongs_to :question
acts_as_sequenced scope: :question_id
end
つっつきボイス:「このgemの嬉しみってどのあたりでしょう?」「冒頭に書いてあるそのまんまですが、プライマリキーではない、スコープドのシーケンシャルIDを生成できるということですね☺️」
「使いみちとしては、たとえばですがUser
モデルにhas_many :pictures
があったとすると、どのユーザーについてもユーザー独自の1個目の画像をURLで表現できるようにしたい、なんて場合があればでしょうね」
「Railsで普通にネステッドスコープを作ると、ネステッドの先もサロゲートキーになりますよね: 言い換えればそこは名前空間が同じになるので、ユーザーAにとっての画像1もユーザーBにとっての画像1も同じものを指してしまう」「ふむふむ」「このsequenced gemを使えば、/ユーザーA/1
で取れる画像が必ずそのユーザーAにとっての1個目の画像になり、/ユーザーB/1
だとそれとは異なるユーザーBにとっての1個目の画像になる、といった具合です」
「このgemを使うかどうかは別として、こういうのをやりたい場合があるのはわかりますね☺️」「自分で書くのもありな機能でしょうか?」「スコープドのシーケンシャルID生成ではシーケンス番号がかぶらないように保証するのが面倒くさくなりがちなので、このgemがトランザクション管理までやってくれるのであればワンチャンあるかも🤔」
「READMEの下の方にdata integrityとかあるしやってくれるかな?...とよく見ると『これはPostgreSQLでしかコンカレント安全でない』って書いてあるし😆」「😆」「というわけでぽすぐれ以外ではシーケンシャルがIDかぶる可能性あります: 以下のPARTITION BYあたりとかPostgreSQL向けっぽいですし↓」
# 同リポジトリより
# app/db/migrations/20151120190645_add_sequental_id_to_badgers.rb
class AddSequentalIdToBadgers < ActiveRecord::Migration
add_column :badgers, :sequential_id, :integer
execute <<~SQL
UPDATE badgers
SET sequential_id = old_badgers.next_sequential_id
FROM (
SELECT id, ROW_NUMBER()
OVER(
PARTITION BY burrow_id
ORDER BY id
) AS next_sequential_id
FROM badgers
) old_badgers
WHERE badgers.id = old_badgers.id
SQL
change_column :badgers, :sequential_id, :integer, null: false
add_index :badgers, [:sequential_id, :burrow_id], unique: true
end
- PostgreSQL 11ドキュメント: 3.5. ウィンドウ関数
「こういうことをしたいときが数年に1回ぐらいはありそう😆」「😆」「そのときにこのgemを思い出せるかどうかですけどっ😆」
⚓Open API仕様記述ツール
- サイト: OpenAPI.Tools
つっつきボイス:「今日のWebチーム内発表がOpen APIの話題だったので先週(ウォッチ20200203)に引き続いて」「そうそう、Open API(Swagger)で仕様を書くことがあるんですけど、上のサイトはOpen APIのツール集ですね: Open APIは夢のツールとまではいきませんが😆」
「チーム内発表ではstoplightというツール↓が登場してましたね」「stoplightはちゃんとWYSIWYGエディタになってて、とにかくyamlを手書きしなくていいのが嬉しい❤️」
「Swaggerエディタ↓って結局yamlを書かないといけないのがつらくありません?😆」「ある程度しょうがないかと思うけど生成されるyamlのファイル長すぎじゃね?って思ったりもするけど、Open APIがなかったらExcelで仕様書かないといけなくなりますし😆」
- サイト: Swagger Editor
参考: Open API仕様記述ツールを比較してみた - Qiita
「Qiitaにある中でAPI Blueprintは書いたことありますね: ちょっとMarkdown風ですが自由に書けすぎる感😆」
⚓Chrome 80のSameSite属性
世間を少し賑わせているChrome 80のSameSite属性の件が、ちょうど手持ちのRailsアプリに影響しそうだったので、対応方法をまとめてみました。
rails_same_site_cookie gemで、RailsアプリにChrome 80向けのSameSite属性を指定する https://t.co/uKPS6tC033 #Qiita
— Junichi Ito (伊藤淳一) (@jnchito) February 5, 2020
つっつきボイス:「SameSiteはもう入ってきたんでしたっけ?」「Chrome 80は昨日見ている目の前でインストールされました」「SameSiteの動作変更は来週からみたい」「デフォルトのSameSiteは本来こうあるべきかなと思いますけど😆」「SameSite=None; Secure
を付けると不具合を発生するブラウザって...」
「これで影響を受ける決済ってどのぐらいあるんでしょう?」「まあカード会社のサイトに行って戻るようなECサイトではそもそも普通POST
ではやりませんし」「おぉ」
「今どきクロスサイトでPOST
して、しかもまた戻ってくるような実装ってあんまり思いつかない🤔: トラッキング系のシステムとかならもしかするとあるかもしれませんが、jnchitoさんの記事もテスト方法が中心で実装されている例については見当たらないようなので、後で参考記事↓と合わせて読んだ方がよさそう」
参考: Chrome 80が密かに呼び寄せる地獄 ~ SameSite属性のデフォルト変更を調べてみた - Qiita
⚓長期間動き続けるジョブと戦う(Ruby Weeklyより)
割と長い記事です。
- バックグラウンドジョブでやるべきとき:
- リクエストがタイム・アウトする
- メモリスパイクの発生
- UXに影響する
- ツール
- Active Jobにするかどうか
- Delayed JobかSidekiqか
- バックグラウンドジョブの基礎
- グローバルID
- ジョブの事前条件をチェック(破壊的なアクションを叩かないよう注意)
- 巨大なジョブを分割
- ユーザーを上手に待たせる
- 完了をメールで通知
- ポーリングしてプログレスバーを表示
- 合わせ技プラスアルファ
- 上級技の紹介(取り扱い注意)
- まとめ
つっつきボイス:「wrangleはざっくり『戦う』ぐらいの感じで😆: Ruby Weeklyのタイトルではtameになってましたが」「長期間のバックグラウンドタスクはいろいろ大変😅」
「メモリスパイク、どのツールにするか、Delayed JobかSidekiqか、ジョブはグローバルIDで管理せよ、ジョブは冪等に書け、でかいジョブは分割せよ...と、なかなかいい感じにまとまった記事👍」「Resqueは選択肢に入ってないらしい😆」「やっぱ古いか😆」
「ユーザーを待たせる間どうするかの話も押さえてありますね: すぐ終わるダウンロードならいいけど20分ぐらいかかるようなジョブだとユーザーが待ちきれなくてブラウザ閉じちゃったりするので😆、どうハンドリングするかとか」「😆」「対策としてメールで通知するか、ポーリングしてプログレスバー出すかとか実践的なことが書かれてますね😋」
「前に勉強会で話していただいたバッチ処理の話↓にも通じるところありそうですね」「たしかに近いかも☺️」(ここで当該社内向けスライドを一同で閲覧)
「ただこの記事が掲載されているboringrails.comは今年春に発売予定のRails本↓に収録するためにサンプル記事以外は非表示にしているようです😅(ウォッチ20190930)」「ありゃ😆」「もしかすると後で非表示になるかも」
⚓その他Rails
- 元記事: Rails 6 - ActiveSupport Deprecations in Unicode and Chars support in favour of String – Saeloun Blog
つっつきボイス:「前にもウォッチ↓で取り上げた内容ですが一応リマインダーとして」「そうそう、Active Supportのdowncase
やupcase
やswapcase
とかがRuby本体でできるようになってましたね☺️」
週刊Railsウォッチ(20181022)Railsの名前空間地獄とrequire_dependency、PostgreSQL 11がリリース、clean-rails.orgほか
つっつきボイス:「短い記事です」「2.7のdeprecation warningを止める方法が3つ書かれてるけど結局RUBYOPT
でやるのは一緒で、それをどう渡すかの違いだけ😆」
参考: 環境変数 (Ruby 2.7.0 リファレンスマニュアル)
ジェレミー: ふつうreturnは書かん、ていうかスペース有無強制されるのマジ意味ないcop消したい
ラファエル: ふつうreturnは書かん、ていうかcop消して余計なスペース入るのなにがうれしいん?
サミュエル: return書かんくてバグったことあるから基本書きたい、スペースに関しては入れないのが好み— Ryuta Kamizono (@kamipo) February 6, 2020
ちなみにぼくは冗長なreturnは書かない派で演算子やhashブラケット前後のスペースはあける派です
— Ryuta Kamizono (@kamipo) February 6, 2020
つっつきボイス:「楽しい😋」「コミッター内でこれだけスタイルの好みが違うという😋」「hashブラケット前後のスペースを入れるかどうかは結構分かれますね〜☺️」「自分は入れる派」「linterにお任せ😆」
前編は以上です。後編は祝日をはさんで2/12(水)となります。
バックナンバー(2020年度第1四半期)
週刊Railsウォッチ(20200204後編)Ruby3.0の他のbreaking change、Rubyのシリアライザ、GitHubのcode ownersほか
- 20200203前編 Railsの各種高速化コミット、OpenAPIの使い所、パンくずリストgem loaf、Railsビュー最適化ほか
- 20200128後編 もう一つのgemマネージャgel、”Did you mean”の仕組みを追う、DXOpalでブラウザゲームほか
- 20200127前編 Railsでキーワード引数warning退治始まる、ライブラリとフレームワークの違い、ShopifyのRails高速化記事ほか
- 20200121後編 RubyKaigi 2020受付開始、RubyGemsとBundlerの今後、ファイル同期ツールMutagenほか
- 20200120前編 福岡でも公開つっつき会、Railsのconnection_specification_nameでprimaryという名前が非推奨に、structure.sqlとschema.rbほか
- 20200115後編 Ruby 2.7関連情報、Bootstrap 5は今年前半リリースか、PostgreSQLでやってはいけないリストほか
- 20200114前編 config_forのbreaking change、Active Storage variantをDBでトラッキング、SprocketsとWebpackの違いほか
今週の主なニュースソース
ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp Slackなど)です。