edge
Daugiau informacijos rubyonrails.org: Daugiau apie Ruby on Rails

Aktyvaus saugojimo apžvalga

Šiame vadove aprašoma, kaip pridėti failus prie jūsų Aktyvaus įrašo modelių.

Po šio vadovo perskaitymo žinosite:

1 Kas yra Aktyvus saugojimas?

Aktyvus saugojimas palengvina failų įkėlimą į debesų saugojimo paslaugą, pvz., Amazon S3, „Google Cloud Storage“ arba „Microsoft Azure Storage“, ir prideda tuos failus prie Aktyvus įrašo objektų. Jis turi vietinės disko pagrindinės paslaugos diegimui ir testavimui ir palaiko failų kopijavimą į pavaldžias paslaugas atsarginėms kopijoms ir migracijoms.

Naudodamas Aktyvų saugojimą, taikomoji programa gali keisti įkeltų paveikslėlių formatą arba generuoti vaizdinį atvaizdą ne paveikslėlių įkėlimams, pvz., PDF ir vaizdo įrašams, ir ištraukti metaduomenis iš bet kokių failų.

1.1 Reikalavimai

Įvairios Aktyvaus saugojimo funkcijos priklauso nuo trečiųjų šalių programinės įrangos, kurią „Rails“ neįdiegs ir kuriai reikia atskirai įdiegti:

Paveikslėlių analizei ir transformacijoms taip pat reikalingas image_processing grotelė. Jei reikia, ją atkomentuokite savo Gemfile arba pridėkite:

gem "image_processing", ">= 1.2"

PATARIMAS: Palyginti su libvips, ImageMagick yra geriau žinomas ir plačiau prieinamas. Tačiau libvips gali būti iki 10 kartų greitesnis ir sunaudoja 1/10 atminties. JPEG failams tai galima toliau pagerinti pakeičiant libjpeg-dev į libjpeg-turbo-dev, kuris yra 2-7 kartus greitesnis.

ĮSPĖJIMAS: Prieš įdiegdami ir naudodami trečiųjų šalių programinę įrangą, įsitikinkite, kad suprantate jos licencijos reikšmes. Ypač MuPDF licencijuojamas pagal AGPL ir reikalauja komercinės licencijos kai kuriems naudojimo atvejams.

2 Diegimas

$ bin/rails active_storage:install
$ bin/rails db:migrate

Tai nustato konfigūraciją ir sukuria tris Aktyvaus saugojimo naudojamas lentas: active_storage_blobs, active_storage_attachments ir active_storage_variant_records.

Lentelė Paskirtis
active_storage_blobs Saugo duomenis apie įkeltus failus, pvz., failo pavadinimą ir turinio tipą.
active_storage_attachments Polimorfinė jungtinė lentelė, kuri jungia jūsų modelius su blobais. Jei jūsų modelio klasės pavadinimas pasikeičia, turėsite paleisti migraciją šioje lentelėje, kad atnaujintumėte pagrindinį record_type į jūsų modelio naują klasės pavadinimą.
active_storage_variant_records Jei variantų sekimas yra įjungtas, saugo įrašus kiekvienam sugeneruotam variantui.

ĮSPĖJIMAS: Jei savo modeliuose vietoj sveikųjų skaičių naudojate UUID kaip pirminį raktą, turėtumėte nustatyti Rails.application.config.generators { |g| g.orm :active_record, primary_key_type: :uuid } konfigūracijos faile.

Apibrėžkite Aktyvaus saugojimo paslaugas config/storage.yml faile. Kiekvienai jūsų taikomosios programos naudojamai paslaugai pateikite pavadinimą ir reikiamą konfigūraciją. Pavyzdys žemiau deklaruoja tris paslaugas, pavadinimu local, test ir amazon:

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

amazon:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  bucket: ""
  region: "" # pvz., 'us-east-1'

Pasakykite Aktyviam saugojimui, kurią paslaugą naudoti nustatydami Rails.application.config.active_storage.service. Kadangi kiekviena aplinka tikriausiai naudos skirtingą paslaugą, rekomenduojama tai daryti aplinkos pagrindu. Norėdami naudoti ankstesnio pavyzdžio disko paslaugą vystymosi aplinkoje, pridėtumėte šį kodą prie config/environments/development.rb:

# Saugoti failus vietiniame diske.
config.active_storage.service = :local

Norėdami naudoti S3 paslaugą gamyboje, pridėtumėte šį kodą prie config/environments/production.rb:

# Saugoti failus „Amazon S3“.
config.active_storage.service = :amazon

Norėdami naudoti testavimo metu, pridėtumėte šį kodą prie config/environments/test.rb:

# Saugoti įkeltus failus vietiniame failų sistemos laikinyje aplanke.
config.active_storage.service = :test

PASTABA: Aplinkai specifiniai konfigūracijos failai bus pirmenybėje: pvz., gamyboje, jei egzistuoja config/storage/production.yml failas, jis bus pirmenybėje prieš config/storage.yml failą.

Rekomenduojama naudoti Rails.env kibirų pavadinimuose, kad dar labiau sumažintumėte riziką atsitiktinai sunaikinti gamybos duomenis.

amazon:
  service: S3
  # ...
  bucket: your_own_bucket-<%= Rails.env %>

google:
  service: GCS
  # ...
  bucket: your_own_bucket-<%= Rails.env %>

azure:
  service: AzureStorage
  # ...
  container: your_container_name-<%= Rails.env %>

Toliau skaitykite daugiau informacijos apie įdiegtus paslaugų adapterius (pvz., Disk ir S3) ir jų konfigūraciją.

2.1 Disko paslauga

Apibrėžkite Disko paslaugą config/storage.yml faile:

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

2.2 S3 paslauga (Amazon S3 ir S3 suderinami API)

Norėdami prisijungti prie Amazon S3, apibrėžkite S3 paslaugą config/storage.yml faile:

amazon:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  region: ""
  bucket: ""

Galite pasirinktinai nurodyti kliento ir įkėlimo parinktis:

amazon:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  region: ""
  bucket: ""
  http_open_timeout: 0
  http_read_timeout: 0
  retry_limit: 0
  upload:
    server_side_encryption: "" # 'aws:kms' arba 'AES256'
    cache_control: "private, max-age=<%= 1.day.to_i %>"

PATARIMAS: Nustatykite tinkamus kliento HTTP laukimo laikus ir pakartotinio bandymo limitus savo programai. Tam tikrose nesėkmės scenarijose numatyta AWS kliento konfigūracija gali sukelti ryšių laikymąsi iki kelių minučių ir sukelti užklausų eilėjimą.

Pridėkite aws-sdk-s3 paketą į savo Gemfile:

gem "aws-sdk-s3", require: false

