SlideShare a Scribd company logo
Getting Started with Active
Storage
Presentation by: Bishal Khanal & Devyani Dubey
Group name: Web9
Intro
- Built into rails
- Support for Multiple cloud-based storage services such as Amazon S3, Google Cloud Storage and
Microsoft Azure, and on local disk as well.
- Configuration is minimal
- Let’s dive into it
Configuration
- Install Active Storage
rails active_storage:install
Generates a migration that creates two table: active_storage_blobs and
active_storage_attachments
Blob- a record that contains the metadata about a file and a key for where that file resides on
the service
Attachments associate records with blobs.
- Run that migration
rails db:migrate
Configuration (contd)
- Declare Active Storage Services in config/storage.yml
Configuration (contd)
- Tell Active Storage which service to use by setting
Rails.application.config.active_storage.service
Do this on per-environment basis, that is, for development, test and production environment:
- In config/environments/development.rb
# Store files locally.
config.active_storage.service = :local
- In config/environments/production.rb set it to :amazon or any cloud
- In config/environments/test.rb set it to :test
Configuration (In our case)
- In config/environments/development.rb
config.active_storage.service = :local
- In config/environments/production.rb we set it to :local
- In config/environments/test.rb we set it to :test
Note: We used local disk in our production environment. We have to set one more thing to avoid
deletion of our user attachments in storage folder every time we deploy new version. (uploaded
attachment will get stored in storage folder, we set it in config/storage.yml)
In config/deploy.rb, append storage directory
append :linked_dirs, "storage"
Attaching file/files to our model
- Suppose we want to create an avatar for a user profile with other features such as Name, Age, etc. This
is how we generate scaffold/model:
$ rails generate scaffold Profile avatar:attachment name:string age:number
This will set has_one_attached :avatar in Profile.rb file.
OR
$ rails generate scaffold Profile avatar:attachments name:string age:number
This will set has_many_attached :avatars in Profile.rb file.
Uploading attachment (image in this example)
- Model is now ready to accept an image attachment. We can create a form including a file upload input field like:
<%= form_with(model :profile) do |f| %>
<%= f.label :avatar %>
<%= f.file_field :avatar %>
<% end %>
Note: If you have created scaffold then avatar attribute should automatically added to the list of permitted
parameters. Otherwise, don’t forget to add avatar attribute to the list of permitted parameters in the controller
that handles the form.
def profile_params
params.require(:profile).permit(:avatar, :name, :age) # if single attachment
# params.require(:profile).permit(avatar: [], :name, :age) # if multiple attachments
end
Uploading attachment (image in this example)
This <%= f.file_field :avatar %> will let user to select and upload any kind of attachment. If we want
to restrict the file type, we can filter out or restrict user to upload certain kind of attachment by adding
extra accept argument in file_field form helper.
<%= form.file_field :avatar, accept: 'image/png,image/gif,image/jpeg' %>
This will restrict user to select other files except the file with 'image/png,image/gif,image/jpeg' file
format.
Later we will use validations to implement these kinds of restrictions.
Displaying Uploaded attachments (image)
- To display the image that’s attached to the model:
<%= image_tag(@profile.avatar, width: “240px”, height: “auto”) %>
Or
<image src = “<%= url_for(@profile.avatar)” %>
- It’s better if we check if the file is attached or not before displaying ,by enclosing above code inside:
<% if @profile.avatar.attached? %>
<% end %>
Displaying Uploaded attachments (video)
- To display video file attached to the model:
<%= video_tag(url_for(@movie.trailer), width: “240px”, height: “auto”, control=true, poster:
url_for(@movie.poster)) %>
- poster argument in video_tag is to set the thumbnail for the video. If not passed, then the first frame of
the video is used as a thumbnail.
- control argument in video_tag is needed to get the controls for the video, such as play, pause, volume,
time information, full screen, etc. If it is not set to true, then we won’t be able to play the video, but we
can download the video.
- url_for(@movie.trailer) is necessary, just @movie.trailer doesn’t work unlike in image_tag!!
Displaying Uploaded Image
- The image file that we displayed so far is an untouched image file, meaning the file is exactly of the same
size as uploaded by the user. When we saved that displayed image file, the dimensions and the bytes size
of the image was same to that we uploaded (3 MB, dimension- 5k) even though we set the width to to be
240px.
<%= image_tag(@profile.avatar, width: “240px”, height: “auto”) %>
- This is because the Active Storage always stores unaltered copies of uploaded files and it uses that.
- Is it good to use the unaltered big image file in situations where such high quality doesn’t even matter,
like in thumbnail, etc. ? Why use unnecessary extra bandwidth of user and also why increase the loading
time of the user?
- We might want resize an uploaded image to generate a smaller thumbnail image.
Displaying Uploaded Image (Image Variants)
- Active Storage will help us with that.
- It can create something it calls a variant, which is a variation of the original uploaded image which we
can use it like this:
<%= image_tag @profile.avatar.variant(resize_to_limit: [200,nil]) %>
- This resize_to_limit option will downsize the image to fit the specified dimension, here (200, auto)
maintaining the original aspect ratio.
- We can actually create as many as we like, and they are automatically created and stored when
requested.
Displaying Uploaded Image (Image Variants)
- To use this variant we want to do following steps:
- To generate variants for images, Rails uses image_processing gem. This gem is actually present in
Gemfile we just need to uncomment this line in that file:
# Use Active Storage variant
gem 'image_processing', '~> 1.2'
- Then install it with:
$ bundle install
- The image_processing gem relies on ImageMagick to do the actual image transformation.
ImageMagick isn’t a Ruby gem; it’s distributed as a binary that’s specific to the OS on which our
web-app runs. So we need to install it separately on our OS.
Displaying Uploaded Image (Image Variants)
- Installing ImageMagick on different OS.
For LINUX use apt-get:
$ sudo apt-get install imagemagick
For MAC use Homebrew:
$ brew install imagemagick
For Windows use the Windows binary release.
Downloading Attachments
- Getting a downloadable link for the user is easy. You can simply do this to let user download the
active storage attachments:
<%= link_to "Download Trailer", url_for(@movie.trailer) %>
OR SIMPLY
<%= link_to "Download Trailer", @movie.trailer %>
For previous example:
<%= link_to "Profile", @profile.avatar %>
Deleting Attachments
- When we create scaffold of some model, rails provides us with basic CRUD operations. Usually,
while editing or updating, we could remove some fields entirely leaving the field to be empty (if
there is no restrictions on emptiness on that field).
- But removing or deleting the Active Storage Attachments is not straightforward. We can only
update the attachment once uploaded. After that to delete that we have to delete the whole
object.
- We can implement this ‘deleting of the attachment feature’ on our own by calling purge on the
attachment.
profile.avatar.purge
- Purging deletes the blob and the file from the storage service. Background removal of the
attachments can be done by calling purge_later instead.
Deleting Attachments (contd)
- We created separate action to delete the attachment.
def removeAvatar
remove = params[:remove]
if remove
profile = Profile.find(params[:id])
profile.avatar.purge
end
end
- And we provide button to the user to perform this action.
<% if @profile.avatar.attached? %>
<%= button_to "Remove Profile Picture", :remove => true, :action => "removeAvatar",
:id => @profile.id %>
<% end %>
- Don’t forget to add routes in /config/routes.rb -> post 'profiles/removeAvatar'
Testing Controller
- Let’s test if the uploading of image or any attachments is actually working or not.
Consider the previous Profile example with attributes avatar (attachment), name (string), age (number).
Testing Controller
- profile.xml fixture contains:
one:
user_id: 1
name: "Bishal"
age: 26
As you can see there is no avatar attachment in the fixture. So how will we supply image attachments in
the parameter for the post request?
avatar: fixture_file_upload("test.JPG", “image/jpeg”)
Use fixture_file_upload function to do that. The first argument is file name and second argument is file
type (mime type or content type), and this test image file should be kept inside /test/fixtures/files
directory.
Testing Controller
- This is a portion of our profiles_controller_test.rb :
test "should create profile" do
assert_difference('Profile.count') do
post profiles_url, params: {
profile: {avatar: fixture_file_upload("test.JPG","image/jpeg"),
age: @profile.age, name: @profile.name }
}
end
assert_redirected_to profile_url(Profile.last)
profile = Profile.order(:created_at).last
assert profile.avatar.attached?
end
Testing Controller
- The last two lines checks if the recently added profile contains avatar attached to it or not.
profile = Profile.order(:created_at).last
assert profile.avatar.attached?
- That’s all!
Acceptance Tests or Behaviour testing
- To do this, we need to upload attachment to the avatar field of Profile (our example). We can use this
function for that:
attach_file("Avatar", File.join(Rails.root, 'features', 'upload_files', 'test.JPG'))
for this view form:
<div class="col-md-6">
<label for="profile_avatar">Avatar</label>
<input type="file" name="profile[avatar]" id="profile_avatar" />
</div>
where, "Avatar" is the attachment label, (name and id can also be used) and File.join(Rails.root,
'features', 'upload_files', 'test.JPG') provides the location (/features/upload_files/test.JPG) and
filename of the test image test.JPG.
Adding Validations
- Up until now, users can actually attach any kind of files, such as .pdf, .txt, etc. instead of files with image
file extensions such as .jpg, .png, etc. which we actually want. But we can’t trust users. We should do it on
our own to allow only the valid files.
- Does Active Storage include build-in validations? Unfortunately, the answer is NO!!
- BUT, Thankfully it’s surprisingly easy to write custom validations.
Adding Validations (contd)
- Register a custom validation method. Here we named acceptable_image
validate :acceptable_image
- Define this validation method:
def acceptable_image
end
- with code accepting only jpeg and png image file, rejecting every other image file formats and other file formats with error telling
avatar must be a JPEG or PNG
acceptable_types = ["image/jpeg", "image/png"]
unless acceptable_types.include?(avatar.content_type)
errors.add(:avatar, "must be a JPEG or PNG")
end
- using content_type attribute of the attachment avatar.content_type
Adding Validations (contd)
- Portion of our code in Profile.rb, to validate the uploaded attachment in image in png or jpg format or
not.
validate :acceptable_image
def acceptable_image
return unless avatar.attached?
acceptable_types = ["image/jpeg", "image/png"]
unless acceptable_types.include?(avatar.content_type)
errors.add(:avatar, "must be a JPEG or PNG")
end
Adding Validations (contd)
- Similarly, we can restrict the uploaded image size (2 MB in this example). Inside the acceptable_image
definition
.
.
.
unless avatar.byte_size <= 2.megabyte
errors.add(:avatar, "is too big")
end
.
.
.
Adding Validations (contd)
- These are the minimum validation that we want to add. But there could be many other things that we
may want to consider in future.
- As an alternative to writing custom validation functions there are some Active Storage Validations gem
available that may have included other variety of validations that maybe important to us. Here is a link to
one of such gems:
https://github.com/igorkasyanchuk/active_storage_validations
References:
- Pragmatic Studio
- Active Storage Rails Guide
Things that needs to be addressed:
We need to address following things:
- Rails default video player lets user to download the content. We can use other video player on
top of that to hide that feature.
- Even though we let only authenticated users and authorized users to perform certain actions,
but once they get the link to our content then anybody can use that link to watch and download
the content without even signing in. We should find a way to avoid this, like creating redirect or
temporary link with expiration period, etc.

More Related Content

PDF
Unit 1 Kali NetHunter is the official Kali Linux penetration testing platform...
PDF
Cognitive Complexity でコードの複雑さを定量的に計測しよう
PDF
Introduction to JADE (Java Agent DEvelopment) Framework
PDF
Emacs上のターミナルを最強に
PPTX
Hosting a website on IIS Server
PDF
FreeSWITCH Cluster by K8s
PDF
AWS Fargate와 Amazon ECS를 사용한 CI/CD 베스트 프랙티스 - 유재석, AWS 솔루션즈 아키텍트 :: AWS Build...
PDF
pgpool-II demonstration
Unit 1 Kali NetHunter is the official Kali Linux penetration testing platform...
Cognitive Complexity でコードの複雑さを定量的に計測しよう
Introduction to JADE (Java Agent DEvelopment) Framework
Emacs上のターミナルを最強に
Hosting a website on IIS Server
FreeSWITCH Cluster by K8s
AWS Fargate와 Amazon ECS를 사용한 CI/CD 베스트 프랙티스 - 유재석, AWS 솔루션즈 아키텍트 :: AWS Build...
pgpool-II demonstration

What's hot (20)

PPTX
Saying Hello to Bug Bounty
PDF
Jenkins with Unity3d & Android
PDF
Red Hat Enterprise Linux 8 Workshop
PDF
높은 가용성과 성능 향상을 위한 ElastiCache 활용 팁 - 임근택, SendBird :: AWS Summit Seoul 2019
PDF
Web Saldırı Teknikleri & Korunma Yöntemleri
KEY
テスト駆動開発入門
PPTX
Building RESTful Java Applications with EMF
PDF
AWS re:Invent re:Cap - 비용 최적화: 모범사례와 아키텍처 설계 기초편 - 이종남
PPTX
Getting Started with React.js
PPTX
Công nghệ ảo hóa
PDF
Arm 기반의 AWS Graviton 프로세서로 구동되는 AWS 인스턴스 살펴보기 - 김종선, AWS솔루션즈 아키텍트:: AWS Summi...
PPTX
Introduction to Facebook React
PDF
Prisma the ORM that node was waiting for
PDF
セキュリティを楽しむ(CTFとbugbountyの始め方)
PDF
Fargate 를 이용한 ECS with VPC 1부
PDF
Automatic Vectorization in ART (Android RunTime) - SFO17-216
PDF
[온라인교육시리즈] 글로벌 서비스를 위한 인프라 구축방법(남용현 클라우드 솔루션 아키텍트)
PDF
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
PDF
DBI-Assisted Android Application Reverse Engineering
PPT
Spring Core
Saying Hello to Bug Bounty
Jenkins with Unity3d & Android
Red Hat Enterprise Linux 8 Workshop
높은 가용성과 성능 향상을 위한 ElastiCache 활용 팁 - 임근택, SendBird :: AWS Summit Seoul 2019
Web Saldırı Teknikleri & Korunma Yöntemleri
テスト駆動開発入門
Building RESTful Java Applications with EMF
AWS re:Invent re:Cap - 비용 최적화: 모범사례와 아키텍처 설계 기초편 - 이종남
Getting Started with React.js
Công nghệ ảo hóa
Arm 기반의 AWS Graviton 프로세서로 구동되는 AWS 인스턴스 살펴보기 - 김종선, AWS솔루션즈 아키텍트:: AWS Summi...
Introduction to Facebook React
Prisma the ORM that node was waiting for
セキュリティを楽しむ(CTFとbugbountyの始め方)
Fargate 를 이용한 ECS with VPC 1부
Automatic Vectorization in ART (Android RunTime) - SFO17-216
[온라인교육시리즈] 글로벌 서비스를 위한 인프라 구축방법(남용현 클라우드 솔루션 아키텍트)
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
DBI-Assisted Android Application Reverse Engineering
Spring Core
Ad

