Skip to content

Instantly share code, notes, and snippets.

@ecmelkytz
Last active May 29, 2018 13:01
Show Gist options
  • Save ecmelkytz/9f2e4f8a34740ecda2c685cf5a84e7f2 to your computer and use it in GitHub Desktop.
Save ecmelkytz/9f2e4f8a34740ecda2c685cf5a84e7f2 to your computer and use it in GitHub Desktop.

ActiveStorage

1. ActiveStorage Nedir?

Rails 5.2 ile gelen ActiveStorage özelliği, dosyaları Amazon S3, Google Cloud, Microsoft Azure Cloud gibi cloud bir servise upload etmemizi sağlar.

2. Kurulum

rails active_storage:install

Bu çalıştırılan kod active_storage_blobs ve active_storage_attachments tablolarını oluşturan bir migrate dosyası ve servis konfigürasyonları için config altında storage.yml dosyası oluşturur.

3. ActiveStorage'ın Temel Sınıfları

  • ActiveStorage::Service
  • ActiveStorage::Blob
  • ActiveStorage::Attachment

3.1 ActiveStorage::Service

Service sadece baytların hareketinden sorumlu kısımdır. Dosyanın baytlarını bellekten ve browserdan alıp disk'e taşır.

class ActiveStorage::Service
  def upload(key, io, checksum: nil)
    raise NotImplementedError
  end
  def download(key)
    raise NotImplementedError
  end
end

ActiveStorage::Service aslında bir patterndir. Sadece bir tane service değil, birden fazla subclass var. Yani ActiveStorage::Service'i direk çağırıp metodlarını kullanamayız. Onun subclass'larından biriyle çağırabiliriz. Tüm subclass'larda upload ve download metodu mevcut çünkü her servis kendi gerçeklemesini farklı bir yol ile yapmaktadır.

Disk alt sınıfı: class ActiveStorage::Service::DiskService < Service

S3 alt sınıf: class ActiveStorage::Service::S3Service < Service

Farklı bir servis kullanmak istiyorsak bu pattern doğrultusunda oluşturup kullanabiliriz. ActiveStorage şu an Disk, Amazon S3, Microsoft Azure Storage, Google Cloud Storage, Mirror servislerini desteklemektedir.

3.1.1 Yeni Servis Konfigürasyonu

storage.yml içerisinde default servis olarak Disk kullanılmaktadır. Hangi servisi kullanmak istiyorsak onu belirtmeliyiz. Örneğin Amazon S3 servisini eklemek için aşağıdaki gibi bir düzenleme yapmamız ve aws-sdk-s3 gem'ini Gemfile'a eklememiz gerekmektedir.

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

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

3.1.2 Mirror Servis Özelliği

Birden fazla servisi senkronize olarak mirror servis olarak kullanarak yedekli çalışabiliriz. Bir dosya eklendiğinde veya silindiğinde bütün mirror edilmiş servislere aynı anda yansıtılır. Bu özellik production'da servisler arası geçişi kolaylaştırmak için kullanılabilir.

Mirror servis örneği:

s3_west_coast:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  ...
 
s3_east_coast:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  ...
 
production:
  service: Mirror
  primary: s3_east_coast
  mirrors:
    - s3_west_coast

Dosyalar primary servisden sunulur.

3.2 ActiveStorage::Blob

Blob; dosya adı, content-type gibi metadataların tutulduğu yerdir. Dosyanın aslı depolama servisinde ya da diskte saklanır. Her blob’un depolama servisinde identifier key'i vardır.

create_table :active_storage_blobs do |t|
  t.string   :key,        null: false
  t.string   :filename,   null: false
  t.string   :content_type
  t.text     :metadata
  t.bigint   :byte_size,  null: false
  t.string   :checksum,   null: false
  t.datetime :created_at, null: false

  t.index [ :key ], unique: true
end

3.3 ActiveStorage::Attachment

Attachment, blob ile model arasında bağlantıyı sağlar. Bir blob birden fazla modelle bağlantılı olabilir.

create_table :active_storage_attachments do |t|
  t.string     :name,     null: false
  t.references :record,   null: false, polymorphic: true, index: false
  t.references :blob,     null: false
  t.datetime :created_at, null: false

  t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
