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
File Upload 2017
Search
Shinichi Maeshima
August 19, 2017
Programming
7
9.2k
File Upload 2017
RejectKaigi 2017で発表した資料です。ActiveStorageの機能を紹介する過程で、ファイルアップロードを実装するのに必要な要件と選択肢について解説しています。
Shinichi Maeshima
August 19, 2017
Tweet
Share
More Decks by Shinichi Maeshima
See All by Shinichi Maeshima
Sidekiq vs Solid Queue
willnet
13
9.6k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
5
1.1k
Exceptional Rails
willnet
6
6.9k
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 Programming
See All in Programming
テストコード文化を0から作り、変化し続けた組織
kazatohiei
2
1.5k
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
210
LLM Supervised Fine-tuningの理論と実践
datanalyticslabo
4
1.1k
命名をリントする
chiroruxx
1
390
ドメインイベント増えすぎ問題
h0r15h0
1
280
Recoilを剥がしている話
kirik
5
6.6k
【re:Growth 2024】 Aurora DSQL をちゃんと話します!
maroon1st
0
770
Refactor your code - refactor yourself
xosofox
1
260
Semantic Kernelのネイティブプラグインで知識拡張をしてみる
tomokusaba
0
180
rails statsで大解剖 🔍 “B/43流” のRailsの育て方を歴史とともに振り返ります
shoheimitani
2
930
KMP와 kotlinx.rpc로 서버와 클라이언트 동기화
kwakeuijin
0
140
[JAWS-UG横浜 #76] イケてるアップデートを宇宙いち早く紹介するよ!
maroon1st
0
460
Featured
See All Featured
Scaling GitHub
holman
458
140k
Navigating Team Friction
lara
183
15k
Building Better People: How to give real-time feedback that sticks.
wjessup
365
19k
Optimising Largest Contentful Paint
csswizardry
33
3k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
810
Building Adaptive Systems
keathley
38
2.3k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
66k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
What's in a price? How to price your products and services
michaelherold
243
12k
Embracing the Ebb and Flow
colly
84
4.5k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
520
Transcript
File Upload 2017 @willnet
RejectKaigi • ;ͭ͏ͷRailsΤϯδχΞͩͱMRI͍ͬͨ͡Γ͠ͳ͍ͷͰͳ͔ͳ ͔CFPͩͤͳ͍ • ͔͠͠Α͘Α͘ߟ͑ΔͱRESTAPIɺΞϓϦέʔγϣϯαʔό ͳͲͷςʔϚ࠾͞ΕͯΔ • ॲཧܥҎ֎ͷͰ௨Δͱࢥ͏Μ͚ͩͲԿ͔͔͋ͬͨͳ…
RubyKaigiͱࢲ • File UploadͳΒݟ͋Δ͍͚͠ΔͷͰʁ • ؾ͍ͮͨͷ͕ఏग़ظݶޙ !
RejectKaigiͰͦ͏
ࣗݾհ • લౡਅҰ aka @willnet or @netwillnet • ginza.rb ͔Βདྷ·ͨ͠
• ϑϦʔϥϯεRailsٕज़ސ • https://github.com/willnet • https://twitter.com/netwillnet • http://blog.willnet.in
ؔ࿈ॻ੶ WEB+DB PRESS Vol.95 ͰϑΝΠϧΞοϓϩʔυͷΛॻ͖·ͨ͠
File Upload
File Upload͍ͬͯ͠ΜͰ͢Α…! • ϑΝΠϧΛͲ͜Ͱม͢Δ͔ • Ͳ͜ʹอଘ͢Δ͔ • όϦσʔγϣϯΛͲ͏͢Δ͔ • ηΩϡϦςΟΛͲ͏୲อ͢Δ͔
• շదʹϑΝΠϧΛΞοϓϩʔυ͢ΔʹͲ͏͢Δ͔ • Ξοϓϩʔυͨ͠ϑΝΠϧͷΞΫηεݖݶ
ϑΝΠϧΞοϓϩʔυػೳ • ଟ͘ͷߟྀ͖͢ཁૉ͕͋Δ • εΫϥονͰ࣮͢Δͷ͍ͨΜ
gemΛ͓͏ !
RubyͷओͳϑΝΠϧΞοϓϩʔυϥΠϒϥϦ • paperclip • carrierwave • dragonfly • refile •
shrine • attache • active_storage(new!)
ͲͷϥΠϒϥϦΛ͏ͱ͍͍ΜͰ͢ ͔ʙʁ ! ✋
ཁ ݅ ࣍ ୈ
ͱ͍ͬͯԿΛͲ͏બΜͩΒ͍͍ͷ͔… ϑΝΠϧΞοϓϩʔυͷ • ߟྀ͖͢ཁૉ • ͦͷબࢶ ͱϥΠϒϥϦͷػೳΛѲ͢ΔͱબΔͷͰ
શ෦͢ͷແཧ
ͦ͜Ͱࠓ (RailsͷͰڪॖͰ͕͢)ΈΜͳؾʹͳΔActive Storageͷػೳհ Λ௨ͯ͡ϑΝΠϧΞοϓϩʔυશൠʹ͍ͭͯ͠·͢
ͦͦActive Storageͱʁ • Rails 5.2ͰೖΔ༧ఆͷػೳ • mountable engineͱͯ͠࡞ΒΕͨ • ͭ·ΓಠࣗͷϧʔςΟϯάɺίϯτϩʔϥɺϞσϧ͕͋Δ
Active Storageͷಛ • ϙϦϞʔϑΟοΫؔ࿈ • ΞΫηε࣌ม • ੍࣌ؒݶ͖ͷURLΛ؆୯ʹѻ͑Δ • μΠϨΫτΞοϓϩʔυରԠ
• ϛϥʔػೳ
Active Storage Λ͏લͷ४උ AttachmentͱBlob༻ͷςʔϒϧΛ࡞Δ ./bin/rails active_storage:install ./bin/rails db:migrate
ϙϦϞʔϑΟοΫؔ࿈ • ϑΝΠϧཧ༻ͷϞσϧ͕༻ҙ͞Ε͍ͯΔ • Attachment (தؒςʔϒϧ) • Blob (ϑΝΠϧͷϝλใ) •
UserͳͲͷϞσϧʹϑΝΠϧ༻ͷΧϥϜΛՃ͠ͳ͍ܗࣜ • ͯ͢ͷϑΝΠϧΛˢͷ2ͭͰཧ͢Δ
ϝϦοτ • εΩʔϚͷมߋʹॊೈ
ϝϦοτͷྫ • 1Ϣʔβ1ΞόλʔͰӡ༻͍͕ͯͨ͠ɺ1ϢʔβෳΞόλʔʹ ༷มߋ͕͋ͬͨ • ଞϥΠϒϥϦͩͱςʔϒϧͷՃ͕ඞཁʹͳΔ • Active StorageͩͱεΩʔϚใͷมߋ͕ඞཁͳ͍
σϝϦοτ ͯ͢ͷछྨͷϑΝΠϧใ͕Blobʹ֨ೲ͞ΕΔ • Ξόλʔ • ը૾Ξοϓϩʔυ • ϑΝΠϧڞ༗
Ϟσϧ class User < ApplicationRecord has_one_attached :avatar end class Gallery
< ApplicationRecord has_many_attached :photos end
Ϗϡʔ(ϑΥʔϜ) <%= form.file_field :avatar %>
ίϯτϩʔϥ def create @user = User.new(user_params) if @user.save @user.avatar.attach( io:
params[:user][:avatar], filename: 'avatar.jpeg' ) redirect_to @user, notice: 'User was successfully created.' else render :new end end
ը૾ͷදࣔ <%= image_tag user.avatar.variant(resize: "100x100") %>
Active StorageΞΫηε࣌มܗࣜ • dragonfly, refile, attacheͳͲ͕࠾༻͍ͯ͠Δܗࣜ • มͷܗࣜΛؚΊͨURLͰΞΫηε • มܗࣜΛ૿͢ͱ͖ͷࣄલ४උ͕ෆཁͰָ
• ΞϓϦέʔγϣϯαʔόʹෛՙ͕͔͔Δ߹͕͋Δ
ෛՙ͕͔͔Δྫ 1. ը૾ΛҰʹͨ͘͞ΜΞοϓϩʔυ 2. ը૾ҰཡϖʔδʹભҠ 3. ͨ͘͞Μͷը૾ͷม͕ಉ࣌ʹ࣮ߦ͞ΕΔ
ෛՙΛࢄ͠Α͏ͱ͢ΔϥΠϒϥϦ͋Δ • attache͕࠾༻͍ͯ͠ΔΓํ • (·ͩࣄͰ͔ͭ͑Δײ͡Ͱͳ͍Ͱ͢) • ΞϓϦέʔγϣϯͱಠཱͨ͠ը૾༻ͷαʔόΛཱͯͯɺAPIͰ ΓͱΓ͢Δ • CloudinaryΈ͍ͨͳPaasΛࣗલͰӡ༻͢ΔΠϝʔδ
• microservice
Active StorageͳΒͰͷಛ • ॳճΞΫηε࣌ʹมͨ͠ͷΛΫϥυʹΞοϓϩʔυ • ΫϥυͷURLϦμΠϨΫτ • σϑΥϧτ5ͷظݶ͖URL • ύʔϚωϯτͳURLΞϓϦέʔγϣϯαʔόͷURL
ϑΝΠϧͷΞΫηεڐՄ • Active Storageظݶ͖ͷURLΛ࠾༻ • ΊͣΒ͍͠ • େྨਪͷ͍͠URLͰOKͱ͢Δ͜ͱ͕ଟ͍ • ݫີʹݖݶΛνΣοΫ͢ΔͱΞϓϦέʔγϣϯαʔόʹෛՙ
͕͔͔Δ • Active Storage ↑ͷΛ͏·͘ղܾ͍ͯ͠Δ
ଞͷมܗࣜ • Ξοϓϩʔυ࣌ʹม • όοΫάϥϯυͰม
Ξοϓϩʔυ࣌ʹม • paperclip, carrierwaveͳͲ͕࠾༻ • ࣮తʹҰ൪ૉͰཧղ͍͢͠ • ϑΝΠϧม͢Δ࣌ؒɺϢʔβΛͨͤΔ͜ͱʹͳΔ • ΞϓϦέʔγϣϯαʔόʹෛՙ͕͔͔Δ
• ม͢Δछྨ͕ଟ͍ • ϑΝΠϧΞοϓϩʔυ͕ूத͢Δ࣌ؒଳ
όοΫάϥϯυͰม • shrine͕࠾༻ • ΞοϓϩʔυͷλΠϛϯάͰΩϡʔʹมλεΫΛ٧ΊΔ • όοΫάϥϯυϫʔΧʔ͕ॱ൪ʹม͍ͯ͘͠ͷͰෛՙͷ ΛܰݮͰ͖Δ • ม͕ऴΘΔલʹը૾͕ඞཁʹͳΔέʔεͰࠔΔ
μΠϨΫτΞοϓϩʔυ • ΞϓϦέʔγϣϯαʔόΛܦ༝ͤͣΫϥυʹΞοϓϩʔ υ • ΞϓϦέʔγϣϯαʔόͷෛՙݮ • ͍͔ͭ͘ͷϥΠϒϥϦͰαϙʔτ͍ͯ͠Δ • ϑΥʔϜͷsubmit࣌ʹΞοϓϩʔυ
μΠϨΫτΞοϓϩʔυ application.js //= require activestorage _form.html.erb <%= form.filefield :avatar, direct_upload:
true %>
Ξοϓϩʔυઌͷઃఆ(Ұ෦) config/storage.yml test: service: Disk root: <%= Rails.root.join("tmp/storage") %> local:
service: Disk root: <%= Rails.root.join("storage") %> # amazon: # service: S3 # access_key_id: <%= Rails.application.secrets.dig(:aws, :access_key_id) %> # secret_access_key: <%= Rails.application.secrets.dig(:aws, :secret_access_key) %> # region: us-east-1 # bucket: your_own_bucket
config/environments/development.rbͳͲ config.active_storage.service = :local
ϛϥʔͷઃఆ ಉ࣌ʹෳͷΫϥυετϨʔδʹΞοϓϩʔυͯ͠όοΫΞο ϓͰ͖Δ config/storage.yml mirror: service: Mirror primary: amazon mirrors:
[ google, microsoft ]
Ұ௨Γಛͨ͠
Կ͔Γͯͳ͍ͷ͋ΔΑ͏ͳ!
Active Storegeʹݱঢ়Γ͍ͯͳ͍Α͏ʹΈ͑ Δͷ • όϦσʔγϣϯ • cache
όϦσʔγϣϯ େͷϥΠϒϥϦʹόϦσʔγϣϯͷαϙʔτ͕͋Δ͕ɺݱঢ় ͷActive Storegeʹͳ͔ͥଘࡏ͠ͳ͍
όϦσʔγϣϯྫ • ϑΝΠϧܗࣜͷ֬ೝ • ֦ுࢠ • Content Type
όϦσʔγϣϯྫ • ϑΝΠϧͷେ͖͞ • ༰ྔ • ը૾ͷॎ෯ԣ෯: Biggest image in
the smallest space
όϦσʔγϣϯ • PRνϟϯε? • ͔͠͠Ϟσϧ͕ڞ༗ͳͷͰ࣮ͮ͠Β͍ • ྫ: Ξόλʔ5MB͚ͩͲͦΕҎ֎ͷࣸਅ10MB·ͰOK
cache • ଞͷϥΠϒϥϦͰ΄΅αϙʔτ͞Ε͍ͯΔ • όϦσʔγϣϯΤϥʔ࣌ͷϑΝΠϧஔ͖
cacheͷྫ 1. ը૾ͱίϝϯτΛϑΥʔϜ͔Βૹ৴ 2. ίϝϯτ͕όϦσʔγϣϯΤϥʔ 3. ը૾cacheྖҬʹอଘ͍ͯ͠ΔͷͰίϝϯτ͚ͩमਖ਼ͯ͠࠶ ૹ৴ 4. ը૾cacheྖҬ͔Βຊ൪ྖҬʹҠಈ͢Δ
cache αϯϓϧίʔυ͕͜͏ͳͷͰɺຖճΞοϓϩʔυ͠Ζͱ͍͏ׂΓ Γʹݟ͑Δ class MessagesController < ApplicationController # ུ def
create message = Message.create! params.require(:message).permit(:title, :content) message.images.attach(params[:message][:images]) redirect_to message end # ུ end
·ͱΊ Active StorageͷػೳհΛ௨ͯ͡ɺϑΝΠϧΞοϓϩʔυͷ • ߟྀ͖͢ཁૉ • ͦͷબࢶ ͷҰ෦Λհ͠·ͨ͠
·ͱΊ • ϑΝΠϧΞοϓϩʔυͷ͠͞ɺΘΓ·͔ͨ͠ʁ • ສೳͳϥΠϒϥϦͳ͍ͷͰɺཁ݅ݟ͍͚ͯ·͠ΐ͏
Happy File Uploading !"⬆!