Slide 1

Slide 1 text

Rails Good Parts, Bad Parts @willnet

Slide 2

Slide 2 text

自己紹介 » 前島真一 aka @willnet or @netwillnet » ginza.rb から来ました » メドピアさんで技術顧問しています » https://github.com/willnet » https://twitter.com/netwillnet » https://blog.willnet.in

Slide 3

Slide 3 text

技術顧問として 主に負債を減らしたり、負債の増加を防ぐために頑 張っています !

Slide 4

Slide 4 text

技術顧問について詳しく知りたい方は こちらをどうぞ » Rails Developers Meetup で喋った » https://speakerdeck.com/willnet/ji-shu-gu- wen-toiudong-kifang » ブログ書いた » https://blog.willnet.in/entry/ 2018/04/09/101808

Slide 5

Slide 5 text

今日のテーマは技術的負 債 !

Slide 6

Slide 6 text

負債へのアプローチは2 つ

Slide 7

Slide 7 text

できてしまった負債を減 らす⬇

Slide 8

Slide 8 text

新規開発で負債を増やさ ない⬆ !

Slide 9

Slide 9 text

今日は負債を増やさない 話をします

Slide 10

Slide 10 text

負債の増加を防ぐにはど うしたらよいか

Slide 11

Slide 11 text

Railsのレールに乗る

Slide 12

Slide 12 text

レールに乗る、とは? » みんなよく言ってるけどふわっとした概念 » レールについてきちんと説明している文章がない ように見える

Slide 13

Slide 13 text

Railsが提供しているべんりな機能を活 用する = レールに乗る ここではこういう定義とします

Slide 14

Slide 14 text

Railsのべんりな機能 » たくさんある » こういうメソッドないかな?と思って調べると大 抵定義済み

Slide 15

Slide 15 text

べんりな機能を知らずに スクラッチで実装して微 妙な感じになるケースが よくある !

Slide 16

Slide 16 text

べんりな機能の具体例 » あまり知られていない&&知ってると便利なもの » 複数のお手伝い先で何回も言ってるやつ

Slide 17

Slide 17 text

has_many

Slide 18

Slide 18 text

みんな知ってる

Slide 19

Slide 19 text

定義することで使えるよ うになる機能がたくさん ある

Slide 20

Slide 20 text

has_manyで使えるようになるものたち collection collection<<(object, ...) collection.delete(object, ...) collection.destroy(object, ...) collection=(objects) collection_singular_ids collection_singular_ids=(ids) collection.clear

Slide 21

Slide 21 text

has_manyで使えるようになるものたち collection.empty? collection.size collection.find(...) collection.where(...) collection.exists?(...) collection.build(attributes = {}, ...) collection.create(attributes = {}) collection.create!(attributes = {}) collection.reload

Slide 22

Slide 22 text

全種類知ってますか?

Slide 23

Slide 23 text

collection=(objects), collection_singular_ids=(ids) » 既存のcollectionをいい感じに置き換える » has_many through の場合は中間テーブルを置き 換える

Slide 24

Slide 24 text

合わせ技でつかえるview helper » collection_check_boxes これらをスクラッチで書いてしまう人めっちゃ多い (当社比)

Slide 25

Slide 25 text

コード例 ビールの銘柄にタグ付けをするコードを考えてみま す

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

modelはこんな感じ class Beer < ApplicationRecord has_many :taggings has_many :tags, through: :taggings end

Slide 28

Slide 28 text

素直に書くと <% Tag.all.each do |tag| %> <%= form.label tag.name do %> <%= check_box_tag 'beer[tag][id][]', tag.id, beer.tags.find { |t| tag.id == t.id } %> <%= tag.name %> <% end %> <% end %>

Slide 29

Slide 29 text

素直に書くと def update @beer = Beer.find(params[:id]) @beer.attributes = beer_params original_taggings = @beer.taggings taggings_ids = params[:beer][:tag][:id] delete_taggings = original_taggings.reject { |bt| taggings_ids.include?(bt.tag_id.to_s) } delete_taggings.each(&:destroy) add_tags = taggings_ids.reject { |id| original_taggings.map(&:tag_id).include?(id.to_i) } add_tags.each do |tag_id| @beer.taggings.build(tag_id: tag_id) end if @beer.save redirect_to @beer, notice: 'Beer was successfully updated.' else render :edit end end private def beer_params params.require(:beer).permit(:name) end

Slide 30

Slide 30 text

一瞬では読めないです ね… !

Slide 31

Slide 31 text

既存のタグと入力値との 差分を見て、必要なもの だけinsert, deleteして いる

Slide 32

Slide 32 text

読みづらいしバグも入り 込みやすそう

Slide 33

Slide 33 text

便利メソッドたちを使うと <%= form.collection_check_boxes :tag_ids, Tag.all, :id, :name %>

Slide 34

Slide 34 text

便利メソッドたちを使うと def update @beer = Beer.find(params[:id]) if @beer.update(beer_params) redirect_to @beer, notice: 'Beer was successfully updated.' else render :edit end end private def beer_params params.require(:beer).permit(:name, tag_ids: []) end

