Slide 1

Slide 1 text

File Upload 2017 @willnet

Slide 2

Slide 2 text

RejectKaigi • ;ͭ͏ͷRailsΤϯδχΞͩͱMRI͍ͬͨ͡Γ͠ͳ͍ͷͰͳ͔ͳ ͔CFPͩͤͳ͍ • ͔͠͠Α͘Α͘ߟ͑ΔͱREST΍APIɺΞϓϦέʔγϣϯαʔό ͳͲͷςʔϚ΋࠾୒͞ΕͯΔ • ॲཧܥҎ֎ͷ࿩Ͱ΋௨Δͱ͸ࢥ͏Μ͚ͩͲԿ͔͔͋ͬͨͳ…

Slide 3

Slide 3 text

RubyKaigiͱࢲ • File UploadͳΒ஌ݟ͋Δ͍͚͠ΔͷͰ͸ʁ • ؾ͍ͮͨͷ͕ఏग़ظݶޙ !

Slide 4

Slide 4 text

RejectKaigiͰ࿩ͦ͏

Slide 5

Slide 5 text

ࣗݾ঺հ • લౡਅҰ aka @willnet or @netwillnet • ginza.rb ͔Βདྷ·ͨ͠ • ϑϦʔϥϯεRailsٕज़ސ໰ • https://github.com/willnet • https://twitter.com/netwillnet • http://blog.willnet.in

Slide 6

Slide 6 text

ؔ࿈ॻ੶ WEB+DB PRESS Vol.95 ͰϑΝΠϧΞοϓϩʔυͷ࿩Λॻ͖·ͨ͠

Slide 7

Slide 7 text

File Upload

Slide 8

Slide 8 text

File Uploadͬͯ೉͍͠ΜͰ͢Α…! • ϑΝΠϧΛͲ͜Ͱม׵͢Δ͔ • Ͳ͜ʹอଘ͢Δ͔ • όϦσʔγϣϯΛͲ͏͢Δ͔ • ηΩϡϦςΟΛͲ͏୲อ͢Δ͔ • շదʹϑΝΠϧΛΞοϓϩʔυ͢Δʹ͸Ͳ͏͢Δ͔ • Ξοϓϩʔυͨ͠ϑΝΠϧͷΞΫηεݖݶ

Slide 9

Slide 9 text

ϑΝΠϧΞοϓϩʔυػೳ • ଟ͘ͷߟྀ͢΂͖ཁૉ͕͋Δ • εΫϥονͰ࣮૷͢Δͷ͸͍ͨ΁Μ

Slide 10

Slide 10 text

gemΛ࢖͓͏ !

Slide 11

Slide 11 text

Ruby੡ͷओͳϑΝΠϧΞοϓϩʔυϥΠϒϥϦ • paperclip • carrierwave • dragonfly • refile • shrine • attache • active_storage(new!)

Slide 12

Slide 12 text

ͲͷϥΠϒϥϦΛ࢖͏ͱ͍͍ΜͰ͢ ͔ʙʁ ! ✋

Slide 13

Slide 13 text

ཁ ݅ ࣍ ୈ

Slide 14

Slide 14 text

ͱ͸͍ͬͯ΋ԿΛͲ͏બΜͩΒ͍͍ͷ͔… ϑΝΠϧΞοϓϩʔυͷ • ߟྀ͢΂͖ཁૉ • ͦͷબ୒ࢶ ͱϥΠϒϥϦͷػೳΛ೺Ѳ͢Δͱબ΂ΔͷͰ͸

Slide 15

Slide 15 text

શ෦࿩͢ͷ͸ແཧ

Slide 16

Slide 16 text

ͦ͜Ͱࠓ೔͸ (Railsͷ࿩ͰڪॖͰ͕͢)ΈΜͳؾʹͳΔActive Storageͷػೳ঺հ Λ௨ͯ͡ϑΝΠϧΞοϓϩʔυશൠʹ͍ͭͯ࿩͠·͢

Slide 17

Slide 17 text

ͦ΋ͦ΋Active Storageͱ͸ʁ • Rails 5.2ͰೖΔ༧ఆͷػೳ • mountable engineͱͯ͠࡞ΒΕͨ • ͭ·ΓಠࣗͷϧʔςΟϯάɺίϯτϩʔϥɺϞσϧ͕͋Δ

Slide 18

Slide 18 text

Active Storageͷಛ௃ • ϙϦϞʔϑΟοΫؔ࿈ • ΞΫηε࣌ม׵ • ੍࣌ؒݶ෇͖ͷURLΛ؆୯ʹѻ͑Δ • μΠϨΫτΞοϓϩʔυରԠ • ϛϥʔػೳ

Slide 19

Slide 19 text

Active Storage Λ࢖͏લͷ४උ AttachmentͱBlob༻ͷςʔϒϧΛ࡞Δ ./bin/rails active_storage:install ./bin/rails db:migrate

Slide 20

Slide 20 text

