- Ruby / Rails関連
週刊Railsウォッチ(20200330前編)Active Record Doctorで診断、Webpacker 5、GitHubのViewComponentとRails 6.1の3rd-party component frameworkほか
こんにちは、hachi8833です。
つっつき前ボイス:「このところフルリモートで自宅作業していると、つい人と口をきくのを忘れちゃいそうになるので、つっつき会参加します」「そんなに」「ゴミ捨て以外まったく外に出ませんでした」「ほぼパーフェクト」
- 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
- 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
- 毎月第一木曜日に「公開つっつき会」を開催しています: お気軽にご応募ください
⚓Rails: 先週の改修(Rails公式ニュースより)
今回はコミットリストから見繕いました。
⚓PartialRendererをリファクタリング
今回のコミットリストでtenderloveさんのコミット数がやけに多いと思ったら、これでした。
つっつきボイス:「以下の❌マークの組み合わせはありえないので削除したということのようです」「お〜これは頑張った感ある」「パフォーマンス的には速くなった部分と遅くなった部分でプラマイゼロに近いようですが、コードはだいぶすっきりしたようです」
diffがかなり増えて申し訳ない。
PartialRenderer
が複雑でこのところつらかったので、意を決して手を入れることにした。
ビュー内部で誰かがrender
を呼ぶときにいろんな組み合わせのオプションが渡されるが、PartialRenderer
はそれらを一手に引き受けていたので、まずはいろんなシナリオを表にまとめてみた。
修正前はPartialRenderer
が❌も含めて全部やっていたので、ObjectRenderer
とCollectionRenderer
を切り出した。
同コミットより
「今までPartialRenderer
がoptions
で何でも受けられるようになってて組み合わせが爆発していたのを整理したということかな: render
にパーシャル名を渡す場合、コレクションを渡す場合、オブジェクトを渡す場合...みたいな」「render
にコレクションとオブジェクトを両方渡すとか全然意味わかんないし」「それが❌の場合か」「パーシャル名を渡す場合は普通にレンダリング、パーシャル名とコレクションを渡す場合はコレクション内のオブジェクトをeach
で回して云々、パーシャル名とオブジェクトを渡す場合はこう、コレクションだけを渡す場合はこう...というふうに上の表で整理したということですね」
「プルリクにも、options
ハッシュがいろんなケースに対応しすぎてたり使われない組み合わせをわざわざチェックしてたりしたみたいなことが書かれてますね↓」「そういう余分な処理を枝刈りしたということか」「こういうリファクタリングは全容を把握してる人じゃないと大変そう」「コミット数45は大きいですね」「これでいいんだろうかと首を傾げながら修正してそう」
名前でわかるように、
CollectionRenderer
はコレクションのレンダリングを担当し、ObjectRenderer
はオブジェクトのレンダリングを担当する。これで各クラスの実装がシンプルになって理解しやすくなった(し、最適化もしやすくなったと思いたい)。そのためにスタックを少々複雑にせざるを得ず、前述のoptions
ハッシュを分解してどのレンダラーで使うか決められるようにする必要もあった。
同コミットより
⚓lookup_store
の互換性が壊れていたのを修正
# activesupport/lib/active_support/cache.rb#L57
def lookup_store(store = nil, *parameters)
case store
when Symbol
options = parameters.extract_options!
retrieve_store_class(store).new(*parameters, **options)
+ when Array
+ lookup_store(*store)
when nil
ActiveSupport::Cache::MemoryStore.new
else
store
end
end
つっつきボイス:「これは@kamipoさんによる修正ですね」「lookup_store
って何だっけ?」「ああ、キャッシュストアに入ってるオブジェクトを引っ張ってくるのか」「Active Supportのキャッシュなんですね」
「lookup_store
は、シングルトンメソッド的に任意の箇所でキャッシュストアの内容を引っ張ってくるのね」「つまりこのメソッドはシングルトンだからどこからでも呼べる」「なるほど」「Railsでコンフィグされていればそれを取れるし、されてなければメモリストアが取れるみたいな」
「Railsでは、こういうグローバルコンテキストから持ってくるみたいな書き方ってあんまりしませんけど、何かで必要になったら使うのかも🤔」
⚓insert_all
がenumを型キャストしない問題を修正
# activerecord/lib/active_record/insert_all.rb#L178
def extract_types_from_columns_on(table_name, keys:)
columns = connection.schema_cache.columns_hash(table_name)
unknown_column = (keys - columns.keys).first
raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
- keys.index_with { |key| connection.lookup_cast_type_from_column(columns[key]) }
+ keys.index_with { |key| model.type_for_attribute(key) }
end
つっつきボイス:「insert_all
がenumで型キャストしない、そういえばそうなってたような覚えが🤔」「まだinsert_all
使ったことない」「これとかupsert_all
ってRails 6からでしたっけ?」「そうですね」
- API:
insert_all
(ActiveRecord::Persistence::ClassMethods) - APIdock - API:
upsert_all
-- ActiveRecord::Persistence::ClassMethods
「たぶんバグかな」「今まではinsert_all
でenumをサポートする気があんまりないのかと思ってました」「お?」「だってcreated_at
とかも作ってくれないですし」「あ〜そういうことか、insert_all
って結構挙動違うのかも」「もしかすると最新のRails 6のmasterでは作るのかもしれませんけど、少なくとも自分のプロジェクトではcreated_at
とかも全部書きましたし、そういうものなのかなと思ってました」「とりあえずAPIdockでinsert
を見た感じでは、created_at
とか設定しなさそうだけど🤔」「コールバックやバリデーションはトリガしないけど、enumをキャストしないとは書いてませんね」「どっちなんだろう」
単一のINSERT文で単一のレコードをインサートする。モデルはインスタンス化されず、Active Recordのコールバックやバリデーションもトリガされないが、渡された値はActive Recordの型キャストとシリアライズ処理を通る。
apidock.comより大意
「今回の修正の方向を今後も推し進めていったら、例のactiverecord_import gem↓とだんだん似てきたりして」「ありそう」「activerecord_importならやれるんだったかな...?あれはオブジェクト自体を渡すからやれると思います」「insert_all
ではオブジェクトじゃなくてハッシュを渡しますから」「activerecord_import gemは結構使ってきたけど、ほぼActive Recordと同じように使えましたし、特に困ることもありませんでしたね」「その代わりactiverecord_importはレコードの数だけインスタンスを作るから、困るとすればそこぐらいかなと」
「activerecord_importでActive Recordのバリデーションをスキップしてもスピードが足りなくなったときに、Active Recordを使うのを諦めるという選択肢を取ったことありましたよ」「insert_all
を使いたい場面ってだいたいパフォーマンスと隣り合わせのタイミングになってるはずだし」「Active Recordを使うのを諦めたときは、ああユニケージのアプローチは正しかったんだなって思いましたし」「ユニケージということは私に振ってます?」「つまりオブジェクトを作るとか無駄なことするより、テキスト処理でズゴっとやるのが一番速いなと」「まあ状況によってはそうかもしれませんね」「TSV作ってMySQLのトランザクションをオフにしてcopy fromで突っ込むと、ディスク読み出しと変わらないぐらい爆速になりましたし🚀」
⚓normalize_keys
を高速化
# actionpack/lib/action_controller/renderer.rb#L103
private
def normalize_keys(defaults, env)
new_env = {}
- defaults.each_pair { |k, v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
env.each_pair { |k, v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
+
+ defaults.each_pair do |k, v|
+ key = rack_key_for(k)
+ new_env[key] = rack_value_for(k, v) unless new_env.key?(key)
+ end
+
new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
new_env
end
RACK_KEY_TRANSLATION = {
http_host: "HTTP_HOST",
https: "HTTPS",
method: "REQUEST_METHOD",
script_name: "SCRIPT_NAME",
input: "rack.input"
}
- IDENTITY = ->(_) { _ }
-
- RACK_VALUE_TRANSLATION = {
- https: ->(v) { v ? "on" : "off" },
- method: ->(v) { -v.upcase },
- }
def rack_key_for(key)
RACK_KEY_TRANSLATION[key] || key.to_s
end
def rack_value_for(key, value)
- RACK_VALUE_TRANSLATION.fetch(key, IDENTITY).call value
+ case key
+ when :https
+ value ? "on" : "off"
+ when :method
+ -value.upcase
+ else
+ value
+ end
end
end
つっつきボイス:「1.24倍速くなってますね」「何のキーだろう?」「コントローラがリクエストするときのキーとかそのあたりかな🤔」「rack_value_for
があるからRackとかenv
がらみっぽい」「プルリク↓に書いてあるように、毎回defaults.each_pair
で全部引っ張ってたら遅いから、先にenv.each_pair
してからdefaults.each_pair
で必要なものだけ設定するように修正したということか」「なるほど」
このPRでは以下の2つを行う:
*defaults
をすべて新しい環境ハッシュに設定してからenv
のエントリでオーバーライドするのをやめて、env
の値をすべて設定した後は既に設定済みのdefaults
の値の設定をスキップする。
*case
文でlambdaのハッシュを切り替える
同PRより大意
⚓ドキュメント修正
- PR: Update doc for #pluck to use non-deprecated syntax by stevenjackson · Pull Request #38774 · rails/rails
- PR: Fix confusing wording in Asset Pipeline guide [ci skip] by rmacklin · Pull Request #38782 · rails/rails
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "DATEDIFF(updated_at, created_at)". Non-attribute arguments will be disallowed in Rails 6.1. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql().
つっつきボイス:「1つ目は、pluck
のAPIドキュメントの書き方が古くて、そのとおりにしたらwarningが表示された↑ということみたいです」「ああなるほど、pluck
に直接文字列を渡したらいかんと🚫」「Arel.sql
を通しなさいと」「へ〜、pluck
にも文字列渡したらダメなのか」「order
とかに文字列渡してはいけないというのが入ったのは何となく覚えてますけどいつだったかな〜?」「同じぐらいのタイミングでpluck
もそうなった気がする」「別々に対応する理由もなさそうですし」「とにかくSQLインジェクション対策のためにはArel.sql
を使う必要がありますね」
# activerecord/lib/active_record/relation/calculations.rb#L177
- # Person.pluck('DATEDIFF(updated_at, created_at)')
+ # Person.pluck(Arel.sql('DATEDIFF(updated_at, created_at)'))
- API:
sql
-- Arel
後で調べるとRails 6から文字列を渡せなくなったんですね↓。
# guides/source/asset_pipeline.md#L44
Using the `--skip-sprockets` option will prevent Rails from adding
-them to your `Gemfile`, so if you later want to enable
-the asset pipeline you will have to add those gems to your `Gemfile`. Also,
+this gem, so if you later want to enable the asset pipeline
+you will have to add it to your `Gemfile` manually. Also,
creating an application with the `--skip-sprockets` option will generate
a slightly different `config/application.rb` file, with a require statement
for the sprockets railtie that is commented-out. You will have to remove
the comment operator on that line to later enable the asset pipeline:
「2つ目はアセットパイプラインのガイドの文面がいろいろイマイチだったので修正したということだそうです↑」「修正も英作文レベルみたい」「ついにCoffeeScriptの記述も消されてる」「さらばCoffeeScript」
⚓Rails
⚓Webpacker 5.0がリリース(RubyFlowより)
- 元記事: Webpacker 5.0 released
- リポジトリ: rails/webpacker: Use Webpack to manage app-like JavaScript modules in Rails
必要な最小バージョンがNode.js 10.13.0、Rails 5.2、Ruby 2.4になりました。
つっつきボイス:「Webpackの現在のバージョンは4.42.1ですし、WebpackerはWebpackとバージョン合わせる気なさそう」「Webpackも頑張って更新しないといけないうえにWebpackerまで気にしないといけないのって、どうもね...」「Webpackerの5を見た感じでは、必要なRubyやRailsやNodeのバージョンが上がったぐらいで、そんなに大きく変わってなさそうでした」「Multiple files per entryってどういう感じなのかな?🤔」「ファイル名が同じjsやcssごとにバンドルするようになったということのようで、以下で言うとhome.jsとhome.cssは同じhomeにバインドされるということみたいです」
# app/javascript/packs
accounts.js
application.js
home.js
accounts.css
home.css
「extract_css
について書かれてるけど、そもそもextract_css
が何をするのかを知らないと意味わからないでしょうね」「Webpackerのオプション以前にWebpackのプラグインとしてcss extract的なものがあるんですよ」「あ、そういうことですか」「Webpackで使うプラグインまでRailsと密結合しにいくのって、それはそれでひとつの未来かもしれないけど、それってどうなのかな〜」
config/webpacker.ymlの
extract_css
オプションもtrueに設定しなければならない。
extract_css
は、出力ファイルをCSSパックごとに分割して生成するようWebpackに指示する。このオプションはdevelopment環境ではデフォルトでfalseなので、development環境でCSSバンドルを生成するには明示的にtrueに変更する必要がある。
同記事より
おそらく以下がそれのようです。
参考: webpack-contrib/mini-css-extract-plugin: Lightweight CSS extraction plugin
⚓Webpackerのあり方
「もしかするとRailsとしてはそういう方向に持っていきたいのかも: Railsとして推奨するWebpackプラグインをバンドルして、みんなこれを出発点にしてくれみたいな」「それありそうですね」「Railsって元々そういうところありますし、レールを敷きたいわけだし」「今まで使われてきたSASSがWebpackerでデフォルトで入っているあたりにそれを感じますね」「そうそう、Railsが推奨するWebpackの機能は最初からバンドルして便利に使えるようにしとくから、という世界を目指している感じはちょっとある」
「そのレールがいい感じのレールになるなら、Rails専門エンジニアにとってはWebpackerでいいかという気持ちになれるかも」「実際その辺のこと考えたくないですし」「考えたくない」「ゴリゴリのフロントエンド案件ならともかく、管理画面程度だったら、何を入れるかあれこれ考えるよりデフォルトの組み合わせでいこうぜみたいな」「よほど特殊なプラグインが組み込まれるとかでなければ」
「どっちにしろjavascript_pack_tag
とかは自分たちでやらないといけませんし、manifest.jsonまでつながる何かを一気通貫で用意しとかないといけないというのは、そのとおりだと思います」「そのあたりが事前に決まっていれば細かいエラーに遭わなくて済みますし」「その分フロントエンドエンジニアにはキラワレそうですけど」「まあWebpackerは剥がせるようになってますから」「たしかに」
⚓ViewComponent: GitHubのViewComponent(Ruby Weeklyより)
- リポジトリ: github/view_component: View components for Rails
- デモリポジトリ: joelhawksley/view-component-demo: Rails application with ViewComponent
ViewComponentの設計哲学: 「驚き最小の原則」に従ってRailsへのシームレスな統合を目指す
同リポジトリより
ViewComponentは、React Componentsにインスパイアされたビューレンダリングクラスであり、データを受け取って出力安全なHTMLを返す。PresenterやDecoratorやViewModelパターンの進化系と思えばよい。
コンポーネントは、ビューのコードが再利用されるほとんどの場面で効果を発揮し、直接テストできるというメリットもある。
同リポジトリより
ViewComponentは、次に取り上げる「3rd-party component framework」とも互換性を保つそうです。
以下の動画が資料として紹介されていました。
つっつきボイス:「GitHubがガンガン使っているというViewComponentと、次の3rd-party component frameworkについて見落としてたので、ViewComponentがどういうものなのかとりあえず上に軽くまとめました」「文字どおりビューのコンポーネントか: inspired by React Componentとあるぐらいだから、Reactと同じぐらいのコンポーネント粒度ということなのかな」「こういうふうに↓render
にコンポーネントを書いて使うと」「なるほど」
<!-- 同リポジトリより -->
<%= render(ModalComponent.new) do |component| %>
<% component.with(:header) do %>
Hello Jane
<% end %>
<% component.with(:body) do %>
<p>Have a great day.</p>
<% end %>
<% end %>
「ViewComponent、入れるのには相当抵抗あるけど、もしかするといいものなのかもしれない」「ビューをコンポーネント単位で単体テストしたいというのが開発の動機だったのね」「たしかにこうなっていればコンポーネント単位で試験できる: フロントエンジニアはこういうのをフロントでコードを書いてテストするけど、同じことをRailsのレイヤでやろうとするとこうなるでしょうね」「やろうとしてることは理解できるけど、これを導入するのは勇気が要るというか、フロントエンドに戻れなくなりそうではありますね」「導入するなら今後すべてRailsでやるという不退転の決意が必要ということになりそう」
「Reactにインスパイアされたんだったら、ERBじゃないスタイルにして欲しかったなんて思ったり」「まあERB以外でもできるみたいだし」「content_tag
とかtag.div
とか書く↓みたいですけど、書きたくないというか、ここに生HTML書けるならワンチャンあるかなと思ったり」「プロジェクトメンバーが全員Railsエンジニアで、フロントエンドにあんまり興味ないという編成なら、ありかも」「GitHubはそういう立ち位置なんでしょうね」
# 同リポジトリより
class TestComponentPreview < ViewComponent::Preview
def with_default_title
render(TestComponent.new(title: "Test component default"))
end
def with_long_title
render(TestComponent.new(title: "This is a really long title to see how the component renders this"))
end
def with_content_block
render(TestComponent.new(title: "This component accepts a block of content") do
tag.div do
content_tag(:span, "Hello")
end
end
end
end
Q: ERB以外のテンプレート言語も使えるか?
A: ERB、haml、slimでテスト済みだが、ほとんどのRailsテンプレートハンドラーをサポートしているはず。
同リポジトリより
「おそらくGitHubはプロダクトが大きくなりすぎて、JSでテスト回すのがつらくなったのかも: ViewComponentならそれだけ読み込めばテストできるけど、フロントだとひととおり全部読み込まないとテストできないものが多いとか🤔」「次のトピックでそこに言及されてました↓」
⚓Rails 6.1で入る「3rd-party component framework」とViewComponent
Rails 6.1で入る「3rd-party component framework」機能に今頃気づきましたが、これも主にViewComponentのためのようです。以下の2つのPRは昨年のです。
- PR: Introduce support for 3rd-party component frameworks by joelhawksley · Pull Request #36388 · rails/rails
- PR: Render objects that respond_to render_in in controllers by joelhawksley · Pull Request #37919 · rails/rails
このプルリクでは、ViewComponentを含む「3rd-party component framework」のサポートが導入される。
GitHubには4000テンプレートがあるため、Railsビューで以下のつらみがある:
* テストがつらい: 現在のRailsではビューのテストを結合テストかシステムテストでやることを推進しているが、そのためビューだけをテストすればよいというわけにいかず、ルーティングやコントローラ層のオーバーヘッドがあるためにビューのフルテストがつらいことになっている。それによって同じパーシャルがビューごとに何度もテストされるので、ビューをDRYにしたメリットが帳消しになってしまう。
* カバレッジ: ビューのカバレッジが多くのRubyコードで正しく扱われていないためにテストの監査が難しく、テストスイートとのギャップが開いている。
* データフロー: ビューでは、オブジェクトでのメソッド宣言と異なり、受け取ることを期待する値が宣言されない。そのため、レンダリングに必要なコンテキストを判定するのが難しくなり、1つのビューを複数のコンテキストで使い回すと微妙なバグをしょっちゅう踏むようになる。
* 標準的なRubyコードでもつらい: GitHubのビューは、Rubyクラスで期待される標準的なコード品質であっても、ほとんどがメソッドが長いだの条件ネストが深いだのでfailする。
同PRより大意
ViewComponentのメリット:
* ビューを単体テストできる。単体テストならだいたい25ミリ秒、結合テストでも最大6秒。
* カバレッジ: 少なくともカバレッジツールと一部互換性があり、SimpleCovでは一部うまくいっている。
* データフロー: コンポーネントのレンダリングに必要なコンテキストを明確に定義できるので、パーシャルよりも再利用が楽になった。
同PRより
つっつきボイス:「GitHubのビューテンプレートが4000超えてて、テストが重くてつらくてしょうがなかったそうです」「上の『ルーティングやコントローラ層のオーバーヘッドがあるためにビューのフルテストがつらいことになっている』とか、きっとフロントエンド勢から『フロントとAPIの構成にしとけばよかったのに、密結合してるからそういうことになるんじゃぁ』って言われそう」「『そんな無理しなくてもFirebaseでも使えば、フロントエンドでテスト書いてテストできるよ』って言われたりして」
「カバレッジを改善したいという意図、理解できる」
「まあRailsのビューにもうひとつ別のソリューションが入ることは悪くないと思いますね」「言えてる」「3rd-party component frameworkでやれば新しい言語覚えないで済むし」「ただGitHubがもし仮に最初からやり直せるとしたら、果たしてViewComponentを選んだだろうかって思ったり」「それ」「歴史的な理由でこれになったんじゃないかと」
「もしかすると3rd-party component frameworkって、いわゆるActiveとかActionが名前に付かないコンポーネントを導入できるという意味なんだろうか??」「今でもgemを使えば入れられますし」「そういえば何が違うんだろう?」「そういう位置づけは詳しく見ないとわからないな〜」
「とりあえず#36388の『いいね👍』数がめちゃくちゃ多いし期待されてそうではありますね」「Railsの最大手ユーザーのひとつであるGitHubが使ってるから、という勢いで押されてたりして」「サードパーティといいつつ今のところGitHubぐらいしかなさそうですけど」「とりあえずViewComponentそのものは、コンポーネント単位でテストできますし、自分は割とキライじゃないですね👍」「今の世の中でスクラッチからRailsプロジェクトを立ち上げるときに使うかというと、ちょっと考えますけど」
「以下もViewComponent的なものらしいです↓」「コンポーネントを組み合わせてビューを作るという考え方は、それこそいにしえの昔からあるヤツですね: それこそPHPでSymfonyのバージョン0.x系使ってた頃から、コンポーネントを作ってその中にコンポーネントスロットを作ったりとか、そういう名前でありましたし」「いわゆるビューモデルというヤツ」「概念としては新しくない」「まあそんなにキレイに作れるかどうかはまた別」
⚓🌟Active Record Doctor: ARの問題を診断🌟(Ruby Weeklyより)
Active Record Doctorでやれること:
- インデックス化されてない外部キーのインデックス化
- 不要不急なインデックスを検出する
- 外部キー制約付け忘れを検出する
- 未定義テーブルを参照しているモデルを検出する
- uniqueインデックスがないuniquenessバリデーションを検出する
- non-NULL制約付け忘れを検出する
- 存在バリデーション付け忘れを検出する
- booleanカラムに誤って付けられた存在バリデーションを検出する
つっつきボイス:「Active Record周りをチェックしてくれるのね」「なるほど」「これは何も考えずに入れておいていいgemかな👍」「CIに入れてもよさそうですね」「指摘もらって、それが正しいかどうか確認するだけでも意義ありそう」「単にやり忘れてたとか、そのうちやるつもりでそのままになってたなんてことはいつでもありますし」「外部キーを付けることも面倒で忘れやすい」「こういうのに怒られたらしょうがないという気持ちになれますし」
「uniquenessバリデーションあるのにuniqueインデックスが張られてないって」「ありがち」「もう正しさしかない」「う、やっちゃってるかも」「モデルのバリデーションって、一種気休めというか、本質的じゃないですし」「uniquenessチェックで毎回SELECTするのにuniqueインデックスないのはヤバい」「本当に信じられるのはunique制約エラーぐらい: create_or_find_by
というメソッドがRailsに生えてるぐらいですし」「下手するとそこでINSERTが詰まる」
久しぶりに🌟を進呈いたします。おめでとうございます🎉。
⚓Facadeパターンでパフォーマンスとメンテナンス性を改善(Ruby Weeklyより)
# 同記事より
module Books
class IndexFacade
attr_reader :books, :params, :user
def initialize(user:, params:)
@params = params
@user = user
@books = user.books
end
def filtered_books
@filtered_books ||= begin
scope = if query.present?
books.where('name ILIKE ?', "%#{query}%")
elsif isbn.present?
books.where(isbn: isbn)
else
books
end
scope.order(created_at: :desc).page(params[:page])
end
end
def recommended
# ネストしたfacadeがここにある。
# ビューの`Recommended Books`の責務は1つなので
# これを切り出すことでカプセル化とテストしやすさが改善される
@recommended ||= Books::RecommendedFacade.new(
books: books,
user: user
)
end
private
def query
@query ||= params[:query]
end
def isbn
@isbn ||= params[:isbn]
end
end
end
つっつきボイス:「普通のFacadeパターンかなと思いつつ」「普通にFacadeパターンですね」
「Facadeって、GoFのデザインパターンの中でも『これってパターンというほどのものかしら、ただの切り出しでは?』という気持ちになりますね」「『ここはFacadeパターンでやりました』とか言うとスゴいことやってるような響きありますけど」「オブジェクト指向というほどでもない感」
⚓その他Rails
- 元記事: RuboCoping with legacy: Bring your Ruby code up to Standard — Martian Chronicles, Evil Martians’ team blog 現在進行系はRuboCoppingが正しいのかな?
つっつきボイス:「『ロード・オブ・ザ・リング』のセリフなどをいろいろもじってたのが楽しかったので」「普通にRuboCopでレガシーコードと戦う記事💣」「3306 files inspected, 12418 offenses detected
とか見るとドキドキする」
「Todo or not Todo」「You shall not passはガンダルフの『ここは通さぬ!』↓ですね」
つっつきボイス:「*_previously_changed?
きたー」「dirtyってどこまで使えるのかドキドキしちゃう」「from: nil, to: "Tesla"
とか書けるようになるとは」
# 同記事より
car = Car.new
car.changed? # => false
car.company = "Tesla"
car.changed? # => true
car.company_changed? # => true
car.company_changed?(from: nil, to: "Tesla") # => true
「何のpreviousなんだろ?」「値がnil
から"Tesla"
に変わったということか」「dirty絡みっていろんなメソッドがあって覚えにくい」「changed?
は保存するとfalseに変わるようになったんですね↓」「サンプルコードでfrom:
とto:
付けても付けなくてもbooleanが同じだと違いがわからん」「ちょい見づらい」「reload
するとクリアされるということか」「reload
に対応するのは無理そうかな」
# 同記事より
car.save
car.changed? # => false
car.company_changed? # => false
car.reload
car.company_previously_changed? # => false
car.company_previously_changed?(from: nil, to: "Tesla") # => false
WSL2移行、お手伝いしてるRailsプロジェクトの開発してるが致命的な問題はなさそう。「どうにかしてくれよ」と思うのは localhost 以外で hosts に 127.0.0.1 に名前振ってもWSL2にフォーワードされない上に、Hyper-V 既知のバグ(仕様?)通り、IPが固定できないこと。
— masa寿司 (@masa_iwasaki) March 26, 2020
「自分はDocker for Windowsは普通に使う分には今のところそんなに苦労してないかな〜」
『#Railsチュートリアル の歩き方』解説動画 #YouTube から公開しました! 🚀🆕
これまではスライドのみを公開していましたが、動画版も追加された形になります 👨🏫📹
背景や見所などをまとめた #note を @Yuppyhappytoyou さんに書いてもらったので、よければぜひぜひ 😉✨ https://t.co/xFlzQXURqP https://t.co/jFdaeKjQSS
— 安川要平/Yohei Yasukawa (@yasulab) March 26, 2020
「チュートリアルにさらに解説動画があるという」「Railsチュートリアル大きいから」「こうやって裾野が広がっていくのはいいですね👍」
前編は以上です。
バックナンバー(2020年度第1四半期)
週刊Railsウォッチ(20200317後編)Strangler Figパターンでリファクタリング、ペアプロ実践記事、イミュータブルデータモデルほか
- 20200316前編 Webpackerの対抗馬Simpackerはいかが、Hanami::APIは高速性をフィーチャー、N+1と戦うgemほか
- 20200310後編 Flutter+Firebaseでモバイルアプリ開発、命名7つの鉄則、Rubyバージョンを切り替えるchruby gemほか
- 20200309前編 Webpackerに乗り換えるべき理由25、Railsのindex_byとindex_withは有能、GCPはやっぱりスゴいほか
- 20200303後編 Ruby 2.7で引数のruby2_keywordsフラグを確認する、fake_apiでAPIプロトタイプ、groupdateで日付をグルーピングほか
- 20200302前編 RubyKaigi 2020は9月に延期、Railsのセキュリティパッチバージョニングが変更、dry-monadsほか
- 20200226後編 dry-rbを使うべき理由、最近のRubyオンライン教材、AWSから乗り換えた話ほか
- 20200212後編 Rubyistが解説するUnicodeとUTF-8、Sorbetが速い理由、CSSの歴史、2019年の脆弱性まとめほか
- 20200210前編 Railsのベンチマークジェネレータ、長いバックグラウンドジョブと戦う、Timestamp切り詰めの謎、Open APIツールほか
- 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など)です。