File uploading is an important aspect of many Ruby on Rails applications. The Paperclip gem was long seen as the go-to solution for this functionality. However, with its recent deprecation, Active Storage is now the go-to source for enabling file uploading within Rails applications. Active Storage is an aspect of Rails that allows users to upload files in various environments and to various cloud storage services. These services include Amazon’s S3 service, Google Cloud Storage, and Microsoft Azure Storage service. It also provides a local-disk based service that can be used in the application development stage. Images are one of the file types that Active Storage can store and are the focus of this quick, step-by-step tutorial.
In order to set up Active Storage within your project, enter the following commands to cd into the project directory, and install the service:
This creates a migration file that will introduce two tables into the application’s database once migrated, called, “active_storage_blobs” and “active_storage_attachments” as seen below.
Once migrated, you can configure the storage services your application uses by editing the storage.yml file in the config folder. By default, Active Storage utilizes the local disk for storage.
You can use different storage services in each environment (test, development and production) by editing the appropriate line in the environment config files to match your desired service. For example, if you configured the Google Cloud storage service to utilize it in production, ensure that the following line exists in your config/environments/production.rb file:
For an in-depth look at how to configure these cloud services in your rails app, check out this article by Wiktor Plaga.
Once your storage service is properly configured, you can move forward with implementing the necessary logic for uploading an image. No additional model is required.
In the case of an app where the user wants to associate images with their articles, the following configuration can be made to the appropriate model:
This macro “has_one_attached” enables one-to-one mapping between each Article record and the image file. The symbol that follows can be given any name. However, once that name is specified, it will have to be used in all subsequent application logic for image uploading. If you implemented a private params method for model creation, pass the named symbol to the params method as follows:
In order to enable the mapping of multiple images to each record, add the line below instead. It’s important to note that the symbol passed to the macro must be pluralized in this instance.
Once these simple configurations are made, you can go ahead and implement a form that allows users to attach an image file. The same symbol passed to the macro in the model must be passed to file_field form helper:
Once the user completes the form and hits send, the image will be uploaded and the credentials stored in the database. Upon uploading the image, you can incorporate it into the flow of the post in different ways. You can conditionally attach the image as follows:
You can also apply that image as a background:
Seeding Images in Your Rails Database
Rails also enables users to seed the database with images if they want. To do so, you can use the ‘attach’ method, passing in a hash with two keys. The ‘io’ key calls the open method on the File class and takes the image’s relative path as an argument.
Rails also provides some basic methods that can be used on the console to interact with the image records. The ‘attached?’ method can be used to determine if a particular object has an associated attachment. To call this method, run the following commands to open the console and query the database. The ‘attached’ method returns a Boolean response.
Deleting Attached Images
Rails also provides two methods for deleting attached images from the database. The ‘purge’ and ‘purge_later’ methods are used for this purpose. They are synchronous and asynchronous respectively and can both be called in the rails console. Please note that associated images are automatically deleted from storage if the record it was associated with has been deleted. eg. deleting an article, also deletes its attached images. There is no need to add ‘dependent: :destroy’ to the model to allow this behavior.
And there you have it! I hope this is helpful, in showing how to add a feature in your Rails app, so your users can upload images. Happy coding!
To learn more about Microverse, and joining our supportive community of remote software developers, get started here!