ϙϦϞʔϑΟοΫؔ࿈ • ϑΝΠϧ؅ཧ༻ͷϞσϧ͕༻ҙ͞Ε͍ͯΔ • Attachment (தؒςʔϒϧ) • Blob (ϑΝΠϧͷϝλ৘ใ) • UserͳͲͷϞσϧʹϑΝΠϧ༻ͷΧϥϜΛ௥Ճ͠ͳ͍ܗࣜ • ͢΂ͯͷϑΝΠϧΛˢͷ2ͭͰ؅ཧ͢Δ

Slide 21

Slide 21 text

ϝϦοτ • εΩʔϚͷมߋʹॊೈ

Slide 22

Slide 22 text

ϝϦοτͷྫ • 1Ϣʔβ1ΞόλʔͰӡ༻͍͕ͯͨ͠ɺ1Ϣʔβෳ਺Ξόλʔʹ࢓ ༷มߋ͕͋ͬͨ • ଞϥΠϒϥϦͩͱςʔϒϧͷ௥Ճ͕ඞཁʹͳΔ • Active StorageͩͱεΩʔϚ৘ใͷมߋ͕ඞཁͳ͍

Slide 23

Slide 23 text

σϝϦοτ ͢΂ͯͷछྨͷϑΝΠϧ৘ใ͕Blobʹ֨ೲ͞ΕΔ • Ξόλʔ • ը૾Ξοϓϩʔυ • ϑΝΠϧڞ༗

Slide 24

Slide 24 text

Ϟσϧ class User < ApplicationRecord has_one_attached :avatar end class Gallery < ApplicationRecord has_many_attached :photos end

Slide 25

Slide 25 text

Ϗϡʔ(ϑΥʔϜ) <%= form.file_field :avatar %>

Slide 26

Slide 26 text

ίϯτϩʔϥ 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

Slide 27

Slide 27 text

ը૾ͷදࣔ <%= image_tag user.avatar.variant(resize: "100x100") %>

Slide 28

Slide 28 text

Active Storage͸ΞΫηε࣌ม׵ܗࣜ • dragonfly, refile, attacheͳͲ͕࠾༻͍ͯ͠Δܗࣜ • ม׵ͷܗࣜΛؚΊͨURLͰΞΫηε • ม׵ܗࣜΛ૿΍͢ͱ͖ͷࣄલ४උ͕ෆཁͰָ • ΞϓϦέʔγϣϯαʔόʹෛՙ͕͔͔Δ৔߹͕͋Δ

Slide 29

Slide 29 text

ෛՙ͕͔͔Δྫ 1. ը૾ΛҰ౓ʹͨ͘͞ΜΞοϓϩʔυ 2. ը૾ҰཡϖʔδʹભҠ 3. ͨ͘͞Μͷը૾ͷม׵͕ಉ࣌ʹ࣮ߦ͞ΕΔ

Slide 30

Slide 30 text

ෛՙΛ෼ࢄ͠Α͏ͱ͢ΔϥΠϒϥϦ΋͋Δ • attache͕࠾༻͍ͯ͠Δ΍Γํ • (·ͩ࢓ࣄͰ͔ͭ͑Δײ͡Ͱ͸ͳ͍Ͱ͢) • ΞϓϦέʔγϣϯͱ͸ಠཱͨ͠ը૾༻ͷαʔόΛཱͯͯɺAPIͰ ΍ΓͱΓ͢Δ • CloudinaryΈ͍ͨͳPaasΛࣗલͰӡ༻͢ΔΠϝʔδ • microservice

Slide 31

Slide 31 text

Active StorageͳΒͰ͸ͷಛ௃ • ॳճΞΫηε࣌ʹม׵ͨ͠΋ͷΛΫϥ΢υʹΞοϓϩʔυ • Ϋϥ΢υ΁ͷURL΁ϦμΠϨΫτ • σϑΥϧτ5෼ͷظݶ෇͖URL • ύʔϚωϯτͳURL͸ΞϓϦέʔγϣϯαʔόͷURL

Slide 32

Slide 32 text

ϑΝΠϧ΁ͷΞΫηεڐՄ • Active Storage͸ظݶ෇͖ͷURLΛ࠾༻ • ΊͣΒ͍͠ • େ఍͸ྨਪͷ೉͍͠URLͰOKͱ͢Δ͜ͱ͕ଟ͍ • ݫີʹݖݶΛνΣοΫ͢ΔͱΞϓϦέʔγϣϯαʔόʹෛՙ ͕͔͔Δ • Active Storage ↑ͷ໰୊Λ͏·͘ղܾ͍ͯ͠Δ

Slide 33

Slide 33 text

ଞͷม׵ܗࣜ • Ξοϓϩʔυ࣌ʹม׵ • όοΫάϥ΢ϯυͰม׵

Slide 34

Slide 34 text

Ξοϓϩʔυ࣌ʹม׵ • paperclip, carrierwaveͳͲ͕࠾༻ • ࣮૷తʹ͸Ұ൪ૉ௚Ͱཧղ͠΍͍͢ • ϑΝΠϧม׵͢Δ࣌ؒɺϢʔβΛ଴ͨͤΔ͜ͱʹͳΔ • ΞϓϦέʔγϣϯαʔόʹෛՙ͕͔͔Δ • ม׵͢Δछྨ͕ଟ͍ • ϑΝΠϧΞοϓϩʔυ͕ूத͢Δ࣌ؒଳ

