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