Rails Uploading Images And Rich Text With ActiveStorage

Techie     November 2022

Introduction

Image upload in Rails is easy to implement with ActiveStorage. We can also implement action_text for image uploading but also as a toolkit for handling rich text content & editing and file attachments in general.

In this section, we are going to be setting up ActiveStorage and action_text to upload images to our Rails application in simple steps.


Prerequisites

Rails 7.0.4
Ruby 3.2.0


Part A: Install and Configure ActiveStorage

1. Install active_storage and action_text

$ rails active_storage:install;

$ rails g action_text:install;

$ rails db:migrate


ii). Uncomment image_processing gem in Gemfile

 
#...

# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
gem "image_processing", "~> 1.2"
  


iii). Bundle up

 

$ bundle install


2. Install ImageMagick

Active storage will require image processing to resize the images. vips is the default image processor but we’ll use imagemagick.


i) Switch image processing from vips to image_magick. Add this code in /config/environments/development.rb

#...

Rails.application.configure do
#...
      
  config.active_storage.variant_processor = :mini_magick 

end
     


ii) Install ImageMagick

The chances that ImageMagick has already been installed on your Ubuntu system are pretty high. Confirm this by checking its version:

 
$ convert --version


You’ll get an error message if it is not installed. Install it with the following command:

$ sudo apt install imagemagick


Part B: Usage Example

1. Create a person scaffold

i). Generate the scaffold

   
$ rails g scaffold person name


ii). Add the route

# config/routes.rb
#...

resources person


2. Associating the Model With ActiveStorage

i). Set up image upload for the person.rb model

# models/person.rb
#...

  has_one_attached :image # if you want the object to have a single image
  has_many_attached :pictures # if you want the object to have multiple images
  has_rich_text :body # for rich texts that can also include images e.g blog posts


ii). White-list the image params in the persons_controller.rb:

# controllers/persons_controller.rb
#...

   def person_params
     params.require(:person).permit(:name, :image, :body, pictures: [])


iii). Resizing The Images

Create a method for resizing the images in person.rb

# ...

  def resize_image_to_thumbnail
    return unless image.content_type.in?(%[image/jpeg image/png])
    image.variant(resize_to_limit: [300, 300]).processed
  end

  def resize_picture_to_thumbnail(pic)
    return unless pic.content_type.in?(%[image/jpeg image/png])
    pic.variant(resize_to_limit: [250, 250]).processed
  end


iv). Create the form

 

<%= simple_form_for(@person do |f| %>
 <%= f.error_notification %>
 
  <div>
   <%= f.label :name, style: "display: block" %>
   <%= f.text_field :name %>
  </div>
  
  <br>
  <div>
   <%= f.rich_text_area :body %>
  </div>

  <div>
   <%= f.label :image %>
   <%= f.file_field :image %>
  </div>

  <div>
   <%= f.label :pictures %>
   <%= f.file_field :pictures, multiple: true %>
  </div>

  <div class="form-actions">
    <%= f.button :submit, class: "btn btn-success" %>
  </div>

<% end %>


v). Edit show.html.erb to resemble this:

 
<h2>Rich Text Area</h2>
<%= @question.body %>

<br>
<h2>Single Image</h2>
<% if @person.image.content_type.in?(%[image/jpeg image/png]) %>
  <%= link_to image_tag(@person.resize_image_to_thumbnail), person.image if person.image.attached? %>
<% end %>


<br>
<h2>Multiple Images</h2>
<% person.resize_picture_to_thumbnail.each do |picture| %>
<%= link_to image_tag(@person.resize_picture_to_thumbnail(picture)), picture %>
<% end %>


vi). Install simple_form gem

Use these instructions to install simple_form



That’s all!


Thanks for reading, see you in the next one!