Slide 35

Slide 35 text

όοΫάϥϯυͰม׵ • shrine͕࠾༻ • ΞοϓϩʔυͷλΠϛϯάͰΩϡʔʹม׵λεΫΛ٧ΊΔ • όοΫάϥ΢ϯυϫʔΧʔ͕ॱ൪ʹม׵͍ͯ͘͠ͷͰෛՙͷ໰ ୊ΛܰݮͰ͖Δ • ม׵͕ऴΘΔલʹը૾͕ඞཁʹͳΔέʔεͰࠔΔ

Slide 36

Slide 36 text

μΠϨΫτΞοϓϩʔυ • ΞϓϦέʔγϣϯαʔόΛܦ༝ͤͣΫϥ΢υʹ௚઀Ξοϓϩʔ υ • ΞϓϦέʔγϣϯαʔόͷෛՙ௿ݮ • ͍͔ͭ͘ͷϥΠϒϥϦͰαϙʔτ͍ͯ͠Δ • ϑΥʔϜͷsubmit࣌ʹΞοϓϩʔυ

Slide 37

Slide 37 text

μΠϨΫτΞοϓϩʔυ application.js //= require activestorage _form.html.erb <%= form.filefield :avatar, direct_upload: true %>

Slide 38

Slide 38 text

Ξοϓϩʔυઌͷઃఆ(Ұ෦) 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

Slide 39

Slide 39 text

config/environments/development.rbͳͲ config.active_storage.service = :local

Slide 40

Slide 40 text

ϛϥʔͷઃఆ ಉ࣌ʹෳ਺ͷΫϥ΢υετϨʔδʹΞοϓϩʔυͯ͠όοΫΞο ϓͰ͖Δ config/storage.yml mirror: service: Mirror primary: amazon mirrors: [ google, microsoft ]

Slide 41

Slide 41 text

Ұ௨Γಛ௃࿩ͨ͠

Slide 42

Slide 42 text

Կ͔଍Γͯͳ͍΋ͷ͋ΔΑ͏ͳ!

Slide 43

Slide 43 text

Active Storegeʹݱঢ়଍Γ͍ͯͳ͍Α͏ʹΈ͑ Δ΋ͷ • όϦσʔγϣϯ • cache

Slide 44

Slide 44 text

όϦσʔγϣϯ େ఍ͷϥΠϒϥϦʹ͸όϦσʔγϣϯͷαϙʔτ͕͋Δ͕ɺݱঢ় ͷActive Storegeʹ͸ͳ͔ͥଘࡏ͠ͳ͍

Slide 45

Slide 45 text

όϦσʔγϣϯྫ • ϑΝΠϧܗࣜͷ֬ೝ • ֦ுࢠ • Content Type

Slide 46

Slide 46 text

όϦσʔγϣϯྫ • ϑΝΠϧͷେ͖͞ • ༰ྔ • ը૾ͷॎ෯ԣ෯: Biggest image in the smallest space

Slide 47

Slide 47 text

όϦσʔγϣϯ • PRνϟϯε? • ͔͠͠Ϟσϧ͕ڞ༗ͳͷͰ࣮૷ͮ͠Β͍ • ྫ: Ξόλʔ͸5MB͚ͩͲͦΕҎ֎ͷࣸਅ͸10MB·ͰOK

Slide 48

Slide 48 text

cache • ଞͷϥΠϒϥϦͰ͸΄΅αϙʔτ͞Ε͍ͯΔ • όϦσʔγϣϯΤϥʔ࣌ͷϑΝΠϧஔ͖৔

Slide 49

Slide 49 text

cacheͷྫ 1. ը૾ͱίϝϯτΛϑΥʔϜ͔Βૹ৴ 2. ίϝϯτ͕όϦσʔγϣϯΤϥʔ 3. ը૾͸cacheྖҬʹอଘ͍ͯ͠ΔͷͰίϝϯτ͚ͩमਖ਼ͯ͠࠶ ૹ৴ 4. ը૾͸cacheྖҬ͔Βຊ൪ྖҬʹҠಈ͢Δ

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

·ͱΊ Active Storageͷػೳ঺հΛ௨ͯ͡ɺϑΝΠϧΞοϓϩʔυͷ • ߟྀ͢΂͖ཁૉ • ͦͷબ୒ࢶ ͷҰ෦Λ঺հ͠·ͨ͠

Slide 52

Slide 52 text

·ͱΊ • ϑΝΠϧΞοϓϩʔυͷ೉͠͞ɺ఻ΘΓ·͔ͨ͠ʁ • ສೳͳϥΠϒϥϦ͸ͳ͍ͷͰɺཁ݅ݟͯ࢖͍෼͚·͠ΐ͏

Slide 53

Slide 53 text

Happy File Uploading !"⬆!