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.4k
File Upload 2017
RejectKaigi 2017で発表した資料です。ActiveStorageの機能を紹介する過程で、ファイルアップロードを実装するのに必要な要件と選択肢について解説しています。
Shinichi Maeshima
August 19, 2017
Tweet
Share
More Decks by Shinichi Maeshima
See All by Shinichi Maeshima
rails g authenticationから学ぶRails8.0時代の認証
willnet
5
3k
What's a well-behaved Rails extension gem?
willnet
0
440
Sidekiq vs Solid Queue
willnet
14
13k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
6
1.5k
Exceptional Rails
willnet
6
7.8k
Breaking the Flaky Test Cycle
willnet
2
2.2k
mrskで広がるインフラの選択肢
willnet
1
1.1k
アプリケーションを長期にわたって無理なく運用するためのたったひとつの方法
willnet
2
2.2k
HotwireからDHHが考えるこれからのRailsとJSの付き合い方を知る
willnet
14
14k
Other Decks in Programming
See All in Programming
開発生産性を上げるための生成AI活用術
starfish719
3
1.5k
なぜあの開発者はDevRelに伴走し続けるのか / Why Does That Developer Keep Running Alongside DevRel?
nrslib
3
410
Claude Agent SDK を使ってみよう
hyshu
0
1.3k
bootcamp2025_バックエンド研修_WebAPIサーバ作成.pdf
geniee_inc
0
120
『毎日の移動』を支えるGoバックエンド内製開発
yutautsugi
2
270
釣り地図SNSにおける有料機能の実装
nokonoko1203
0
190
kiroとCodexで最高のSpec駆動開発を!!数時間で web3ネイティブなミニゲームを作ってみたよ!
mashharuki
0
780
AI Agent 時代的開發者生存指南
eddie
4
2k
Google Opalで使える37のライブラリ
mickey_kubo
2
120
When Dependencies Fail: Building Antifragile Applications in a Fragile World
selcukusta
0
110
CSC509 Lecture 05
javiergs
PRO
0
310
Introduce Hono CLI
yusukebe
6
3k
Featured
See All Featured
Docker and Python
trallard
46
3.6k
Raft: Consensus for Rubyists
vanstee
140
7.2k
Typedesign – Prime Four
hannesfritz
42
2.8k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Facilitating Awesome Meetings
lara
56
6.6k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.7k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
10
880
KATA
mclloyd
PRO
32
15k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
34
2.3k
Testing 201, or: Great Expectations
jmmastey
45
7.7k
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 !"⬆!