Pastaba: Pagrindinės Active Storage funkcijos reikalauja šių leidimų: s3:ListBucket, s3:PutObject, s3:GetObject ir s3:DeleteObject. Viešas prieigos taip pat reikalauja s3:PutObjectAcl. Jei turite papildomų įkėlimo parinkčių, pvz., nustatydami ACL, gali būti reikalingi papildomi leidimai.

Pastaba: Jei norite naudoti aplinkos kintamuosius, standartinius SDK konfigūracijos failus, profilius, IAM egzempliorių profilius ar užduočių roles, galite pamiršti access_key_id, secret_access_key ir region raktus aukščiau pateiktame pavyzdyje. S3 paslauga palaiko visus autentifikavimo parinktis, aprašytas AWS SDK dokumentacijoje.

Norėdami prisijungti prie S3 suderinamo objektų saugojimo API, pvz., DigitalOcean Spaces, nurodykite endpoint:

digitalocean:
  service: S3
  endpoint: https://nyc3.digitaloceanspaces.com
  access_key_id: ...
  secret_access_key: ...
  # ...ir kitos parinktys

Yra daug kitų parinkčių. Jų sąrašą galite rasti AWS S3 kliento dokumentacijoje.

2.3 Microsoft Azure Storage paslauga

Apibrėžkite Azure Storage paslaugą config/storage.yml faile:

azure:
  service: AzureStorage
  storage_account_name: ""
  storage_access_key: ""
  container: ""

Pridėkite azure-storage-blob paketą į savo Gemfile:

gem "azure-storage-blob", "~> 2.0", require: false

2.4 Google Cloud Storage paslauga

Apibrėžkite Google Cloud Storage paslaugą config/storage.yml faile:

google:
  service: GCS
  credentials: <%= Rails.root.join("path/to/keyfile.json") %>
  project: ""
  bucket: ""

Pasirinktinai pateikite įgaliojimų maišą vietoj raktų failo kelio:

google:
  service: GCS
  credentials:
    type: "service_account"
    project_id: ""
    private_key_id: <%= Rails.application.credentials.dig(:gcs, :private_key_id) %>
    private_key: <%= Rails.application.credentials.dig(:gcs, :private_key).dump %>
    client_email: ""
    client_id: ""
    auth_uri: "https://accounts.google.com/o/oauth2/auth"
    token_uri: "https://accounts.google.com/o/oauth2/token"
    auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs"
    client_x509_cert_url: ""
  project: ""
  bucket: ""

Pasirinktinai nurodykite Cache-Control metaduomenis, kurie bus nustatyti įkeltiems ištekliams:

google:
  service: GCS
  ...
  cache_control: "public, max-age=3600"

Pasirinktinai naudokite IAM vietoj credentials naudojant URL adresus. Tai naudinga, jei autentifikuojate savo GKE programas naudodami darbo apkrovos tapatybę, daugiau informacijos rasite šiame Google Cloud tinklaraščio įraše.

google:
  service: GCS
  ...
  iam: true

Pasirinktinai naudokite konkretų GSA, kai pasirašote URL adresus. Naudojant IAM, metaduomenų serveris bus naudojamas, kad gautų GSA el. paštą, tačiau šis metaduomenų serveris ne visada yra prieinamas (pvz., vietiniai testai), ir galite norėti naudoti ne numatytąjį GSA.

google:
  service: GCS
  ...
  iam: true
  gsa_email: "[email protected]"

Pridėkite google-cloud-storage paketą į savo Gemfile:

gem "google-cloud-storage", "~> 1.11", require: false

2.5 Veidročių paslauga

Galite sinchronizuoti kelias paslaugas, apibrėždami veidročių paslaugą. Veidročių paslauga atkuria įkėlimus ir trynimus tarp dviejų ar daugiau pavaldžių paslaugų.

Veidročių paslauga skirta laikinai naudoti per migraciją tarp paslaugų gamyboje. Galite pradėti veidročių kurti naujai paslaugai, nukopijuoti ankstesnius failus iš senosios paslaugos į naująją ir visiškai perjungti į naująją paslaugą.

Pastaba: Veidročių kūrimas nėra atomiškas. Įkėlimas gali sėkmingai įvykti pagrindinėje paslaugoje ir nepavykti vienoje iš pavaldžių paslaugų. Prieš visiškai perjungiant į naują paslaugą, patikrinkite, ar visi failai buvo nukopijuoti.

Apibrėžkite kiekvieną paslaugą, kurias norite veidročiuoti, kaip aprašyta aukščiau. Nuorodą į jas nurodykite, apibrėždami veidročių paslaugą:

s3_west_coast:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  region: ""
  bucket: ""

s3_east_coast:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  region: ""
  bucket: ""

production:
  service: Mirror
  primary: s3_east_coast
  mirrors:
    - s3_west_coast

Nors visos antrinės paslaugos gauna įkėlimus, atsisiuntimus visada tvarko pagrindinė paslauga.

Veidročių paslaugos yra suderinamos su tiesioginiais įkėlimais. Nauji failai tiesiogiai įkeliami į pagrindinę paslaugą. Kai tiesiogiai įkeltas failas pridedamas prie įrašo, fone užduotis įtraukiama, kad jį nukopijuotų į antrines paslaugas.

2.6 Viešas prieigos

Pagal numatytuosius nustatymus, Active Storage priima privačią prieigą prie paslaugų. Tai reiškia, kad generuojami pasirašyti, vienkartiniai URL adresai blob'ams. Jei norite, kad blob'ai būtų viešai prieinami, nurodykite public: true savo programos config/storage.yml failo:

gcs: &gcs
  service: GCS
  project: ""

private_gcs:
  <<: *gcs
  credentials: <%= Rails.root.join("path/to/private_key.json") %>
  bucket: ""

public_gcs:
  <<: *gcs
  credentials: <%= Rails.root.join("path/to/public_key.json") %>
  bucket: ""
  public: true

Įsitikinkite, kad jūsų kibirai tinkamai sukonfigūruoti viešai prieinamai. Žr. dokumentaciją, kaip įjungti viešą skaitymo leidimą Amazon S3, Google Cloud Storage ir Microsoft Azure saugojimo paslaugoms. Amazon S3 taip pat reikalauja, kad turėtumėte s3:PutObjectAcl leidimą.

Konvertuojant esamą programą naudojant public: true, įsitikinkite, kad prieš perjungiant, kiekvienas atskiras failas kibirėlyje yra viešai skaitomas.

3 Failų pridėjimas prie įrašų

3.1 has_one_attached

has_one_attached makro nustato vieno įrašo ir failų vienareikšmį atitikimą. Kiekvienam įrašui gali būti pridėtas vienas failas.