Slide 35

Slide 35 text

普通に書ける beer.tag_ids = params[:beer][:tag_id] » has_many :tagsでtag_ids=メソッドが生えてい る » いい感じに差分を見て中間テーブルをinsert, deleteしてくれる

Slide 36

Slide 36 text

これ、初めて知った人 ✋

Slide 37

Slide 37 text

どうやってべんりな機能を知るのか » 公式のドキュメントやRailsガイドを読みましょ う » もしくは強い人にレビューやペアプロしてもらい ましょう

Slide 38

Slide 38 text

ここまでの話をまとめる と

Slide 39

Slide 39 text

Railsが提供するべんり な機能を使えば負債を作 らずに開発できる!

Slide 40

Slide 40 text

なんですけど…

Slide 41

Slide 41 text

Railsが提供している機能が全部無条件 に便利というわけではない » 安易に使うとやけどする機能もある » ググるといろいろでてくるはず » callback » default_scope » nested attributes

Slide 42

Slide 42 text

gemも似たように、安易に採用すべきで はないものがある » devise » simple_form » activeadmin » etc

Slide 43

Slide 43 text

この手のやつ、どう取り扱うべきか » チーム開発のときは特に慎重になったほうが良い » 禁止にしておいたほうが無難なことも多い » 利用シーンやチームの状況によって使えることも あるので、できれば吟味して決めたい

Slide 44

Slide 44 text

例えばwebpacker » 最近よくdisられている » しかしフロントエンド専任がおらず、片手間でjs を書く&&とりあえずes6使いたい、というケース だと大変便利 » フロントエンド専任がいて、webpackの設定をち ゃんとしたい、というケースでは必要ない

Slide 45

Slide 45 text

例えばdevise » 昔からよくdisられている » devise wayから外れるとつらい » 管理画面だけ認証が必要、などdevise wayで問題 ないならサッと導入できて便利

Slide 46

Slide 46 text

要注意なものは » なぜ注意が必要なのか » どう避けるか » どういうときなら使ってもよいのか を把握してまとめておくと良い

Slide 47

Slide 47 text

例えばhas_manyのcollection<<は要注 意 class User has_many :posts end これはイマイチな書き方 user.posts << Post.new(title: 'hello world!')

Slide 48

Slide 48 text

なぜか collection<<は、レシーバのオブジェクトがDBに 保存済みか否かで挙動が異なる(クエリが発行され たり発行されなかったりする)

Slide 49

Slide 49 text

どう避けるか user.posts.build(title: 'hello world!') user.posts.create(title: 'hello world!') のように書いたほうが可読性が高く、事故りにくい

Slide 50

Slide 50 text

どういうときなら使ってもよいのか collection.build や collection.createが適切 でない、かつチームメンバー全員が挙動を理解して いればギリギリOKかと tag = Tag.create(name: 'Ϗʔϧ') Beer.each { |beer| beer.tags << tag }

Slide 51

Slide 51 text

(こうも書けるのであんまり例が良くな い) tag = Tag.create(name: 'Ϗʔϧ') Beer.each { |beer| beer.taggings.create!(tag: tag) }

Slide 52

Slide 52 text

このように » なぜ注意が必要なのか » どう避けるか » どういうときなら使ってもよいのか を把握してチーム内で共有したい

Slide 53

Slide 53 text

負債を作らないために は、負債になりそうな要 素の対応法をみんなが理 解している必要がある

Slide 54

Slide 54 text

少なくとも、レビューで 負債になりそうな要素を 止められるようにしてお きたい

Slide 55

Slide 55 text

負債を作らないイコール 社内教育を頑張る

Slide 56

Slide 56 text

メドピアでは » 社内読書会 » ペアプロ » ふりかえり会 などしています

Slide 57

Slide 57 text

ところで、さっきの例は 簡単すぎ

Slide 58

Slide 58 text

現実ではもっと判断に悩 むケースが多い

Slide 59

Slide 59 text

判断に悩む例: コールバックをどう回 避するとよいか? » フォームオブジェクト? » サービスクラス? » その他 ↑方針を決めたとして、具体的にどうやって作ると いいの?

Slide 60

Slide 60 text

なるべく具体的に「こう だ!」と道を示さない と、それぞれ思い思いの 実装になってそれが負債 につながる

Slide 61

Slide 61 text

しかし選択するのが難し い

Slide 62

Slide 62 text

そこで clean-rails.org ですよ

Slide 63

Slide 63 text

可読性の高いRailsのコ ードを議論するコミュニ ティ

Slide 64

Slide 64 text

どのように実装するとよ いか判断に悩むときに相 談できる

Slide 65

Slide 65 text

皆様からの投稿お待ちし ています !

Slide 66

Slide 66 text

まとめ » 負債を作らないためには、べんりな機能、要注意 な機能を知ることが大事 » 要注意なものについて、チーム全体で理解できる ように詳細を詰めて周知する » 勉強と教育をがんばりましょう

Slide 67

Slide 67 text

判断に悩むものは一緒に 勉強していきましょう