end

4. Nasıl dosya eklenir?

Car adında bir modeliniz var diyelim ve araba resimlerini tutmak için dosya upload etmek istiyorsunuz. O halde yapacağınız ilk iş bir migration dosyası ile modelinize resimleri tutacağınız yeni bir kolon eklemeniz olacaktır. Bu upload yapmak istediğiniz her model için geçerlidir.

ActiveStorage ise diğer dosya upload çözümlerinden biraz farklı çalışır. ActiveStorage'da modelinize yeni bir field eklemeye gerek yoktur. Dosya ile ilgili bütün bilgiler activestorage install edilirken oluşturulan blobs ve attachments tablolarında tutulmaktadır.

4.1 Bir dosya attach etmek için yapılması gerekenler

class Car < ApplicationRecord
  has_one_attached :image
end

# strong_parameters
params.require(:car).permit(:name, :image)

4.2 Birden fazla dosya attach etmek için yapılması gerekenler

class Car < ApplicationRecord
  has_many_attached :images
end

# strong_parameters
params.require(:car).permit(:name, images: [])

5. Transformation İşlemleri

Transforming işlemcilerin(processor) destekleği metodlar ölçüsünde bloblar üzerinde resimlerin varyasyonlarını oluşturabiliriz. Default processor olarak MiniMagick kullanılmaktadır ancak Vips'de kullanılabilir.

Biçimlendirmeyi etkinleştirmek için image_processing gemi kullanılmaktadır. Bununla ilgili pull request.

gem 'image_processing', '~> 1.2'

Aşağıdaki satır yorumlandığı zaman bir defaya mahsus orijinal blob'un biçimlendirilmiş halinin URL'i oluşturulur ve dosyalarınız nerede tutuluyorsa disk/cloud oraya kaydedilir.

<%= image_tag @cat.image.variant(resize: "100x100") %>

6. Direk Upload

ActiveStorage bir ruby gemi olmasının yanında bünyesinde javascript kütüphanesi de barındırır. Dosyalarımızı Rails uygulamasına değil de direk cloud bir servise upload etmek istediğimiz zaman bu javascript kodları devreye girmektedir.

Blob oluşurken bir identifier key üretilir ve dosya bu key ile cloud servise upload edilir. Resme tekrar ulaşmak istediğimizde bu key ile bağlantı kurulup erişilmektedir. Direk upload işleminde blob oluşturulma ve resmin store edilme sıralamasında değişiklik olur.

Direk upload işlemi için

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

7. Tartışma

Rails dosya upload işlemleri için carrierview, paperclip, refine gibi bir çok güzel kütüphaneye sahip. Hepsinin kendi içinde farklı yaklaşımları var. Doğru bir tercih için ihtiyaçlar belirlenmeli ve kütüphanelerin özellik setine bakılarak bir seçim yapılmalıdır.

Paperclip geliştiricileri artık Rails'in kendi upload çözümü olan ActiveStorage'ın kullanımını tavsiye ediyor. Paperclip ile ActiveStorage'ı karşılaştıracak olursak dosya validasyonları konusunda ActiveStorage'ın şu an için güzel bir çözümü yok. Bununla ilgili file_validators gibi 3rd party çözüm önerileri var ya da custom validasyon yazılması gerekiyor.

"ActiveStrorage'ı kullanalım mı?, ActiveStorage'a geçiş yapalım mı?" tarzında sorulara araştırmalarım sonucunda şöyle bir cevap elde ettim diyebilirim:

Uygulamanızda halihazırda kullandığınız bir upload çözümü var ve siz bundan memnunsanız ActiveStorage'a geçiş yapmanız için değerli bir sebebiniz yok demektir. Böyle bir durumda, ActiveStrorage'da bulunan bir özelliği kullanmak istiyorsanız geçiş yapabilirsiniz. Mirror servis özelliği gibi. Yani başka bir upload çözümüne geçiş yapmayı düşünüyorsanız bunu kullanmak istediğiniz özellik bazında karar verin.

Eğer yeni bir uygulamaya başlıyorsanız ActiveStorage'ı deneyin.

8. Kaynakça

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment