المكتبة Active Storage في ريلز

من موسوعة حسوب

يجعل Active Storage عملية رفع الملفات وإنشاء مرجع لها في أي خدمة سحابية - مثل Amazon S3، أو Google Cloud Storage، أو Microsoft Azure Storage - وربطها بنماذج Active Record عمليةً بسيطةً وسهلةً. يدعم أيضًا امتلاك خدمة تخزين أساسية في خدمة سحابية، وخدمة تخزين انعكاسية (mirror) في خدمات سحابية أخرى وذلك من أجل تحقيق التوافر الدائم. أضف إلى ذلك أنه يوفر خدمة التخزين على قرص صلب (disk service) للفحص أو النشر المحلي ولكن التركيز الأساسي ينصب على التخزين السحابي.

يمكن رفع الملفات من الخادم إلى السحابة أو من العميل إلى السحابة مباشرةً.

إضافة لذلك، يمكن تحويل ملفات الصور من ناحية الجودة أو نسبة العرض إلى الارتفاع، أو الحجم، أو أي عملية تحويل أخرى مدعومة (مثل  MiniMagick و Vips).

يمكنك قراءة المزيد حول Active Storage في دليل نظرة عامة على Active Storage.

الموازنة مع خيارات تخزين أخرى

الاختلاف الجوهري لعمل Active Storage موازنةً مع وسائل التخزين الأخرى المرفقة مع ريلز هو عبر استعمال النموذج Blob (كائن بيانات ثنائية) والنموذج Attachment (المرفقات) المدعومين من قبل Active Record. هذا يعني عدم الحاجة إلى تعديل نماذج التطبيق الموجودة مسبقًا مع حقول إضافية يراد ربطها مع ملفات. يستعمل Active Storage ارتباطات متعددة الأشكال عبر نموذج الربط Attachment الذي يرتبط بعدها مع النموذج Bolb الفعلي.

نماذج Blob تخزن البيانات الوصفية المرفقة (اسم الملف، ونوع المحتوى ...إلخ)، ومفتاح المعرف الخاص بها في خدمة التخزين. لا تخزن نماذج Blob البيانات الثنائية الفعلية، وتعدُّ غير قابلة للتعديل. ملف واحد يعني نموذج Blob واحد (أي كائن بيانات ثنائي واحد). يمكنك ربط نفس كائن بيانات ثنائي (Blob) مع عدة نماذج للتطبيق أيضًا. وإن أردت إجراء عمليات تحويل لكائن Blob معطى، فالفكرة هي أنك ستنشئ ببساطة كائن آخر جديد بدلًا من محاول تعديل الموجود مسبقًا (رغم أنك تستطيع حذف الإصدار السابق لاحقًا إن لم تعد بحاجة إليه).

التنزيل

نفذ الأمر rails active_storage:install لنسخ التهجيرات active_storage.

ملاحظة: إن لم يُعثَر على المهمة، تأكد من وجود "require "active_storage/engine في الملف config/application.rb.

أمثلة

مرفق واحد:

class User < ApplicationRecord
  # ربط مرفق وكائن بيانات ثنائي. عند حذف المستخدم، سيزالا افتراضيًّا
  # إذ تُدمَّر النماذج وتُحذَف ملفات الموارد
  has_one_attached :avatar
end

# ربط صورة رمزية بالمستخدم
user.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/jpg")

# هل يملك المستخدم صورة رمزية؟
user.avatar.attached? # => true

# تدمير الصورة الرمزية وملفات الموارد الحقيقية بشكل متزامن
user.avatar.purge

# Active Job تدمير النماذج المرتبطة وملفات الموارد الحقيقية بشكل غير متزامن عبر
user.avatar.purge_later

# هل يملك المستخدم صورة رمزية؟
user.avatar.attached? # => false

# .دائم لكائن البيانات الثنائي الذي يشير إلى التطبيق URL توليد رابط
# .عند الوصول إليه، يعاد التوجيه إلى الخدمة الفعلية النهائية
# العام عن العنوان الفعلي وتسمح مثلًا بعكس  URL هذه المراوغة تفصل عنوان
# المرفقات على خدمةتخزين مختلفة للحرص على توفيرها بشكل دائم.  تملك
# تساوي 5 دقائق HTTP عملية إعادة التوجيه مدة انتهاء لطلبية
url_for(user.avatar)

class AvatarsController < ApplicationController
  def update
    # ActionDispatch::Http::UploadedFile الكائن params[:avatar] يحوي
    Current.user.avatar.attach(params.require(:avatar))
    redirect_to Current.user
  end
end

عدة مرفقات:

class Message < ApplicationRecord
  has_many_attached :images
end
<%= form_with model: @message, local: true do |form| %>
  <%= form.text_field :title, placeholder: "Title" %><br>
  <%= form.text_area :content %><br><br>

  <%= form.file_field :images, multiple: true %><br>
  <%= form.submit %>
<% end %>
class MessagesController < ApplicationController
  def index
    # Use the built-in with_attached_images scope to avoid N+1
    @messages = Message.all.with_attached_images
  end

  def create
    message = Message.create! params.require(:message).permit(:title, :content)
    message.images.attach(params[:message][:images])
    redirect_to message
  end

  def show
    @message = Message.find(params[:id])
  end
end

تغيير الصورة المرفقة:

<%# Hitting the variant URL will lazy transform the original blob and then redirect to its new service location %>
<%= image_tag user.avatar.variant(resize_to_limit: [100, 100]) %>

التحميل المباشر

يدعم Active Storage، مع مكتبة JavaScript المضمنة فيه، التحميل المباشر من العميل إلى السحابة.

تثبيت التحميل التلقائي

//= require activestorage

باستعمال npm:

require("@rails/activestorage").start()
  • علِّق مدخلات الملفات مع عنوان URL للتحميل المباشر:
    <%= form.file_field :attachments, multiple: true, direct_upload: true %>
    
  • هذا كل ما في الأمر! يجب أن تبدأ عملية التحيمل التحميل بدءًا من إرسال الاستمارة.

التحميل التلقائي لأحداث JavaScript

اسم الحدث الوسم المستهدف بيانات الحدث

(event.detail)

الوصف
direct-uploads:start <form> None أرسلت استمارة تحوي ملفات للتحميل المباشر للحقولها.
direct-upload:initialize <input> {id, file} يرسل مع كل ملف على حدة بعد إرسال الاستمارة.
direct-upload:start <input> {id, file} بدء التحميل المباشر.
direct-upload:before-blob-request <input> {id, file, xhr} قبل إنشاء طلبية لتطبيقك لتحميل البيانات الوصفية بشكل مباشر.
direct-upload:before-storage-request <input> {id, file, xhr} قبل إنشاء طلبية لتخزين ملف.
direct-upload:progress <input> {id, file, progress} مثل الطلبيات لتخزين تقدم تخزين الملفات.
direct-upload:error <input> {id, file, error} خطأ قد حصل. سيُظهَر تنبيه alert ما لم يُلغَى هذا الحدث.
direct-upload:end <input> {id, file} انتهاء عملية التحميل المباشرة.
direct-uploads:end <form> None انتهاء جميع عمليات التحميل المباشر.

مصادر