Pavyzdžiui, jei jūsų programa turi User modelį ir norite, kad kiekvienas vartotojas turėtų avatarą, apibrėžkite User modelį taip:

class User < ApplicationRecord
  has_one_attached :avatar
end

arba, jei naudojate Rails 6.0+, galite paleisti modelio generavimo komandą taip:

bin/rails generate model User avatar:attachment

Galite sukurti vartotoją su avataru:

<%= form.file_field :avatar %>
class SignupController < ApplicationController
  def create
    user = User.create!(user_params)
    session[:user_id] = user.id
    redirect_to root_path
  end

  private
    def user_params
      params.require(:user).permit(:email_address, :password, :avatar)
    end
end

Norėdami pridėti avatarą prie esamo vartotojo, naudokite avatar.attach:

user.avatar.attach(params[:avatar])

Norėdami nustatyti, ar konkretus vartotojas turi avatarą, naudokite avatar.attached?:

user.avatar.attached?

Kai kuriais atvejais gali prireikti pakeisti numatytąją paslaugą tam tikram priedui. Galite konfigūruoti konkretesnes paslaugas kiekvienam priedui naudodami service parinktį:

class User < ApplicationRecord
  has_one_attached :avatar, service: :s3
end

Galite konfigūruoti konkretesnius variantus kiekvienam priedui, iškviesdami variant metodą perduodamam pridedamam objektui:

class User < ApplicationRecord
  has_one_attached :avatar do |attachable|
    attachable.variant :thumb, resize_to_limit: [100, 100]
  end
end

Norėdami gauti miniatiūros variantą iš avatara, naudokite avatar.variant(:thumb):

<%= image_tag user.avatar.variant(:thumb) %>

Taip pat galite naudoti konkretesnius variantus peržiūrai:

class User < ApplicationRecord
  has_one_attached :video do |attachable|
    attachable.variant :thumb, resize_to_limit: [100, 100]
  end
end
<%= image_tag user.video.preview(:thumb) %>

3.2 has_many_attached

has_many_attached makro nustato vieno įrašo ir failų vienam daugeliui atitikimą. Kiekvienam įrašui gali būti pridėti daug failų.

Pavyzdžiui, jei jūsų programa turi Message modelį ir norite, kad kiekvienas pranešimas turėtų daug paveikslėlių, apibrėžkite Message modelį taip:

class Message < ApplicationRecord
  has_many_attached :images
end

arba, jei naudojate Rails 6.0+, galite paleisti modelio generavimo komandą taip:

bin/rails generate model Message images:attachments

Galite sukurti pranešimą su paveikslėliais:

class MessagesController < ApplicationController
  def create
    message = Message.create!(message_params)
    redirect_to message
  end

  private
    def message_params
      params.require(:message).permit(:title, :content, images: [])
    end
end

Norėdami pridėti naujus paveikslėlius prie esamo pranešimo, naudokite images.attach:

@message.images.attach(params[:images])

Norėdami nustatyti, ar konkretus pranešimas turi paveikslėlių, naudokite images.attached?:

@message.images.attached?

Numatytosios paslaugos pakeitimas atliekamas taip pat kaip ir has_one_attached, naudojant service parinktį:

class Message < ApplicationRecord
  has_many_attached :images, service: :s3
end

Konkrečių variantų konfigūravimas atliekamas taip pat kaip ir has_one_attached, iškviesdami variant metodą perduodamam pridedamam objektui:

class Message < ApplicationRecord
  has_many_attached :images do |attachable|
    attachable.variant :thumb, resize_to_limit: [100, 100]
  end
end

3.3 Pridedant failų/IO objektus

Kartais reikia pridėti failą, kuris neatvyksta per HTTP užklausą. Pavyzdžiui, galite norėti pridėti failą, kurį sukūrėte diske arba atsisiuntėte iš vartotojo pateiktos URL. Taip pat galite norėti pridėti fiktyvų failą modelio teste. Tam pateikite Hash, kuriame yra bent atidarytas IO objektas ir failo pavadinimas:

@message.images.attach(io: File.open('/path/to/file'), filename: 'file.pdf')

Kai įmanoma, nurodykite ir turinio tipą. Active Storage bandys nustatyti failo turinio tipą iš jo duomenų. Jei nepavyksta, bus naudojamas nurodytas turinio tipas. ruby @message.images.attach(io: File.open('/path/to/file'), filename: 'file.pdf', content_type: 'application/pdf')

Jei norite apeiti duomenų turinio tipo nustatymą, perduokite identify: false kartu su content_type.

@message.images.attach(
  io: File.open('/path/to/file'),
  filename: 'file.pdf',
  content_type: 'application/pdf',
  identify: false
)

Jei nenurodysite turinio tipo ir Active Storage negalės automatiškai nustatyti failo turinio tipo, jis pagal nutylėjimą bus nustatytas kaip application/octet-stream.

4 Failų pašalinimas

Norėdami pašalinti priedą iš modelio, iškvieskite purge metodą priedui. Jei jūsų programa sukonfigūruota naudoti Active Job, pašalinimas gali būti atliktas fone, iškviečiant purge_later metodą. Pašalinimas ištrina blobą ir failą iš saugojimo paslaugos.

# Sinchroniškai sunaikinkite avatarą ir faktinio resurso failus.
user.avatar.purge

# Asinchroniškai sunaikinkite susijusius modelius ir faktinio resurso failus per Active Job.
user.avatar.purge_later

5 Failų teikimas

Active Storage palaiko du būdus, kaip teikti failus: nukreipiant ir perkeliant.

ĮSPĖJIMAS: Visi Active Storage valdikliai pagal nutylėjimą yra viešai prieinami. Sugeneruotos URL yra sunkiai atspėjamos, tačiau nuolatios. Jei jūsų failams reikalingas aukštesnis apsaugos lygis, apsvarstykite autentifikuotų valdiklių įgyvendinimą Autentifikuoti valdikliai.

5.1 Nukreipimo režimas

Norėdami sugeneruoti nuolatinį URL blobui, galite perduoti blobą į url_for pagalbinį vaizdo valdiklį. Tai sugeneruoja URL su blobo signed_id, kuris nukreipiamas į blobo RedirectController

url_for(user.avatar)
# => /rails/active_storage/blobs/:signed_id/my-avatar.png

RedirectController nukreipia į faktinį paslaugos tašką. Šis nukreipimas atskiria paslaugos URL nuo faktinio URL ir leidžia, pavyzdžiui, atvaizduoti priedus skirtingose paslaugose, siekiant užtikrinti didelį prieinamumą. Nukreipimas turi 5 minučių HTTP galiojimo laiką.

Norėdami sukurti atsisiuntimo nuorodą, naudokite rails_blob_{path|url} pagalbinį vaizdo valdiklį. Naudodami šį pagalbinį vaizdo valdiklį, galite nustatyti dispoziciją.

rails_blob_path(user.avatar, disposition: "attachment")

ĮSPĖJIMAS: Norint apsisaugoti nuo XSS atakų, Active Storage priverčia "Content-Disposition" antraštę būti "attachment" tam tikro tipo failams. Norėdami pakeisti šį elgesį, žr. galimas konfigūracijos parinktis Rails programų konfigūravimas.

Jei norite sukurti nuorodą iš už valdiklio / vaizdo konteksto (fonas darbai, Cron darbai ir kt.), galite pasiekti rails_blob_path taip:

Rails.application.routes.url_helpers.rails_blob_path(user.avatar, only_path: true)

5.2 Perkėlimo režimas

Galite pasirinktinai naudoti failų perkėlimą. Tai reiškia, kad jūsų programos serveriai atsisiųs failo duomenis iš saugojimo paslaugos atsakant į užklausas. Tai gali būti naudinga, jei norite teikti failus iš CDN.

Galite sukonfigūruoti Active Storage naudoti numatytąjį perkėlimo režimą:

# config/initializers/active_storage.rb
Rails.application.config.active_storage.resolve_model_to_route = :rails_storage_proxy

Arba, jei norite aiškiai perkelti konkretų priedą, galite naudoti URL pagalbinius vaizdo valdiklius rails_storage_proxy_path ir rails_storage_proxy_url.

<%= image_tag rails_storage_proxy_path(@user.avatar) %>

5.2.1 CDN naudojimas su Active Storage

Be to, norint naudoti CDN su Active Storage priedais, turėsite generuoti URL su perkėlimo režimu, kad jie būtų aptarnaujami jūsų programos ir CDN talpykloje be papildomo konfigūravimo. Tai veikia iškart, nes numatytasis Active Storage perkėlimo valdiklis nustato HTTP antraštę, nurodančią CDN talpyklai talpinti atsakymą.

Taip pat turėtumėte įsitikinti, kad sugeneruoti URL naudoja CDN prieglobos vietą, o ne jūsų programos prieglobos vietą. Yra kelios būdų tai pasiekti, bet apskritai tai apima jūsų config/routes.rb failo keitimą, kad galėtumėte generuoti tinkamus URL priedams ir jų variantams. Pavyzdžiui, galite pridėti tai:

# config/routes.rb
direct :cdn_image do |model, options|
  expires_in = options.delete(:expires_in) { ActiveStorage.urls_expire_in }

  if model.respond_to?(:signed_id)
    route_for(
      :rails_service_blob_proxy,
      model.signed_id(expires_in: expires_in),
      model.filename,
      options.merge(host: ENV['CDN_HOST'])
    )
  else
    signed_blob_id = model.blob.signed_id(expires_in: expires_in)
    variation_key  = model.variation.key
    filename       = model.blob.filename

    route_for(
      :rails_blob_representation_proxy,
      signed_blob_id,
      variation_key,
      filename,
      options.merge(host: ENV['CDN_HOST'])
    )
  end
end

ir tada generuokite maršrutus taip:

<%= cdn_image_url(user.avatar.variant(resize_to_limit: [128, 128])) %>

5.3 Autentifikuoti valdikliai

Visi Active Storage valdikliai pagal nutylėjimą yra viešai prieinami. Sugeneruoti URL naudoja paprastą signed_id, todėl jie sunkiai atspėjami, bet nuolatiniai. Bet kas, kas žino blobo URL, galės jį pasiekti, net jei before_action jūsų ApplicationController reikalauja prisijungimo. Jei jūsų failams reikalingas aukštesnis apsaugos lygis, galite įgyvendinti savo autentifikuotus valdiklius, remiantis ActiveStorage::Blobs::RedirectController, ActiveStorage::Blobs::ProxyController, ActiveStorage::Representations::RedirectController ir ActiveStorage::Representations::ProxyController

Norėdami leisti prieigą prie savo logotipo tik tam tikram paskyros tipui, galite tai padaryti: ```ruby

config/routes.rb

resource :account do resource :logo end ```

# app/controllers/logos_controller.rb
class LogosController < ApplicationController
  # Perjungti ApplicationController:
  # include Authenticate, SetCurrentAccount

  def show
    redirect_to Current.account.logo.url
  end
end
<%= image_tag account_logo_path %>

Tada turėtumėte išjungti Active Storage numatytuosius maršrutus su:

config.active_storage.draw_routes = false

kad būtų užkirstas kelias failams būti pasiekiamiems per viešai prieinamus URL.

6 Failų atsisiuntimas

Kartais po to, kai įkeliama byla, ją reikia apdoroti, pavyzdžiui, konvertuoti į kitą formatą. Naudokite priedo download metodą, kad nuskaitytumėte bylos binarinius duomenis į atmintį:

binary = user.avatar.download

Galbūt norėsite atsisiųsti bylą į disko failą, kad ją galėtų apdoroti išorinė programa (pvz., virusų skeneris ar medijos transkoderis). Naudokite priedo open metodą, kad atsisiųstumėte bylą į laikinąjį failą diske:

message.video.open do |file|
  system '/path/to/virus/scanner', file.path
  # ...
end

Svarbu žinoti, kad byla dar nėra prieinama after_create atgaliniame iškvietime, bet tik after_create_commit.

7 Failų analizė

Active Storage analizuoja bylas, kai jos yra įkeliamos, užduodant užduotį Active Job. Analizuotos bylos saugo papildomą informaciją metaduomenų maiše, įskaitant analyzed: true. Galite patikrinti, ar blob'as buvo analizuotas, iškviesdami analyzed? jį.

Vaizdo analizė suteikia width ir height atributus. Vaizdo analizė taip pat suteikia duration, angle, display_aspect_ratio ir video bei audio boolean reikšmes, nurodančias, ar yra šių kanalų. Garso analizė suteikia duration ir bit_rate atributus.

8 Vaizdų, vaizdo įrašų ir PDF failų rodymas

Active Storage palaiko įvairių failų atvaizdavimą. Galite iškviesti representation priedą, kad parodytumėte vaizdo variantą arba vaizdo ar PDF peržiūrą. Prieš iškviesdami representation, patikrinkite, ar priedas gali būti atvaizduojamas, iškviesdami representable?. Kai kurie failų formatai negali būti peržiūrėti naudojant Active Storage iš anksto (pvz., „Word“ dokumentai); jei representable? grąžina false, galbūt norėsite nuoroda į bylą.

<ul>
  <% @message.files.each do |file| %>
    <li>
      <% if file.representable? %>
        <%= image_tag file.representation(resize_to_limit: [100, 100]) %>
      <% else %>
        <%= link_to rails_blob_path(file, disposition: "attachment") do %>
          <%= image_tag "placeholder.png", alt: "Download file" %>
        <% end %>
      <% end %>
    </li>
  <% end %>
