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
Become a gorm feeling and use gorm
Search
linyows
April 15, 2018
Programming
9
18k
Become a gorm feeling and use gorm
Gormの気持ちになってGormを使う
Aprio 15, 2018 @Go Conference 2018 Spring でお話しした資料です
linyows
April 15, 2018
Tweet
Share
More Decks by linyows
See All by linyows
研究開発と実装OSSと プロダクトの好循環 / A virtuous cycle of research and development implementation OSS and products
linyows
1
360
コードジェネレーターで 効率的な開発をする / Efficient development with code generators
linyows
0
310
研究を支える拡張性の高い ワークフローツールの提案 / Proposal of highly expandable workflow tools to support research
linyows
0
430
非コンテナ環境において宣言的Deploymentを手軽に実現する / Declarative deployment in non-container environments
linyows
0
220
メール送信サーバの集約における透過型SMTP プロキシの定量評価 / Quantitative Evaluation of Transparent SMTP Proxy in Email Sending Server Aggregation
linyows
0
970
透過型SMTPプロキシによる送信メールの可観測性向上: Update Edition / Improved observability of outgoing emails with transparent smtp proxy: Update edition
linyows
2
470
研究の再現性を高める 仕組みをGoでつくる / Creating a system to improve the reproducibility of research using go
linyows
1
240
奥が深いメールのシステム / The depth of Email system
linyows
4
600
IaCにおけるテスト考察 / Tests in IaC
linyows
2
720
Other Decks in Programming
See All in Programming
Yes, You Can Work on Rails & any other Gem
kaspth
0
110
ZeroETLで始めるDynamoDBとS3の連携
afooooil
0
120
No Install CMS戦略 〜 5年先を見据えたフロントエンド開発を考える / no_install_cms
rdlabo
0
190
MCPを使ってイベントソーシングのAIコーディングを効率化する / Streamlining Event Sourcing AI Coding with MCP
tomohisa
0
180
ソフトウェア設計とAI技術の活用
masuda220
PRO
25
6.7k
What's new in AppKit on macOS 26
1024jp
0
170
CDK引数設計道場100本ノック
badmintoncryer
2
560
AIのメモリー
watany
11
950
階層化自動テストで開発に機動力を
ickx
1
420
TypeScriptでDXを上げろ! Hono編
yusukebe
3
860
AIコーディングエージェント全社導入とセキュリティ対策
hikaruegashira
12
7.2k
PHPカンファレンス関西2025 基調講演
sugimotokei
5
930
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
Bash Introduction
62gerente
613
210k
Automating Front-end Workflow
addyosmani
1370
200k
Art, The Web, and Tiny UX
lynnandtonic
301
21k
Gamification - CAS2011
davidbonilla
81
5.4k
Documentation Writing (for coders)
carmenintech
72
4.9k
The Pragmatic Product Professional
lauravandoore
35
6.8k
Agile that works and the tools we love
rasmusluckow
329
21k
The Language of Interfaces
destraynor
158
25k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
35
2.5k
Mobile First: as difficult as doing things right
swwweet
223
9.7k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
Transcript
5PNPIJTB0EB(.01FQBCP *OD "QSJM (PSNͷؾ࣋ͪʹͳͬͯ(PSNΛ͏ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH ʘԬ͔Βདྷ·ͨ͠ʗ !NPOPDISPNFHBOF͞Μͨͪͱ 'VLVPLBHPΛӡӦ͍ͯ͠·͢ ࣸਅɿԬࢢ
(P$POGFSFODF4QSJOH (.0ϖύϘϓϦϯγύϧΤϯδχΞ খాԝ!MJOZPXT ٕज़෦ٕज़ج൫νʔϜ IUUQUPNPIJTBPEBDPN
(P$POGFSFODF4QSJOH ϩϦοϓʂ ϚωʔδυΫϥυ ·ͳ͘ ਖ਼ࣜ൛ϦϦʔε
(P$POGFSFODF4QSJOH ݄ʹൃചͷ 8&# %#13&44WPM )BTIJ$PSQ7BVMUͷ هࣄΛدߘ͠·ͨ͠ ͜Ε
(P$POGFSFODF4QSJOH MJOVYϢʔβͷ໊લղܾΛ HJUIVCνʔϜίϥϘϨʔλͰ ߦ͏ιϑτΣΞΛ࡞͍ͬͯ·͢ IUUQTHJUIVCDPNMJOZPXTPDUPQBTT
(P$POGFSFODF4QSJOH (PSNͬͨ͜ͱ͋Γ·͔͢ʁ ▸ 03.0CKFDU3FMBUJPOBM.BQQFS ▸ ଟɺ(PͰҰ൪ϝδϟʔͳ03. ▸ (PSNͷଞʹHPSQ YPSN TRMY
▸ ΄͔ͷݴޠͩͱɺ"DUJWF3FDPSE 3VCZ &MPRVFOU 1)1 4FRVFMJ[F /PEFKT "DUJWF3FDPSEͷѹతʜʜʜʜ
(P$POGFSFODF4QSJOH type Product struct { gorm.Model Code string Price uint
} func main() { db, _ := gorm.Open("sqlite3", "test.db") defer db.Close() db.Create(&Product{Code: "L1212", Price: 1000}) var p Product db.First(&p, 1) db.First(&p, "code = ?", "L1212") db.Model(&p).Update("Price", 2000) db.Delete(&p) } (PSNͷ͍ํ
গͳ͍ίʔυྔͰςʔϒϧߦΛߏମʹ Ϛοϐϯάͯ͘͠ΕΔ %#ίωΫγϣϯͱߏମʢϞσϧʣΛ ͚ͯ͏ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH (PSNͷػೳ ▸ "TTPDJBUJPOTIBTNBOZ CFMPOHTUP QPMZNPSQIJTN ▸ )PPLTCFGPSFBGUFS ▸ 1SFMPBEJOH
▸ 5SBOTBDUJPOT ▸ $PNQPTJUF1SJNBSZ,FZ
'VMM'FBUVSFE03. BMNPTU (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH err := db.Debug().Where("role = ?", "admin").Or("role = ?", "super").Find(&users).Error
// SELECT * FROM users WHERE role = 'admin' OR role = 'super'; (PSNͷಛ (PͰ͍͠ϝιουνΣʔϯ ϝιουνΣʔϯͳͷͰಈతͳΫΤϦ࡞͕؆୯Ͱ͖Δ ϝιουνΣʔϯͷͨΊʹΤϥʔΛߏମʹೖΕ͍ͯΔ
(P$POGFSFODF4QSJOH package gorm type Model struct { ID uint `gorm:"primary_key"`
CreatedAt time.Time UpdatedAt time.Time DeletedAt *time.Time `sql:"index"` } package model type User struct { gorm.Model Name string } (PSNͷϞσϧఆٛ
(P$POGFSFODF4QSJOH $ find model -type f -not -name '*_test.go' |
wc -l 35 $ find model -type f -not -name '*_test.go' | xargs grep 'func' | grep -v '\sfunc' | wc -l 196 # ???????????????? ଟ͘ͳ͍ʁ $ find api -type f -not -name '*_test.go' | wc -l 22 (PSNΛར༻ͨ͠ɺ͋Δ"1*4FSWFS
Ϟσϧʹ ؔɺϝιουཚཱ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH func FindUserByName(n string) *User, error { u := new(User)
if err := db. First(u, "name = ?", n).Error; err != nil { return nil, err } return u, nil } Ϟσϧͷཚཱؔɺϝιου1BSU ·͋ɺΓ͍ͨ͜ͱΘ͔Δ
(P$POGFSFODF4QSJOH func FindUserByNameWithProfile(n string) *User, error { u := new(User)
if err := db. Preload("Profile").First(u, "name = ?", n).Error; err != nil { return nil, err } return u, nil } Ϟσϧͷཚཱؔɺϝιου1BSU ଞͷϞσϧґଘΛՃʜ
(P$POGFSFODF4QSJOH func FindUserByNameWithAll(n string) *User, error { u := new(User)
if err := db. Preload("Profile"). Preload("Projects"). Preload("Projects.Repositories"). Preload("Roles").First(u, "name = ?", n).Error; err != nil { return nil, err } return u, nil } Ϟσϧͷཚཱؔɺϝιου1BSU ͋Ε͜ΕՃ͞Ε·ͯ͠ʜ
(P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH func FindUserByName(n string, Preload ...string) *User, error { d
:= db for _, v := range preloads { d = d.Preload(v) } u := new(User) if err := d.First(&u, "name = ?", n).Error; err != nil { return nil, err } return u, nil } Ϟσϧͷཚཱؔɺϝιου1BSU ͏·͍ͬͯ͘Δ෩ʜ
(P$POGFSFODF4QSJOH (u *User) FindByName(n string) error { if err :=
db. First(u, "name = ?", n).Error; err != nil { return err } return nil } Ϟσϧͷཚཱؔɺϝιου1BSU ͪΐͬͱ͓Μͳ͡Μ
(P$POGFSFODF4QSJOH ͜Ε͍͔Μʜ ▸ ࠣࡉͳҧ͍Ͱؔϝιου͕ྔ࢈͞Ε͍ͯΔ ▸ ςετίʔυͳͲɺཧίετ૿͍͑ͯΔ ▸ ଞͷϞσϧґଘɺόάͷԹচ
Կ͕ਖ਼͍͠ͷ͔Θ͔ΒΜ͕ Կ͔ؒҧ͍͑ͯΔ͜ͱΘ͔ͬͨ (PSNͷؾ࣋ͪʹͳΖ͏ (P$POGFSFODF4QSJOH
%#ίωΫγϣϯͱߏମʢϞσϧʣΛ͚ͯ͏͔Β ͍ΘΏΔ.7$Ͱߟ͑ΔͱɺϞσϧʹผϨΠϠʔͰ͋Δ%#ૢ࡞ΛӅ ณ͢Δͷ͕ࣗવʁ ͋ΒͨΊͯ"DUJWF3FDPSEత03.Λߟ͑Δ (P$POGFSFODF4QSJOH Ͳ͏ͯ͜͠͏ͳͬͨʁ ▸ ͞ΕͨͭΛͭʹϥοϓͨ͘͠ͳΔ ▸ ΫΤϦͷ࡞ΓํͰऔಘͰ͖Δߏମ͕มԽ͢Δ
"DUJWF3FDPSE%FTJHO1BUUFSO "OPCKFDUUIBUXSBQTBSPXJOBEBUBCBTFUBCMFPSWJFX FODBQTVMBUFTUIFEBUBCBTFBDDFTT BOEBEETEPNBJOMPHJDPOUIBU EBUB .BSUJO'PXMFS
ςʔϒϧͷߦΛΧϓηϧԽͨ͠ΦϒδΣΫτʹ υϝΠϯϩδοΫΛੜ͢ύλʔϯ (P$POGFSFODF4QSJOH ͭ·Γ
(P$POGFSFODF4QSJOH 3VCZʹ͓͍ͯͷ"3σβΠϯ ▸ 5BCMF$MBTT ▸ 5BCMF3PX*OTUBODF ▸ 5BCMF3PXT"SSBZ ▸ %PNBJO-PHJD*OTUBODF.FUIPE
(P$POGFSFODF4QSJOH user = new User(name: 'linyows') user.save() 3VCZʹ͓͍ͯͷ"3σβΠϯ Πϯελϯε͔ΒอଘͰ͖Δ ͳͥͳΒΫϥεʹ%#ίωΫγϣϯΛแ͍ͯ͠Δ͔Β
(P$POGFSFODF4QSJOH (Pʹ͓͍ͯͷ"3σβΠϯ ▸ 5BCMF'VODUJPO ▸ 5BCMF3PX4USVDU ▸ 5BCMF3PXT4MJDF
▸ %PNBJO-PHJD.FUIPE ͘͢ͳ͘ͱɺ(PSNʹ͓͍ͯ͜͏ͩ
(P$POGFSFODF4QSJOH u := User{Name: "linyows"} db.Save(&u) (Pʹ͓͍ͯͷ"3σβΠϯ ECίωΫγϣϯ͔ΒσʔλΛอଘ͢Δ ߏମͨͩͷೖΕͳͷͰɺવΫϥεͷΑ͏ʹৼΔ͑ͳ͍
σβΠϯͱͯ͠ͳͦ͞͏ (P$POGFSFODF4QSJOH
͋ΒͨΊͯ(Pͷݴޠ༷Λ֬ೝ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH
ΑΓॏཁͳΞΠσΞίϯηϓτͷɻ σʔλͱৼΔ͍ɺ(PͷͭͷҟͳΔίϯηϓτͰ͋Γɺ ʮΫϥεʯͱ͍͏୯Ұͷ֓೦ʹ·ͱΊΒΕ͍ͯͳ͍ɻ (P$POGFSFODF4QSJOH
ͭ·Γɺ͜ͷݴޠ༷ͷҧ͍͕͋ΔʹؔΘΒͣɺ HPSNͷϝιουνΣʔϯςʔϒϧϚοϐϯά͕"3తͰɺ HPSNͷ͍ํΛޡͬͨํʹಋ͍͍ͯΔͷͰʁ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH DMBTT JOTUBODF WBSJBCMFT %#DPOOFDUJPO GVOD %# DPOOFDUJPO TUSVDU NFUIPE
6TFS 3VCZ (P ֤ίϯϙʔωϯτ͕͞ΕΞΫηε͍͢͠ Ϟσϧ Ϟσϧ
(P$POGFSFODF4QSJOH 3BJMTͷ"DUJWF3FDPSEΕΑ͏ ▸ (Pͷ%#ίωΫγϣϯͱσʔλɺυϝΠϯϩδοΫͷΛϝ Ϧοτͱଊ͑Δ ▸ ແ༻ͷΧϓηϧԽ͠ͳ͍ ▸ ݺͼग़͠ଆʹॊೈੑΛ࣋ͨͤΔ
(P$POGFSFODF4QSJOH package api func GetUserWithProfile(c echo.Context) error { n :=
c.Param("username") u, e := model.FindUserByUsernameWithProfile(n) if e != nil { return NewError(http.StatusNotFound, e, "not found") } return c.JSON(http.StatusOK, u)) } package model func FindUserByUsernameWithProfile(n string) (*User, error) { u := new(User) if err := db.Preload("Profile").Scopes(Enabled).Where("username = ?", n).First(u).Error; err != nil { return nil, err } return u, nil } มߋલ
(P$POGFSFODF4QSJOH package api func GetUserWithProfile(c echo.Context) error { n :=
c.Param("username") u := new(model.User) if err := db.Preload("Profile").Scopes(Enabled).Where("username = ?", n).First(u).Error; err != nil { return NewError(http.StatusNotFound, e, "not found") } return c.JSON(http.StatusOK, f) } มߋޙ ͜Ε͚ͩʂϞσϧଆͷ࣮ແ͘ͳΓ·ͨ͠
%#ૢ࡞(PSNʹͤΔ ˣ ͕͞ഉআ͞ΕεοΩϦ (P$POGFSFODF4QSJOH
શͯ(PSNͷؾ࣋ͪ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH ৽ͨͳ՝ɿݺͼग़͠ଆʹࣅͨΑ͏ͳίʔυ͕૿͑ͳ͍ʁ 4DPQFTΛ͑େৎɺݺͼग़͠Λڞ௨Խ͢Δ͜ͱ͕Ͱ͖Δ 4DPQFɺ'VODUJPOͳͷͰϞσϧ໊Λ1SFpYʹ͢Δͱཧ͍͢͠ func UserGolden() func (db *gorm.DB) *gorm.DB
{ return func (db *gorm.DB) *gorm.DB { return db.Preload("Profile").Preload("Projects").Preload("Roles").Where("status = ?", "enabled") } } u := new(user) db.Scopes(UserGolden()).Find(u, 123)
(P$POGFSFODF4QSJOH ·ͱΊ ▸ (PσʔλͱৼΔ͍Λ͍ͯ͠Δ͜ͱΛΕͳ͍ ▸ $MBTTੈքͷ"DUJWF3FDPSEͷ͜ͱΕΑ͏ ▸ (PSNͷ%#ίωΫγϣϯΛϞσϧʹΧϓηϧԽ͠ͳ͍ ▸ ͜ΕΒΛ౿·͑Είʔυ͕؆ૉԽ͢Δ
▸ ͦͯ͠4DPQF݁ߏ͑ΔΑ
͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ (P$POGFSFODF4QSJOH