Similar to Getting started with rails active storage wae (20)

DOC
File uploading through paperclip in rails 3.x
PDF
 Active Storage - Modern File Storage? 
PDF
File Upload 2015
PPTX
12 Introduction to Rails
PDF
Rails Plugins - Linux For You, March 2011 Issue
PDF
Rails 4.0
PDF
Rupicon 2014 Action pack
PDF
QConSP 2015 - Dicas de Performance para Aplicações Web
PDF
Getting Started with Rails
ZIP
Rails 3 (beta) Roundup
PDF
Pragmatic Patterns of Ruby on Rails - Ruby Kaigi2009
PPTX
Learning to code for startup mvp session 3
PDF
Very Xd Hw9
PDF
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
PDF
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
PDF
Ruby On Rails
PPT
Ruby On Rails
PDF
RubyOnRails-Cheatsheet-BlaineKendall
PDF
RubyOnRails-Cheatsheet-BlaineKendall
KEY
Rails Model Basics
File uploading through paperclip in rails 3.x
 Active Storage - Modern File Storage? 
File Upload 2015
12 Introduction to Rails
Rails Plugins - Linux For You, March 2011 Issue
Rails 4.0
Rupicon 2014 Action pack
QConSP 2015 - Dicas de Performance para Aplicações Web
Getting Started with Rails
Rails 3 (beta) Roundup
Pragmatic Patterns of Ruby on Rails - Ruby Kaigi2009
Learning to code for startup mvp session 3
Very Xd Hw9
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby On Rails
Ruby On Rails
RubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendall
Rails Model Basics
Ad