</ul>

Viduje representation iškviečia variant vaizdams ir preview peržiūrai. Taip pat galite tiesiogiai iškviesti šiuos metodus.

8.1 Tingus vs nedelsiantinis įkėlimas

Pagal numatymą Active Storage bus atliekamas tingiai. Šis kodas:

image_tag file.representation(resize_to_limit: [100, 100])

Sugeneruos <img> žymą su src nurodytu į ActiveStorage::Representations::RedirectController. Naršyklė pasiųs užklausą šiam valdikliui, kuris atliks šiuos veiksmus:

  1. Apdoros bylą ir įkelia apdorotą bylą, jei reikia.
  2. Grąžins 302 nukreipimą į bylą arba į
    • nuotolinį tarnybą (pvz., S3).
    • arba ActiveStorage::Blobs::ProxyController, kuris grąžins bylos turinį, jei proxy režimas yra įjungtas.

Tingus bylos įkėlimas leidžia veikti funkcijoms, pvz., vienkartinėms nuorodoms be poveikio pradiniam puslapio įkėlimui.

Tai veikia gerai daugumai atvejų.

Jei norite nedelsiant generuoti URL adresus vaizdams, galite iškviesti .processed.url:

image_tag file.representation(resize_to_limit: [100, 100]).processed.url

Aktyvaus saugojimo varianto sekimo priemonė pagerina šį veikimą, saugodama įrašą duomenų bazėje, jei prašomas variantas buvo apdorotas anksčiau. Taigi, aukščiau pateiktas kodas tik vieną kartą padarys API užklausą į nuotolinę tarnybą (pvz., S3), ir kai variantas bus saugomas, jį naudos. Varianto sekimo priemonė veikia automatiškai, bet gali būti išjungta per config.active_storage.track_variants.

Jei puslapyje atvaizduojate daugybę vaizdų, aukščiau pateiktas pavyzdys gali sukelti N+1 užklausų, įkeliančių visus varianto įrašus. Norėdami išvengti šių N+1 užklausų, naudokite vardinius taškus ActiveStorage::Attachment.

message.images.with_all_variant_records.each do |file|
  image_tag file.representation(resize_to_limit: [100, 100]).processed.url
end

8.2 Vaizdų transformavimas

Vaizdų transformavimas leidžia atvaizduoti vaizdą pasirinktais matmenimis. Norėdami sukurti vaizdo variantą, iškvieskite variant priedą priedui. Metodui galite perduoti bet kokį varianto apdorojimo palaikomą transformaciją. Kai naršyklė pasiekia varianto URL, Active Storage tingiai transformuos pradinį blob'ą į nurodytą formatą ir nukreips į naują tarnybos vietą.

<%= image_tag user.avatar.variant(resize_to_limit: [100, 100]) %>

Jei yra prašoma varianto, Active Storage automatiškai taikys transformacijas priklausomai nuo paveikslėlio formato:

  1. Kintami turinio tipai (kaip nurodyta config.active_storage.variable_content_types) ir nelaikomi interneto paveikslėliais (kaip nurodyta config.active_storage.web_image_content_types), bus konvertuojami į PNG formatą.

  2. Jei nenurodytas quality, bus naudojamas varianto apdorojimo proceso numatytasis kokybės lygis tam tikram formate.

Active Storage gali naudoti arba Vips arba MiniMagick kaip varianto apdorojimo procesorių. Numatytasis priklauso nuo jūsų config.load_defaults tikslinės versijos, o procesorius gali būti pakeistas nustatant config.active_storage.variant_processor.

Šie du procesoriai nėra visiškai suderinami, todėl, migruojant esamą programą tarp MiniMagick ir Vips, reikia atlikti keletą pakeitimų, jei naudojami formatui specifiniai parametrai:

<!-- MiniMagick -->
<%= image_tag user.avatar.variant(resize_to_limit: [100, 100], format: :jpeg, sampling_factor: "4:2:0", strip: true, interlace: "JPEG", colorspace: "sRGB", quality: 80) %>

<!-- Vips -->
<%= image_tag user.avatar.variant(resize_to_limit: [100, 100], format: :jpeg, saver: { subsample_mode: "on", strip: true, interlace: true, quality: 80 }) %>

Galimi parametrai apibrėžti image_processing gemo ir priklauso nuo naudojamo varianto proceso, tačiau abu palaiko šiuos parametrus:

Parametras Pavyzdys Aprašymas
resize_to_limit resize_to_limit: [100, 100] Sumažina paveikslėlį, kad jis tilptų nurodytuose matmenyse, išlaikant originalų kraštinių santykį. Sumažins paveikslėlį tik tuo atveju, jei jis yra didesnis nei nurodyti matmenys.
resize_to_fit resize_to_fit: [100, 100] Sumažina paveikslėlį, kad jis tilptų nurodytuose matmenyse, išlaikant originalų kraštinių santykį. Sumažins paveikslėlį, jei jis yra didesnis nei nurodyti matmenys, arba padidins, jei jis yra mažesnis.
resize_to_fill resize_to_fill: [100, 100] Sumažina paveikslėlį, kad jis užimtų nurodytus matmenis, išlaikant originalų kraštinių santykį. Jei reikia, apkirps paveikslėlį didesniame matmenyje.
resize_and_pad resize_and_pad: [100, 100] Sumažina paveikslėlį, kad jis tilptų nurodytuose matmenyse, išlaikant originalų kraštinių santykį. Jei reikia, užpildys likusią plotą permatomu spalvos sluoksniu, jei šaltinio paveikslėlyje yra alfa kanalas, arba juoda spalva.
crop crop: [20, 50, 300, 300] Ištraukia sritį iš paveikslėlio. Pirmi du argumentai yra ištraukimo srities kairysis ir viršutinis kraštas, o paskutiniai du argumentai yra ištraukimo srities plotis ir aukštis.
rotate rotate: 90 Pasuka paveikslėlį nurodytu kampu.

image_processing turi daugiau galimybių (pvz., saver, kuris leidžia konfigūruoti paveikslėlio suspaudimą) savo dokumentacijoje skirtą Vips ir MiniMagick procesoriams.

8.3 Failų peržiūra

Kai kurie ne paveikslėlių failai gali būti peržiūrimi: tai yra, jie gali būti pateikti kaip paveikslėliai. Pavyzdžiui, vaizdo failas gali būti peržiūrimas išskleidžiant pirmąjį kadro. Iš pradžių Active Storage palaiko vaizdo ir PDF dokumentų peržiūrą. Norėdami sukurti nuorodą į tingiai generuojamą peržiūrą, naudokite prisegimo preview metodą:

<%= image_tag message.video.preview(resize_to_limit: [100, 100]) %>

Norint pridėti palaikymą kitam formatai, pridėkite savo peržiūros įrankį. Daugiau informacijos rasite ActiveStorage::Preview dokumentacijoje.

9 Tiesioginės įkėlimai

Active Storage, su įtraukta JavaScript biblioteka, palaiko tiesioginį įkėlimą iš kliento į debesį.

9.1 Naudojimas

  1. Įtraukite activestorage.js į savo programos JavaScript rinkinį.

    Naudojant turinio paleidimo sistemą:

    //= require activestorage
    

    Naudojant npm paketą:

    import * as ActiveStorage from "@rails/activestorage"
    ActiveStorage.start()
    
  2. Į savo failo lauką pridėkite direct_upload: true:

    <%= form.file_field :attachments, multiple: true, direct_upload: true %>
    

    Arba, jei nenaudojate FormBuilder, pridėkite duomenų atributą tiesiogiai:

    <input type="file" data-direct-upload-url="<%= rails_direct_uploads_url %>" />
    
  3. Konfigūruokite CORS trečiųjų šalių saugyklų paslaugas, kad leistų tiesioginius įkėlimo užklausas.

  4. Tai viskas! Įkėlimai prasideda pateikus formą.

9.2 Cross-Origin Resource Sharing (CORS) konfigūracija

Norint, kad tiesioginiai įkėlimai į trečiųjų šalių paslaugą veiktų, reikės sukonfigūruoti paslaugą, kad ji leistų kryžmines kilmės užklausas iš jūsų programos. Pasitikrinkite savo paslaugos CORS dokumentaciją:

Atkreipkite dėmesį, kad leidžiate:

  • Visus kilmės taškus, iš kurių pasiekiamas jūsų programos
  • PUT užklausos metodą
  • Šiuos antraštės laukus:
    • Origin
    • Content-Type
    • Content-MD5
    • Content-Disposition (išskyrus Azure Storage)
    • x-ms-blob-content-disposition (tik Azure Storage)
    • x-ms-blob-type (tik Azure Storage)
    • Cache-Control (tik GCS, jei nustatytas cache_control) Disko paslaugai nereikia jokios CORS konfigūracijos, nes ji bendrina jūsų programos kilmę.

9.2.1 Pavyzdys: S3 CORS konfigūracija

[
  {
    "AllowedHeaders": [
      "*"
    ],
    "AllowedMethods": [
      "PUT"
    ],
    "AllowedOrigins": [
      "https://www.example.com"
    ],
    "ExposeHeaders": [
      "Origin",
      "Content-Type",
      "Content-MD5",
      "Content-Disposition"
    ],
    "MaxAgeSeconds": 3600
  }
]

9.2.2 Pavyzdys: Google Cloud Storage CORS konfigūracija

[
  {
    "origin": ["https://www.example.com"],
    "method": ["PUT"],
    "responseHeader": ["Origin", "Content-Type", "Content-MD5", "Content-Disposition"],
    "maxAgeSeconds": 3600
  }
]

9.2.3 Pavyzdys: Azure Storage CORS konfigūracija

<Cors>
  <CorsRule>
    <AllowedOrigins>https://www.example.com</AllowedOrigins>
    <AllowedMethods>PUT</AllowedMethods>
    <AllowedHeaders>Origin, Content-Type, Content-MD5, x-ms-blob-content-disposition, x-ms-blob-type</AllowedHeaders>
    <MaxAgeInSeconds>3600</MaxAgeInSeconds>
  </CorsRule>
</Cors>

9.3 Tiesioginio įkėlimo „JavaScript“ įvykiai

Įvykio pavadinimas Įvykio tikslas Įvykio duomenys (event.detail) Aprašymas
direct-uploads:start <form> Nėra Pateiktas forma, kurioje yra failų tiesioginiam įkėlimui skirtų laukų.
direct-upload:initialize <input> {id, file} Išsiunčiamas kiekvienam failui po formos pateikimo.
direct-upload:start <input> {id, file} Pradedamas tiesioginis įkėlimas.
direct-upload:before-blob-request <input> {id, file, xhr} Prieš siunčiant užklausą į jūsų programą dėl tiesioginio įkėlimo metaduomenų.
direct-upload:before-storage-request <input> {id, file, xhr} Prieš siunčiant užklausą dėl failo saugojimo.
direct-upload:progress <input> {id, file, progress} Kai vyksta užklausos dėl failų saugojimo pažanga.
direct-upload:error <input> {id, file, error} Įvyko klaida. Jei šis įvykis nebus atšauktas, bus rodomas įspėjimas.
direct-upload:end <input> {id, file} Tiesioginis įkėlimas baigtas.
direct-uploads:end <form> Nėra Visi tiesioginiai įkėlimai baigti.

9.4 Pavyzdys

Galite naudoti šiuos įvykius, kad parodytumėte įkėlimo pažangą.

direct-uploads

Norėdami rodyti įkeltus failus formoje:

// direct_uploads.js

addEventListener("direct-upload:initialize", event => {
  const { target, detail } = event
  const { id, file } = detail
  target.insertAdjacentHTML("beforebegin", `
    <div id="direct-upload-${id}" class="direct-upload direct-upload--pending">
      <div id="direct-upload-progress-${id}" class="direct-upload__progress" style="width: 0%"></div>
      <span class="direct-upload__filename"></span>
    </div>
  `)
  target.previousElementSibling.querySelector(`.direct-upload__filename`).textContent = file.name
})

addEventListener("direct-upload:start", event => {
  const { id } = event.detail
  const element = document.getElementById(`direct-upload-${id}`)
  element.classList.remove("direct-upload--pending")
})

addEventListener("direct-upload:progress", event => {
  const { id, progress } = event.detail
  const progressElement = document.getElementById(`direct-upload-progress-${id}`)
  progressElement.style.width = `${progress}%`
})

addEventListener("direct-upload:error", event => {
  event.preventDefault()
  const { id, error } = event.detail
  const element = document.getElementById(`direct-upload-${id}`)
  element.classList.add("direct-upload--error")
  element.setAttribute("title", error)
})

addEventListener("direct-upload:end", event => {
  const { id } = event.detail
  const element = document.getElementById(`direct-upload-${id}`)
  element.classList.add("direct-upload--complete")
})

Pridėkite stilių:

/* direct_uploads.css */

.direct-upload {
  display: inline-block;
  position: relative;
  padding: 2px 4px;
  margin: 0 3px 3px 0;
  border: 1px solid rgba(0, 0, 0, 0.3);
  border-radius: 3px;
  font-size: 11px;
  line-height: 13px;
}

.direct-upload--pending {
  opacity: 0.6;
}

