DEV Community

Rafael Almeida
Rafael Almeida

Posted on • Originally published at tech.xing.com

Using Ruby on Rails 5.2 Active Storage

Active Storage, now bundled with Ruby on Rails 5.2, allows you to easily handle your file upload, either to cloud platforms, such as Amazon S3 or Google Cloud Storage, or even upload right into your application directory, linking your uploads to your Active Record models with ease.

In order to start using Active Storage, you should have an existing Ruby on Rails 5.2 or greater application (freshly installed or upgraded), open your terminal in your application directory and type the following command:

rails active_storage:install
Enter fullscreen mode Exit fullscreen mode

This will generate a brand new migration for the two necessary database tables. After this, all you need to do is run the migrations with:

rails db:migrate
Enter fullscreen mode Exit fullscreen mode

After this everything is ready to start using Active Storage.

Setting up

To start you should declare in your config/storage.yml file your Active Storage services, one for each service that you use in your application.

Please, note that for the sake of this article, I’ll just be showing configurations for uploading the files to the same directory as your application, in your local disk. If you prefer to use it to upload to any cloud provider please refer to the docs.

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

After you declared every service that you’ll be using it’s time to tell your application what service should be used on each environment. In this article, I’m going to configure my development environment to use my local storage service. In order to achieve this add the following line to config/environments/development.rb:

# Store files locally.
config.active_storage.service = :local
Enter fullscreen mode Exit fullscreen mode

Use it

Now that we managed to configure Active Storage it’s time to start using it! One of the advantages of it is to easily create a relationship between the uploaded asset and your Active Record models, as stated at the beginning of this article, so we’re to take advantage of it. I have a Speakers model in which I intend to add an avatar to each of the speakers.

We’ll start by informing my Speakers model that it will have a one-to-one relationship with the corresponding uploaded avatar. My model will look like:

class Speaker < ApplicationRecord
    has_one_attached :avatar
end
Enter fullscreen mode Exit fullscreen mode

Then my Speakers controller will accept an avatar to be uploaded. My speaker_params will now look like:

def speaker_params
    params.permit(:name, :company, :email, :avatar)
end
Enter fullscreen mode Exit fullscreen mode

The file should now look like this:

class SpeakersController < APIController
    before_action :set_speaker, only: %i[show update destroy]    def index
        @speakers = Speaker.all
        render json: @speakers, status: :ok
    end    def create
        @speaker = Speaker.create!(speaker_params)
        render json: @speaker, status: :created
    end    def show
        render json: @speaker, status: :ok
    end    def update
        @speaker.update(speaker_params)
        head :no_content
    end    def destroy
        @speaker.destroy
        head :no_content
    end    private    def speaker_params
        params.permit(:name, :company, :email, **:avatar**, :social_media)
    end    def set_speaker
        @speaker = Speaker.find(params[:id])
    end
end
Enter fullscreen mode Exit fullscreen mode

I have to specify on my request body a field named avatar and its value will be a file, that’s going to be used as the speaker avatar.

After you finish your POST request and you navigate to the storage directory you’ll see a newly created directory containing your uploaded file. If you wish to verify that the file is linked to your speaker you can start rails console and type:

irb(main):001:0> speaker = Speaker.find(1)
=> #<Speaker id: 1, name: “Rafael”, email: “rafael.almeida@xing.com”, company: “XING”, social_media: nil, created_at: “2018–10–02 09:58:54”, updated_at: “2018–10–02 09:58:54”>
irb(main):002:0> app.url_for(speaker.avatar)
=> “http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--372a32ffdde03c2f2a37f407e63d10c909fd52ba/xing-photo.jpg"
Enter fullscreen mode Exit fullscreen mode

Et voilá, Active Storage is configured and ready to be used.

Bonus tip

If you execute a GET request on your API you’ll get the information about your speaker that you defined on your migration, like the example below:

{
    "id": 2,
    "name": "Rafael",
    "email": "rafael.almeida@xing.com",
    "company": "XING",
    "social_media": null,
    "created_at": "2018-10-02T09:59:28.494Z",
    "updated_at": "2018-10-02T09:59:28.497Z"
}
Enter fullscreen mode Exit fullscreen mode

However, you also might want to get the associated avatar. We can use a serializer in order to achieve what we intend. You’ll need to add gem 'active_model_serializers' and then include the following line in every controller that you want to get override with the serializer: include ActionController::Serialization. After that you can use rails g serializer speaker and Rails will generate the file for you.

In order to get the associated avatar your serializer should look like:

class SpeakerSerializer < ActiveModel::Serializer
  attributes :id, :name, :email, :company, :avatar

  def avatar
    rails_blob_path(object.avatar, only_path: true) if object.avatar.attached?
  end
end
Enter fullscreen mode Exit fullscreen mode

Now if you re-run your GET request you’ll see something like:

{
    "speaker": {
        "id": 2,
        "name": "Rafael",
        "email": "rafael.almeida@xing.com",
        "company": "XING",
        "avatar": "http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19–515a0de8817b3529b5d3d168871cebf6ccee0463/xing-photo.jpg"
    }
}
Enter fullscreen mode Exit fullscreen mode

You’re now able to see the avatar associated with every speaker.

Top comments (0)