Recently uploaded (20)

PPTX
Pharmacology of Heart Failure /Pharmacotherapy of CHF
PDF
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
PPTX
GDM (1) (1).pptx small presentation for students
PDF
BÀI TẬP BỔ TRỢ 4 KỸ NĂNG TIẾNG ANH 9 GLOBAL SUCCESS - CẢ NĂM - BÁM SÁT FORM Đ...
PDF
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
PDF
FourierSeries-QuestionsWithAnswers(Part-A).pdf
PDF
2.FourierTransform-ShortQuestionswithAnswers.pdf
PDF
Abdominal Access Techniques with Prof. Dr. R K Mishra
PDF
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
PPTX
Cell Structure & Organelles in detailed.
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PPTX
Renaissance Architecture: A Journey from Faith to Humanism
PPTX
human mycosis Human fungal infections are called human mycosis..pptx
PDF
Insiders guide to clinical Medicine.pdf
PDF
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
PDF
O7-L3 Supply Chain Operations - ICLT Program
PDF
102 student loan defaulters named and shamed – Is someone you know on the list?
PDF
TR - Agricultural Crops Production NC III.pdf
PDF
Complications of Minimal Access Surgery at WLH
PPTX
school management -TNTEU- B.Ed., Semester II Unit 1.pptx
Pharmacology of Heart Failure /Pharmacotherapy of CHF
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
GDM (1) (1).pptx small presentation for students
BÀI TẬP BỔ TRỢ 4 KỸ NĂNG TIẾNG ANH 9 GLOBAL SUCCESS - CẢ NĂM - BÁM SÁT FORM Đ...
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
FourierSeries-QuestionsWithAnswers(Part-A).pdf
2.FourierTransform-ShortQuestionswithAnswers.pdf
Abdominal Access Techniques with Prof. Dr. R K Mishra
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
Cell Structure & Organelles in detailed.
Supply Chain Operations Speaking Notes -ICLT Program
Renaissance Architecture: A Journey from Faith to Humanism
human mycosis Human fungal infections are called human mycosis..pptx
Insiders guide to clinical Medicine.pdf
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
O7-L3 Supply Chain Operations - ICLT Program
102 student loan defaulters named and shamed – Is someone you know on the list?
TR - Agricultural Crops Production NC III.pdf
Complications of Minimal Access Surgery at WLH
school management -TNTEU- B.Ed., Semester II Unit 1.pptx