.direct-upload__progress {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  opacity: 0.2;
  background: #0076ff;
  transition: width 120ms ease-out, opacity 60ms 60ms ease-in;
  transform: translate3d(0, 0, 0);
}

.direct-upload--complete .direct-upload__progress {
  opacity: 0.4;
}

.direct-upload--error {
  border-color: red;
}

input[type=file][data-direct-upload-url][disabled] {
  display: none;
}

9.5 Individualūs „drag and drop“ sprendimai

Galite naudoti „DirectUpload“ klasę šiam tikslui. Gavę failą iš pasirinktos bibliotekos, sukurkite „DirectUpload“ objektą ir iškvieskite jo „create“ metodą. „Create“ priima atgalinio iškvietimo funkciją, kuri bus iškviesta baigus įkėlimą.

import { DirectUpload } from "@rails/activestorage"

const input = document.querySelector('input[type=file]')

// Susieti su failo nuleidimu - naudoti ondrop ant tėvinio elemento arba naudoti
//  biblioteką kaip Dropzone
const onDrop = (event) => {
  event.preventDefault()
  const files = event.dataTransfer.files;
  Array.from(files).forEach(file => uploadFile(file))
}

// Susieti su įprastiniu failo pasirinkimu
input.addEventListener('change', (event) => {
  Array.from(input.files).forEach(file => uploadFile(file))
  // galite išvalyti pasirinktus failus iš įvesties
  input.value = null
})

const uploadFile = (file) => {
  // jūsų formai reikia failo lauko direct_upload: true, kuris
  //  suteikia data-direct-upload-url
  const url = input.dataset.directUploadUrl
  const upload = new DirectUpload(file, url)

  upload.create((error, blob) => {
    if (error) {
      // Tvarkyti klaidą
    } else {
      // Pridėti tinkamai pavadintą paslėptąjį įvesties lauką į formą su
      //  blob.signed_id reikšme, kad būtų perduoti blob id įprastame įkėlimo sraute
      const hiddenField = document.createElement('input')
      hiddenField.setAttribute("type", "hidden");
      hiddenField.setAttribute("value", blob.signed_id);
      hiddenField.name = input.name
      document.querySelector('form').appendChild(hiddenField)
    }
  })
}

9.6 Sekite failo įkėlimo pažangą

Naudodami „DirectUpload“ konstruktorių, galite įtraukti trečiąjį parametrą. Tai leis „DirectUpload“ objektui kviečiant „directUploadWillStoreFileWithXHR“ metodą įkėlimo proceso metu. Tada galite pridėti savo pažangos tvarkyklę prie XHR pagal savo poreikius. ```js import { DirectUpload } from "@rails/activestorage"

class Uploader { constructor(file, url) { this.upload = new DirectUpload(this.file, this.url, this) }

upload(file) { this.upload.create((error, blob) => { if (error) { // Tvarkyti klaidą } else { // Pridėti tinkamai pavadintą paslėptą įvestį į formą // su blob.signed_id reikšme } }) }

directUploadWillStoreFileWithXHR(request) { request.upload.addEventListener("progress", event => this.directUploadDidProgress(event)) }

directUploadDidProgress(event) { // Naudokite event.loaded ir event.total, kad atnaujintumėte progreso juostą } } ```

9.7 Integracija su bibliotekomis ar karkasais

Kai gausite failą iš pasirinktos bibliotekos, turite sukurti DirectUpload egzempliorių ir naudoti jo "create" metodą, kad pradėtumėte įkėlimo procesą, pridedant reikalingus papildomus antraštės laukus, jei reikia. "Create" metodas taip pat reikalauja, kad būtų pateiktas atgalinio iškvietimo funkcija, kuri bus paleista baigus įkėlimą.

import { DirectUpload } from "@rails/activestorage"

class Uploader {
  constructor(file, url, token) {
    const headers = { 'Authentication': `Bearer ${token}` }
    // INFO: Siuntimas antraštės yra neprivalomas parametras. Jei nuspręsite nesiųsti antraščių,
    //       autentifikacija bus atliekama naudojant slapukus arba sesijos duomenis.
    this.upload = new DirectUpload(this.file, this.url, this, headers)
  }

  upload(file) {
    this.upload.create((error, blob) => {
      if (error) {
        // Tvarkyti klaidą
      } else {
        // Naudokite blob.signed_id kaip failo nuorodą kitame užklausoje
      }
    })
  }

  directUploadWillStoreFileWithXHR(request) {
    request.upload.addEventListener("progress",
      event => this.directUploadDidProgress(event))
  }

  directUploadDidProgress(event) {
    // Naudokite event.loaded ir event.total, kad atnaujintumėte progreso juostą
  }
}

Norint įgyvendinti pritaikytą autentifikaciją, Rails aplikacijoje reikia sukurti naują valdiklį, panašų į šį:

class DirectUploadsController < ActiveStorage::DirectUploadsController
  skip_forgery_protection
  before_action :authenticate!

  def authenticate!
    @token = request.headers['Authorization']&.split&.last

    return head :unauthorized unless valid_token?(@token)
  end
end

PASTABA: Naudodami Tiesioginį įkėlimą kartais gali atsitikti, kad failas įkeliamas, bet niekada nėra pridedamas prie įrašo. Svarstykite išvalyti nepridėtus įkėlimus.

10 Testavimas

Norint išbandyti failo įkėlimą integracinėje arba valdiklio teste, naudokite fixture_file_upload funkciją. Rails tvarko failus kaip bet kokius kitus parametrus.

class SignupController < ActionDispatch::IntegrationTest
  test "can sign up" do
    post signup_path, params: {
      name: "David",
      avatar: fixture_file_upload("david.png", "image/png")
    }

    user = User.order(:created_at).last
    assert user.avatar.attached?
  end
end

10.1 Testavimo metu sukurtų failų pašalinimas

10.1.1 Sistemos testai

Sistemos testai valo testinius duomenis atšaukdami transakciją. Kadangi destroy niekada nėra iškviestas objekte, pridėti failai niekada nebus išvalyti. Jei norite išvalyti failus, galite tai padaryti naudodami after_teardown atgalinį iškvietimą. Tai padarys, kad visi testo metu sukurti ryšiai būtų užbaigti ir nebus gauta klaida iš Active Storage, kad negali rasti failo.

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  # ...
  def after_teardown
    super
    FileUtils.rm_rf(ActiveStorage::Blob.service.root)
  end
  # ...
end

Jei naudojate [lygiagrečius testus][] ir DiskService, turėtumėte konfigūruoti kiekvieną procesą naudoti savo aplanką Active Storage. Taip teardown atgalinis iškvietimas ištrins failus tik iš atitinkamo proceso testų.

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  # ...
  parallelize_setup do |i|
    ActiveStorage::Blob.service.root = "#{ActiveStorage::Blob.service.root}-#{i}"
  end
  # ...
end

Jei jūsų sistemos testai patikrina modelio su priedais trynimą ir naudojate Active Job, nustatykite savo testinę aplinką naudoti inline eilės adapterį, kad šalinimo darbas būtų vykdomas iš karto, o ne nežinomoje ateityje.

# Naudokite inline darbų apdorojimą, kad viskas vyktų iš karto
config.active_job.queue_adapter = :inline

10.1.2 Integraciniai testai

Panašiai kaip sistemos testuose, failai, įkelti integracinių testų metu, nebus automatiškai išvalyti. Jei norite išvalyti failus, galite tai padaryti naudodami teardown atgalinį iškvietimą.

class ActionDispatch::IntegrationTest
  def after_teardown
    super
    FileUtils.rm_rf(ActiveStorage::Blob.service.root)
  end
end

Jei naudojate [lygiagrečius testus][] ir Disk paslaugą, turėtumėte konfigūruoti kiekvieną procesą naudoti savo aplanką Active Storage. Taip teardown atgalinis iškvietimas ištrins failus tik iš atitinkamo proceso testų.

class ActionDispatch::IntegrationTest
  parallelize_setup do |i|
    ActiveStorage::Blob.service.root = "#{ActiveStorage::Blob.service.root}-#{i}"
  end
end

10.2 Priedų pridėjimas prie fiktyvių duomenų

Galite pridėti priedus prie jūsų esamų fiktyvių duomenų. Pirmiausia turėtumėte sukurti atskirą saugyklos paslaugą:

# config/storage.yml

test_fixtures:
  service: Disk
  root: <%= Rails.root.join("tmp/storage_fixtures") %>

Tai nurodo Active Storage, kur "įkelti" fiktyvius failus, todėl tai turėtų būti laikinas katalogas. Padarydami jį skirtingu katalogu nuo įprastos test paslaugos, galite atskirti fiktyvius failus nuo failų, įkeltų testo metu. Toliau sukurti fiktyvius failus Active Storage klasėms:

# active_storage/attachments.yml
david_avatar:
  name: avatar
  record: david (User)
  blob: david_avatar_blob
# active_storage/blobs.yml
david_avatar_blob: <%= ActiveStorage::FixtureSet.blob filename: "david.png", service_name: "test_fixtures" %>

Tada įdėkite failą į jūsų fiktyvių failų aplanką (numatytasis kelias yra test/fixtures/files) su atitinkamu failo pavadinimu. Daugiau informacijos rasite ActiveStorage::FixtureSet dokumentacijoje.

Kai viskas bus sukonfigūruota, galėsite pasiekti priedus savo testuose:

class UserTest < ActiveSupport::TestCase
  def test_avatar
    avatar = users(:david).avatar

    assert avatar.attached?
    assert_not_nil avatar.download
    assert_equal 1000, avatar.byte_size
  end
end

10.2.1 Fiktyvių failų valymas

Nors failai, įkelti testuose, yra valomi kiekvieno testo pabaigoje, fiktyvių failų reikia valyti tik vieną kartą: kai visi jūsų testai baigiasi.

Jei naudojate lygiagretesnius testus, iškvieskite parallelize_teardown:

class ActiveSupport::TestCase
  # ...
  parallelize_teardown do |i|
    FileUtils.rm_rf(ActiveStorage::Blob.services.fetch(:test_fixtures).root)
  end
  # ...
end

Jei nenaudojate lygiagretesnių testų, naudokite Minitest.after_run arba atitinkamą jūsų testų karkaso funkciją (pvz., after(:suite) RSpec):

# test_helper.rb

Minitest.after_run do
  FileUtils.rm_rf(ActiveStorage::Blob.services.fetch(:test_fixtures).root)
end

10.3 Paslaugų konfigūravimas

Galite pridėti config/storage/test.yml failą, kad konfigūruotumėte paslaugas, naudojamas testavimo aplinkoje. Tai naudinga, kai naudojama service parinktis.

class User < ApplicationRecord
  has_one_attached :avatar, service: :s3
end

Be config/storage/test.yml, naudojama s3 paslauga, sukonfigūruota config/storage.yml faile - net paleidžiant testus.

Būtų naudojama numatytoji konfigūracija ir failai būtų įkelti į paslaugos tiekėją, sukonfigūruotą config/storage.yml faile.

Šiuo atveju galite pridėti config/storage/test.yml ir naudoti Disk paslaugą s3 paslaugai, kad būtų išvengta užklausų siuntimo.

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

s3:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

11 Kitų debesų paslaugų palaikymo įgyvendinimas

Jei norite palaikyti kitą debesų paslaugą, turėsite įgyvendinti paslaugą. Kiekviena paslauga išplečia ActiveStorage::Service įgyvendindama metodus, reikalingus failų įkėlimui ir atsisiuntimui į debesį.

12 Neprisegti įkėlimai

Yra atvejų, kai failas yra įkeltas, bet niekada neprikabintas prie įrašo. Tai gali atsitikti naudojant Tiesioginius įkėlimus. Galite užklausti neprisegtų įrašų naudodami neprisegtų ribojimą. Žemiau pateikiamas pavyzdys naudojant adaptuotą rake užduotį.

namespace :active_storage do
  desc "Valo neprisegtus Active Storage blob'us. Paleiskite reguliariai."
  task purge_unattached: :environment do
    ActiveStorage::Blob.unattached.where(created_at: ..2.days.ago).find_each(&:purge_later)
  end
end

ĮSPĖJIMAS: ActiveStorage::Blob.unattached sugeneruota užklausa gali būti lėta ir potencialiai trukdyti didesnių duomenų bazių programoms.

Atsiliepimai

Jūs esate skatinami padėti pagerinti šio vadovo kokybę.

Prašome prisidėti, jei pastebite rašybos klaidų ar faktinių klaidų. Norėdami pradėti, galite perskaityti mūsų dokumentacijos prisidėjimo skyrių.

Taip pat gali būti nepilnos informacijos arba informacijos, kuri nėra atnaujinta. Prašome pridėti bet kokią trūkstamą dokumentaciją pagrindiniam. Patikrinkite Edge vadovus pirmiausia, ar problemas jau išspręsta arba ne pagrindinėje šakoje. Patikrinkite Ruby on Rails vadovų gaires dėl stiliaus ir konvencijų.

Jei dėl kokios nors priežasties pastebite kažką, ką reikia ištaisyti, bet negalite patys tai pataisyti, prašome pranešti apie problemą.

Ir galiausiai, bet ne mažiau svarbu, bet koks diskusijos dėl Ruby on Rails dokumentacijos yra labai laukiamos oficialiame Ruby on Rails forume.