Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Rails Good Parts, Bad Parts
Search
Shinichi Maeshima
September 12, 2018
Technology
7
14k
Rails Good Parts, Bad Parts
「MedBeer -Rails開発での技術的負債との付き合い方」での発表資料です
Shinichi Maeshima
September 12, 2018
Tweet
Share
More Decks by Shinichi Maeshima
See All by Shinichi Maeshima
Sidekiq vs Solid Queue
willnet
14
11k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
6
1.4k
Exceptional Rails
willnet
6
7.1k
Breaking the Flaky Test Cycle
willnet
2
2k
mrskで広がるインフラの選択肢
willnet
1
1k
アプリケーションを長期にわたって無理なく運用するためのたったひとつの方法
willnet
2
2.1k
HotwireからDHHが考えるこれからのRailsとJSの付き合い方を知る
willnet
14
13k
Rails6.1で新しく入る機能について
willnet
12
15k
Concerns about Concerns
willnet
11
34k
Other Decks in Technology
See All in Technology
組織貢献をするフリーランスエンジニアという生き方
n_takehata
1
1.3k
全文検索+セマンティックランカー+LLMの自然文検索サ−ビスで得られた知見
segavvy
2
110
運用しているアプリケーションのDBのリプレイスをやってみた
miura55
1
720
あれは良かった、あれは苦労したB2B2C型SaaSの新規開発におけるCloud Spanner
hirohito1108
2
590
Platform Engineeringは自由のめまい
nwiizo
4
2.1k
JEDAI Meetup! Databricks AI/BI概要
databricksjapan
0
100
リアルタイム分析データベースで実現する SQLベースのオブザーバビリティ
mikimatsumoto
0
1.4k
次世代KYC活動報告 / 20250219-BizDay17-KYC-nextgen
oidfj
0
260
Larkご案内資料
customercloud
PRO
0
650
Developer Summit 2025 [14-D-1] Yuki Hattori
yuhattor
19
6.2k
Nekko Cloud、 これまでとこれから ~学生サークルが作る、 小さなクラウド
logica0419
2
970
30分でわかる『アジャイルデータモデリング』
hanon52_
9
2.7k
Featured
See All Featured
Adopting Sorbet at Scale
ufuk
74
9.2k
Fontdeck: Realign not Redesign
paulrobertlloyd
83
5.4k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
129
19k
Side Projects
sachag
452
42k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Faster Mobile Websites
deanohume
306
31k
Visualization
eitanlees
146
15k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.4k
How to train your dragon (web standard)
notwaldorf
91
5.8k
Navigating Team Friction
lara
183
15k
GraphQLとの向き合い方2022年版
quramy
44
13k
Facilitating Awesome Meetings
lara
52
6.2k
Transcript
Rails Good Parts, Bad Parts @willnet
自己紹介 » 前島真一 aka @willnet or @netwillnet » ginza.rb から来ました
» メドピアさんで技術顧問しています » https://github.com/willnet » https://twitter.com/netwillnet » https://blog.willnet.in
技術顧問として 主に負債を減らしたり、負債の増加を防ぐために頑 張っています !
技術顧問について詳しく知りたい方は こちらをどうぞ » Rails Developers Meetup で喋った » https://speakerdeck.com/willnet/ji-shu-gu- wen-toiudong-kifang
» ブログ書いた » https://blog.willnet.in/entry/ 2018/04/09/101808
今日のテーマは技術的負 債 !
負債へのアプローチは2 つ
できてしまった負債を減 らす⬇
新規開発で負債を増やさ ない⬆ !
今日は負債を増やさない 話をします
負債の増加を防ぐにはど うしたらよいか
Railsのレールに乗る
レールに乗る、とは? » みんなよく言ってるけどふわっとした概念 » レールについてきちんと説明している文章がない ように見える
Railsが提供しているべんりな機能を活 用する = レールに乗る ここではこういう定義とします
Railsのべんりな機能 » たくさんある » こういうメソッドないかな?と思って調べると大 抵定義済み
べんりな機能を知らずに スクラッチで実装して微 妙な感じになるケースが よくある !
べんりな機能の具体例 » あまり知られていない&&知ってると便利なもの » 複数のお手伝い先で何回も言ってるやつ
has_many
みんな知ってる
定義することで使えるよ うになる機能がたくさん ある
has_manyで使えるようになるものたち collection collection<<(object, ...) collection.delete(object, ...) collection.destroy(object, ...) collection=(objects) collection_singular_ids
collection_singular_ids=(ids) collection.clear
has_manyで使えるようになるものたち collection.empty? collection.size collection.find(...) collection.where(...) collection.exists?(...) collection.build(attributes = {}, ...)
collection.create(attributes = {}) collection.create!(attributes = {}) collection.reload
全種類知ってますか?
collection=(objects), collection_singular_ids=(ids) » 既存のcollectionをいい感じに置き換える » has_many through の場合は中間テーブルを置き 換える
合わせ技でつかえるview helper » collection_check_boxes これらをスクラッチで書いてしまう人めっちゃ多い (当社比)
コード例 ビールの銘柄にタグ付けをするコードを考えてみま す
None
modelはこんな感じ class Beer < ApplicationRecord has_many :taggings has_many :tags, through:
:taggings end
素直に書くと <% 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 %>
素直に書くと 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
一瞬では読めないです ね… !
既存のタグと入力値との 差分を見て、必要なもの だけinsert, deleteして いる
読みづらいしバグも入り 込みやすそう
便利メソッドたちを使うと <%= form.collection_check_boxes :tag_ids, Tag.all, :id, :name %>
便利メソッドたちを使うと 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
普通に書ける beer.tag_ids = params[:beer][:tag_id] » has_many :tagsでtag_ids=メソッドが生えてい る » いい感じに差分を見て中間テーブルをinsert,
deleteしてくれる
これ、初めて知った人 ✋
どうやってべんりな機能を知るのか » 公式のドキュメントやRailsガイドを読みましょ う » もしくは強い人にレビューやペアプロしてもらい ましょう
ここまでの話をまとめる と
Railsが提供するべんり な機能を使えば負債を作 らずに開発できる!
なんですけど…
Railsが提供している機能が全部無条件 に便利というわけではない » 安易に使うとやけどする機能もある » ググるといろいろでてくるはず » callback » default_scope
» nested attributes
gemも似たように、安易に採用すべきで はないものがある » devise » simple_form » activeadmin » etc
この手のやつ、どう取り扱うべきか » チーム開発のときは特に慎重になったほうが良い » 禁止にしておいたほうが無難なことも多い » 利用シーンやチームの状況によって使えることも あるので、できれば吟味して決めたい
例えばwebpacker » 最近よくdisられている » しかしフロントエンド専任がおらず、片手間でjs を書く&&とりあえずes6使いたい、というケース だと大変便利 » フロントエンド専任がいて、webpackの設定をち ゃんとしたい、というケースでは必要ない
例えばdevise » 昔からよくdisられている » devise wayから外れるとつらい » 管理画面だけ認証が必要、などdevise wayで問題 ないならサッと導入できて便利
要注意なものは » なぜ注意が必要なのか » どう避けるか » どういうときなら使ってもよいのか を把握してまとめておくと良い
例えばhas_manyのcollection<<は要注 意 class User has_many :posts end これはイマイチな書き方 user.posts <<
Post.new(title: 'hello world!')
なぜか collection<<は、レシーバのオブジェクトがDBに 保存済みか否かで挙動が異なる(クエリが発行され たり発行されなかったりする)
どう避けるか user.posts.build(title: 'hello world!') user.posts.create(title: 'hello world!') のように書いたほうが可読性が高く、事故りにくい
どういうときなら使ってもよいのか collection.build や collection.createが適切 でない、かつチームメンバー全員が挙動を理解して いればギリギリOKかと tag = Tag.create(name: 'Ϗʔϧ')
Beer.each { |beer| beer.tags << tag }
(こうも書けるのであんまり例が良くな い) tag = Tag.create(name: 'Ϗʔϧ') Beer.each { |beer| beer.taggings.create!(tag:
tag) }
このように » なぜ注意が必要なのか » どう避けるか » どういうときなら使ってもよいのか を把握してチーム内で共有したい
負債を作らないために は、負債になりそうな要 素の対応法をみんなが理 解している必要がある
少なくとも、レビューで 負債になりそうな要素を 止められるようにしてお きたい
負債を作らないイコール 社内教育を頑張る
メドピアでは » 社内読書会 » ペアプロ » ふりかえり会 などしています
ところで、さっきの例は 簡単すぎ
現実ではもっと判断に悩 むケースが多い
判断に悩む例: コールバックをどう回 避するとよいか? » フォームオブジェクト? » サービスクラス? » その他 ↑方針を決めたとして、具体的にどうやって作ると
いいの?
なるべく具体的に「こう だ!」と道を示さない と、それぞれ思い思いの 実装になってそれが負債 につながる
しかし選択するのが難し い
そこで clean-rails.org ですよ
可読性の高いRailsのコ ードを議論するコミュニ ティ
どのように実装するとよ いか判断に悩むときに相 談できる
皆様からの投稿お待ちし ています !
まとめ » 負債を作らないためには、べんりな機能、要注意 な機能を知ることが大事 » 要注意なものについて、チーム全体で理解できる ように詳細を詰めて周知する » 勉強と教育をがんばりましょう
判断に悩むものは一緒に 勉強していきましょう