Getting started with rails active storage wae

  • 1. Getting Started with Active Storage Presentation by: Bishal Khanal & Devyani Dubey Group name: Web9
  • 2. Intro - Built into rails - Support for Multiple cloud-based storage services such as Amazon S3, Google Cloud Storage and Microsoft Azure, and on local disk as well. - Configuration is minimal - Let’s dive into it
  • 3. Configuration - Install Active Storage rails active_storage:install Generates a migration that creates two table: active_storage_blobs and active_storage_attachments Blob- a record that contains the metadata about a file and a key for where that file resides on the service Attachments associate records with blobs. - Run that migration rails db:migrate
  • 4. Configuration (contd) - Declare Active Storage Services in config/storage.yml
  • 5. Configuration (contd) - Tell Active Storage which service to use by setting Rails.application.config.active_storage.service Do this on per-environment basis, that is, for development, test and production environment: - In config/environments/development.rb # Store files locally. config.active_storage.service = :local - In config/environments/production.rb set it to :amazon or any cloud - In config/environments/test.rb set it to :test
  • 6. Configuration (In our case) - In config/environments/development.rb config.active_storage.service = :local - In config/environments/production.rb we set it to :local - In config/environments/test.rb we set it to :test Note: We used local disk in our production environment. We have to set one more thing to avoid deletion of our user attachments in storage folder every time we deploy new version. (uploaded attachment will get stored in storage folder, we set it in config/storage.yml) In config/deploy.rb, append storage directory append :linked_dirs, "storage"
  • 7. Attaching file/files to our model - Suppose we want to create an avatar for a user profile with other features such as Name, Age, etc. This is how we generate scaffold/model: $ rails generate scaffold Profile avatar:attachment name:string age:number This will set has_one_attached :avatar in Profile.rb file. OR $ rails generate scaffold Profile avatar:attachments name:string age:number This will set has_many_attached :avatars in Profile.rb file.
  • 8. Uploading attachment (image in this example) - Model is now ready to accept an image attachment. We can create a form including a file upload input field like: <%= form_with(model :profile) do |f| %> <%= f.label :avatar %> <%= f.file_field :avatar %> <% end %> Note: If you have created scaffold then avatar attribute should automatically added to the list of permitted parameters. Otherwise, don’t forget to add avatar attribute to the list of permitted parameters in the controller that handles the form. def profile_params params.require(:profile).permit(:avatar, :name, :age) # if single attachment # params.require(:profile).permit(avatar: [], :name, :age) # if multiple attachments end
  • 9. Uploading attachment (image in this example) This <%= f.file_field :avatar %> will let user to select and upload any kind of attachment. If we want to restrict the file type, we can filter out or restrict user to upload certain kind of attachment by adding extra accept argument in file_field form helper. <%= form.file_field :avatar, accept: 'image/png,image/gif,image/jpeg' %> This will restrict user to select other files except the file with 'image/png,image/gif,image/jpeg' file format. Later we will use validations to implement these kinds of restrictions.
  • 10. Displaying Uploaded attachments (image) - To display the image that’s attached to the model: <%= image_tag(@profile.avatar, width: “240px”, height: “auto”) %> Or <image src = “<%= url_for(@profile.avatar)” %> - It’s better if we check if the file is attached or not before displaying ,by enclosing above code inside: <% if @profile.avatar.attached? %> <% end %>
  • 11. Displaying Uploaded attachments (video) - To display video file attached to the model: <%= video_tag(url_for(@movie.trailer), width: “240px”, height: “auto”, control=true, poster: url_for(@movie.poster)) %> - poster argument in video_tag is to set the thumbnail for the video. If not passed, then the first frame of the video is used as a thumbnail. - control argument in video_tag is needed to get the controls for the video, such as play, pause, volume, time information, full screen, etc. If it is not set to true, then we won’t be able to play the video, but we can download the video. - url_for(@movie.trailer) is necessary, just @movie.trailer doesn’t work unlike in image_tag!!
  • 12. Displaying Uploaded Image - The image file that we displayed so far is an untouched image file, meaning the file is exactly of the same size as uploaded by the user. When we saved that displayed image file, the dimensions and the bytes size of the image was same to that we uploaded (3 MB, dimension- 5k) even though we set the width to to be 240px. <%= image_tag(@profile.avatar, width: “240px”, height: “auto”) %> - This is because the Active Storage always stores unaltered copies of uploaded files and it uses that. - Is it good to use the unaltered big image file in situations where such high quality doesn’t even matter, like in thumbnail, etc. ? Why use unnecessary extra bandwidth of user and also why increase the loading time of the user? - We might want resize an uploaded image to generate a smaller thumbnail image.
  • 13. Displaying Uploaded Image (Image Variants) - Active Storage will help us with that. - It can create something it calls a variant, which is a variation of the original uploaded image which we can use it like this: <%= image_tag @profile.avatar.variant(resize_to_limit: [200,nil]) %> - This resize_to_limit option will downsize the image to fit the specified dimension, here (200, auto) maintaining the original aspect ratio. - We can actually create as many as we like, and they are automatically created and stored when requested.
  • 14. Displaying Uploaded Image (Image Variants) - To use this variant we want to do following steps: - To generate variants for images, Rails uses image_processing gem. This gem is actually present in Gemfile we just need to uncomment this line in that file: # Use Active Storage variant gem 'image_processing', '~> 1.2' - Then install it with: $ bundle install - The image_processing gem relies on ImageMagick to do the actual image transformation. ImageMagick isn’t a Ruby gem; it’s distributed as a binary that’s specific to the OS on which our web-app runs. So we need to install it separately on our OS.
  • 15. Displaying Uploaded Image (Image Variants) - Installing ImageMagick on different OS. For LINUX use apt-get: $ sudo apt-get install imagemagick For MAC use Homebrew: $ brew install imagemagick For Windows use the Windows binary release.
  • 16. Downloading Attachments - Getting a downloadable link for the user is easy. You can simply do this to let user download the active storage attachments: <%= link_to "Download Trailer", url_for(@movie.trailer) %> OR SIMPLY <%= link_to "Download Trailer", @movie.trailer %> For previous example: <%= link_to "Profile", @profile.avatar %>
  • 17. Deleting Attachments - When we create scaffold of some model, rails provides us with basic CRUD operations. Usually, while editing or updating, we could remove some fields entirely leaving the field to be empty (if there is no restrictions on emptiness on that field). - But removing or deleting the Active Storage Attachments is not straightforward. We can only update the attachment once uploaded. After that to delete that we have to delete the whole object. - We can implement this ‘deleting of the attachment feature’ on our own by calling purge on the attachment. profile.avatar.purge - Purging deletes the blob and the file from the storage service. Background removal of the attachments can be done by calling purge_later instead.
  • 18. Deleting Attachments (contd) - We created separate action to delete the attachment. def removeAvatar remove = params[:remove] if remove profile = Profile.find(params[:id]) profile.avatar.purge end end - And we provide button to the user to perform this action. <% if @profile.avatar.attached? %> <%= button_to "Remove Profile Picture", :remove => true, :action => "removeAvatar", :id => @profile.id %> <% end %> - Don’t forget to add routes in /config/routes.rb -> post 'profiles/removeAvatar'
  • 19. Testing Controller - Let’s test if the uploading of image or any attachments is actually working or not. Consider the previous Profile example with attributes avatar (attachment), name (string), age (number).
  • 20. Testing Controller - profile.xml fixture contains: one: user_id: 1 name: "Bishal" age: 26 As you can see there is no avatar attachment in the fixture. So how will we supply image attachments in the parameter for the post request? avatar: fixture_file_upload("test.JPG", “image/jpeg”) Use fixture_file_upload function to do that. The first argument is file name and second argument is file type (mime type or content type), and this test image file should be kept inside /test/fixtures/files directory.
  • 21. Testing Controller - This is a portion of our profiles_controller_test.rb : test "should create profile" do assert_difference('Profile.count') do post profiles_url, params: { profile: {avatar: fixture_file_upload("test.JPG","image/jpeg"), age: @profile.age, name: @profile.name } } end assert_redirected_to profile_url(Profile.last) profile = Profile.order(:created_at).last assert profile.avatar.attached? end
  • 22. Testing Controller - The last two lines checks if the recently added profile contains avatar attached to it or not. profile = Profile.order(:created_at).last assert profile.avatar.attached? - That’s all!
  • 23. Acceptance Tests or Behaviour testing - To do this, we need to upload attachment to the avatar field of Profile (our example). We can use this function for that: attach_file("Avatar", File.join(Rails.root, 'features', 'upload_files', 'test.JPG')) for this view form: <div class="col-md-6"> <label for="profile_avatar">Avatar</label> <input type="file" name="profile[avatar]" id="profile_avatar" /> </div> where, "Avatar" is the attachment label, (name and id can also be used) and File.join(Rails.root, 'features', 'upload_files', 'test.JPG') provides the location (/features/upload_files/test.JPG) and filename of the test image test.JPG.
  • 24. Adding Validations - Up until now, users can actually attach any kind of files, such as .pdf, .txt, etc. instead of files with image file extensions such as .jpg, .png, etc. which we actually want. But we can’t trust users. We should do it on our own to allow only the valid files. - Does Active Storage include build-in validations? Unfortunately, the answer is NO!! - BUT, Thankfully it’s surprisingly easy to write custom validations.
  • 25. Adding Validations (contd) - Register a custom validation method. Here we named acceptable_image validate :acceptable_image - Define this validation method: def acceptable_image end - with code accepting only jpeg and png image file, rejecting every other image file formats and other file formats with error telling avatar must be a JPEG or PNG acceptable_types = ["image/jpeg", "image/png"] unless acceptable_types.include?(avatar.content_type) errors.add(:avatar, "must be a JPEG or PNG") end - using content_type attribute of the attachment avatar.content_type
  • 26. Adding Validations (contd) - Portion of our code in Profile.rb, to validate the uploaded attachment in image in png or jpg format or not. validate :acceptable_image def acceptable_image return unless avatar.attached? acceptable_types = ["image/jpeg", "image/png"] unless acceptable_types.include?(avatar.content_type) errors.add(:avatar, "must be a JPEG or PNG") end
  • 27. Adding Validations (contd) - Similarly, we can restrict the uploaded image size (2 MB in this example). Inside the acceptable_image definition . . . unless avatar.byte_size <= 2.megabyte errors.add(:avatar, "is too big") end . . .
  • 28. Adding Validations (contd) - These are the minimum validation that we want to add. But there could be many other things that we may want to consider in future. - As an alternative to writing custom validation functions there are some Active Storage Validations gem available that may have included other variety of validations that maybe important to us. Here is a link to one of such gems: https://github.com/igorkasyanchuk/active_storage_validations
  • 29. References: - Pragmatic Studio - Active Storage Rails Guide
  • 30. Things that needs to be addressed: We need to address following things: - Rails default video player lets user to download the content. We can use other video player on top of that to hide that feature. - Even though we let only authenticated users and authorized users to perform certain actions, but once they get the link to our content then anybody can use that link to watch and download the content without even signing in. We should find a way to avoid this, like creating redirect or temporary link with expiration period, etc.