Creating a bare bone photo album app
Today, i’ll show you how to create a basic photo album app with rails6, i’ll be using active_storage to manage uploads/attachments of our photo album. This app will be a very basic photo gallery/ablum app with just the bare bones, so no special styles, no file validations, authentication, and also no direct uploads or uploads to S3 or anything of that sort. In my future blog posts i’ll post an update on how to implement those features, but for now lets stick just with the bare bones.
Getting Started
To get started lets create a new rails app, lets call it ‘photoalbum’.
rails new photoalbum
After that, we’ll add image processing gem to our gemfile, and run bundler. This gem helps in resizing, cropping and processing of images.
#File: Gemfile
gem 'image_processing', '~> 1.2'
bundle install
Then we’ll install active storage for image attachment uploads.
rails active_storage:install
Now, lets create a new scaffold, our model name will be album and will contain a title and a description for the album.
rails g scaffold album title:string description:text
Now run the migrations
rails db:migrate
Adding Attachments
Now, lets start creating the actual part of our application that is to manage the uploads/attachments and display the uploaded photos.
The Model
In our album model we’ll add a has_many_attached type of attachment so that an album can contain multiple photos, we’ll call our attachment ‘album_photos’.
#File: app/models/album.rb
class Album < ApplicationRecord
has_many_attached :album_photos
end
The Controller
In our albums controller, we’ll permit the ‘album_photos’ parameter, album_photos will be sent as an array, since we want multiple uploads, so keep that in mind. We’ll also have to add a new method to delete the photo attachment, later if we want to remove the photos individually, instead of deleting the whole album.
#File: app/controllers/albums_controller.rb
class AlbumsController < ApplicationController
#....other methods.....
def delete_album_photos
attachment = ActiveStorage::Attachment.find(params[:id])
attachment.purge
redirect_back(fallback_location: albums_path)
end
#....other methods.....
private
def set_album
@album = Album.find(params[:id])
end
def album_params
params.require(:album).permit(:title, :description, album_photos: [])
end
end
Routes
For the delete attachment method, we’ll also have to add a new route, and also i added a root route for our app, this will redirect to albums#index page.
#File: config/routes.rb
Rails.application.routes.draw do
root to: 'albums#index'
resources :albums do
member do
delete :delete_album_photos
end
end
end
The Views
In our albums’ form partial, i added a new file field to upload our photo/image files, i added ‘multiple: true’ to enable multiple uploads.
#File: app/views/albums/_form.html.erb
<div class="field">
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :description %>
<%= form.text_area :description %>
</div>
<div class="field">
<%= form.label :album_photos %>
<%= form.file_field :album_photos, multiple: true %>
</div>
In our Albums’ show page, i added a image tag with a image variant, of size 150×150. This will show our uploaded photos as thumbnails, and also i added a link_to to the original file of the photos, it will open the photo in a new tab and show us the full size photo. I also added a download link and file size info for the image files.
#File: app/views/albums/show.html.erb
<p><strong>Title:</strong><%= @album.title %></p>
<p><strong>Description:</strong><%= @album.description %></p>
<%= link_to 'Edit', edit_album_path(@album) %> |
<%= link_to 'Back', albums_path %>
<hr>
<% @album.album_photos.order("created_at DESC").each do |album_photos| %>
<div style="margin: 5px;border: 1px solid #ccc;float: left;width: 150px;">
<%= link_to image_tag(album_photos.variant(resize_to_fill: [150, 150]), style: "width: 100%;height: auto;", alt: album_photos.filename.to_s), album_photos, target: "_blank"%>
<div style="padding: 8px;text-align: center;font-size: 0.7em">
<%= number_to_human_size(album_photos.byte_size.to_i) %>
<%= link_to "Download", album_photos, target: "_blank" %>
<%= link_to 'Delete', delete_album_photos_album_url(album_photos), method: :delete, data: { confirm: 'Are you sure?' } %>
</div>
</div>
<% end %>
Active Storage Initializer
I also added a new initializer for active storage, in app/initializers/ and named it ‘active_storage.rb’, i had to do this to disable a feature called ‘replace_on_assign_to_many’, that is enabled by default. If this is enabled, every time i edit/update an album with a new set of photos, it will delete the previously uploaded attachments and replace it with new ones, by default. After disabling this feature, please don’t forget to restart your rails server.
here’s my blog post about this feature: active_storage.replace_on_assign_to_many
#File: config/initializers/active_storage.rb
Rails.application.config.active_storage.replace_on_assign_to_many = false
The End Result
So this is how the end result looks like, you can check out the complete source code of this app on my github page: https://github.com/railshero/simple_photo_album
I can now create a new album, edit/delete previously created albums, add new photos to new/existing albums or even remove them individually.
![album photos show page](https://railshero.pw/wp-content/uploads/2021/07/album_photos.jpg)
The source of the royalty free images used above is from pexels.com
![new album page](https://railshero.pw/wp-content/uploads/2021/07/new_album-242x300.jpg)
![edit album page](https://railshero.pw/wp-content/uploads/2021/07/edit_page-256x300.jpg)
Final Thoughts
So, as i said earlier, this app is just a bare bone app. I created the entire app in just about 10 minutes, so there are no special features like file validations, authentication, etc, there’s not even a pagination feature. In my future blog post, i’ll post and update on this app. But you can implement those features yourself, if you wish to do so.