Rails 6 Upgrade "Practical" Guide
by
megane42
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
Rails 6 Upgrade "Practical" Guide megane42 / Hikaru Kazama @ giftee 2020/01/30 gotanda.rb #41 @ Mobile Factory
Slide 2
Slide 2 text
自己紹介 • @megane42 • Rails 歴 1 年半 • giftee • 趣味 : かっこいい ワンタイムパスワード集め
Slide 3
Slide 3 text
ちょっと宣伝 • 個人開発 NIGHT #3 やります! • 2020/02/06(木) 19:30 - • giftee @ 東五反田 • https://giftee.connpass.com/event/ 164484/ • 社内有線を作った話をします(予定)
Slide 4
Slide 4 text
アジェンダ • 実践的な更新手順 • 変更点 25 本ノック • 5.2.4 -> 6.0.2 • キャッチーなやつだけ紹介していきます
Slide 5
Slide 5 text
実践的な更新手順
Slide 6
Slide 6 text
基本的な流れ • https://qiita.com/jnchito/items/ 0ee47108972a0e302caf/
Slide 7
Slide 7 text
感想 「カバレッジが高いからといって…」 と思っていた時期が私にもありました (カバレッジ 69%) カバレッジが大正義
Slide 8
Slide 8 text
仕方ないので・・・ https://edgeguides.rubyonrails.org/ 6_0_release_notes.html リリースノートを地道に読んだ
Slide 9
Slide 9 text
リリースノートを読むコツ • リリースノートに対応する PR を見に行く • テストコードを読む • メソッドの前の doc コメントを読む • その PR に含まれる CHANGELOG を見る (サンプルコード付きで説明が載っていると きがある)
Slide 10
Slide 10 text
リリースノートを読むコツ • すべてを理解しようとしない • Removals, Deprecations に関しては、 git grep してヒットしなければ深追いしない • 自動テスト、手動テストを信じて次に進む • 後日、念のため `DEPRECATION WARNING` で ログを検索するといいかもしれない
Slide 11
Slide 11 text
共有 • 今後他のチームの役に立つかなと思って Slack チャンネルを作ってメモを残した
Slide 12
Slide 12 text
変更点 25本ノック
Slide 13
Slide 13 text
ActionDispatch:: HostAuthorization • DNS リバインディング対策のために、新しい rack middleware が導入された • DNS リバインディングとは : https://qiita.com/kidach1/ items/1a3d66abb80bb67e0d64 • ユーザーに罠サイトを表示させたあと、罠サイトのドメ インの A レコードを攻撃対象サイトの IP に向け変える ことで、罠サイトの JS を攻撃対象サイトに向けて実行さ せる 1/25
Slide 14
Slide 14 text
ActionDispatch:: HostAuthorization • ホスト名のホワイトリストを Rails.application.config.hosts に追加できる • development では全 IP アドレスと localhost がデフォルトで許可済み • 他の環境ではデフォルトで未設定 = 全許可 なので、取り急ぎ作業は不要 1/25
Slide 15
Slide 15 text
rails routes —expanded • `-g キーワード` で絞り込みも可能 root@670934a4e388:/app# rails routes --expanded -g user --[ Route 1 ]---------------------------- Prefix | new_admin_user_session Verb | GET URI | /admins/sign_in(.:format) Controller#Action | admins/sessions#new --[ Route 2 ]---------------------------- Prefix | admin_user_session Verb | POST URI | /admins/sign_in(.:format) Controller#Action | admins/sessions#create 2/25
Slide 16
Slide 16 text
rails db:prepare • 新コマンド • データベースが無かったら db:setup する • データベースがあったら db:migration する • bin/setup でも早速使われている 3/25
Slide 17
Slide 17 text
rails db:seed:replant • 新コマンド • テーブルからデータだけを消しつつ、 seed を再度流し込んでくれる • 従来の方法 (rails db:setup db:seed) だと、 テーブル構造まで作り直しになってしまう 4/25
Slide 18
Slide 18 text
ActionDispatch::Request:: Session#dig session[:user] = { id: 1, icon: “http://example.org/nyancat.jpg” } # ͜Ε·Ͱ session[:user][:icon] # ࠓ͔Β͜͏ॻ͚Δ session.dig(:user, :icon) • session を dig できるようになった 5/25
Slide 19
Slide 19 text
ActiveRecord::Relation #extract_associated • スコープで絞り込みつつ、その関連だけを 取ってこれる Post.active.extract_associated(:comments) => [ #, #, # ... ] 6/25
Slide 20
Slide 20 text
ActiveRecord::Relation #annotate • なんかの調査時に役立ちそう Post.annotate("this is a comment”) .where(id: 123) .to_sql # => SELECT “posts”.* FROM “posts" WHERE "posts"."id" = 123 /* this is a comment */ 7/25
Slide 21
Slide 21 text
ActiveRecord::Relation #destroy_by / #delete_by • ありそうでなかった # ͜Ε·Ͱ Post.where(id: [1,2]).destroy_all # ࠓ͔Β͜͏ॻ͚Δ Post.destroy_by(id: [1,2]) 8/25
Slide 22
Slide 22 text
ActiveRecord::Relation #pick • ユースケースがピンポイントすぎるw # ͜Ε·Ͱ Person.where(id: 1).limit(1).pluck(:name).first # ࠓ͔Β͜͏ॻ͚Δ Person.where(id: 1).pick(:name) 9/25
Slide 23
Slide 23 text
ActiveRecord::Base .create_or_find_by/! • find_or_create_by と違って、レースコン ディション発生時にレコードが 2 つできない (DB にユニーク制約がかかっている前提) find したけど < 見つからないから > create してヨシ! 図. find_or_create_by 10/25
Slide 24
Slide 24 text
update_attributes/! の廃止 • update または update! を使いましょう 11/25
Slide 25
Slide 25 text
insert_all(!) / upsert_all • `activerecord-import` gem と違って、 ActiveRecord オブジェクトを生成しない • (+) より早い • (-) バリデーションやコールバックが実行さ れない 12/25
Slide 26
Slide 26 text
Enum から negative scopes が生えた • `not_xxx` が使えるようになった class Post < ActiveRecord::Base enum status: %i[ drafted active trashed ] end # ͜Ε·Ͱ Post.where.not(status: :drafted) # ࠓ͔Β͜͏ॻ͚Δ Post.not_drafted 13/25
Slide 27
Slide 27 text
where の中で endless range を使えるようになった • 生々しいクエリを書かなくて済む # ͜Ε·Ͱ Post.where(“id > ?”, 42) # ࠓ͔Β͜͏ॻ͚Δ Post.where(id: 42..) 14/25
Slide 28
Slide 28 text
クエリ結果の暗黙的な並び順 を設定できるようになった • `first` や `last` が何のカラムをベースに動く かを設定できるようになった。 なるほどなぁ〜 class Project < ActiveRecord::Base self.implicit_order_column = "created_at" end 15/25
Slide 29
Slide 29 text
マイグレーションで同名カラムを 作るとエラーになるようになった • エラーにならなかったのか・・・ 16/25
Slide 30
Slide 30 text
子がユニークじゃないときに 親を save したときの挙動が変わった • 下記を実行するとどうなるでしょう? (parent has_many children とする) parent = Parent.new(children: [ Child.new(name: ‘Wiske'), Child.new(name: ‘Wiske') ]) parent.save ユニーク制約違反 17/25
Slide 31
Slide 31 text
子がユニークじゃないときに 親を save したときの挙動が変わった • 5 以前 : 親と最初の子までは save される • 6 以降 : 親も子も save されない parent = Parent.new(children: [ Child.new(name: ‘Wiske'), Child.new(name: ‘Wiske') ]) parent.save ユニーク制約違反 17/25
Slide 32
Slide 32 text
Date, DateTime, Time, TimeWithZone #before? / #after? • 不等号が辛くなったら思い出してください # ͜Ε·Ͱ Date.new(2020, 1, 30) < Date.new(2020, 1, 31) # ࠓ͔Β͜͏ॻ͚Δ Date.new(2020, 1, 30).before?(Date.new(2020, 1, 31)) 18/25
Slide 33
Slide 33 text
Enumerable#index_with • これが役立つときに思い出せるかどうか… post = Post.new(title: "hey", body: "what's up?") [:title, :body].index_with do |attr| post.public_send(attr) End # => { title: "hey", body: "what's up?" } 19/25
Slide 34
Slide 34 text
Hash# deep_transform_values(!) • transform_values(!) は ruby にあるが、 ネストしていると意図した結果にならない hash = {a: 1, b: {c: 2} } hash.transform_values { |v| v.to_s } # => {:a=>"1", :b=>"{:c=>2}"} hash.deep_transform_values { |v| v.to_s } # =>{:a=>"1", :b=>{:c=>"2"}} 20/25
Slide 35
Slide 35 text
credentials.yml.enc • 長くなったのでまとめました https://qiita.com/megane42/items/ 539812678773c60b7c8a 21/25
Slide 36
Slide 36 text
その他 : ActiveRecord のもろもろ • ActiveRecord 周りの変更 3 点について kamipo さん自ら解説した記事 https://blog.kamipo.net/entry/2019/05/ 15/152652 22/25
Slide 37
Slide 37 text
その他 : メジャーどころ • Webpacker 標準化 • ActionText • Zeitwerk (a.k.a. Z-loader) • https://qiita.com/alfa/items/3a432c31346a705d0690 • ちなみに Rails 6.0.2 だと `rails zeitwerk:check` がコケます 25/25
Slide 38
Slide 38 text
No content
Slide 39
Slide 39 text
Rails 6 Upgrade "Practical" Guide megane42 / Hikaru Kazama @ giftee 2020/01/30 gotanda.rb #41 @ Mobile Factory