Create a Photo Gallery with Rails and Cloudinary
Here are some notes I've taken to my future self while implementing a gallery of photos in Rails and using Cloudinary. Note that I also prepare the same Cloudinary bucket to be used by both development and production, but in a way that we can stay in their free tier (a single bucket). Hope this is useful to others too.
Scaffolding
rails g scaffold property name description:text
rails db:migrate
Setup Cloudinary
bundle add cloudinary
config/initializers/cloudinary.rb ๐ป
Cloudinary.config do |config|
config.cloud_name = Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :cloud_name)
config.api_key = Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :api_key)
config.api_secret = Rails.application.credentials.dig(Rails.env.to_sym, :cloudinary, :api_secret)
config.secure = true
config.cdn_subdomain = true
end
EDITOR=vim rails credentials:edit
development:
cloudinary:
cloud_name: dxe1hjkoi
api_key: 361019726125669
api_secret: Cn6tHfSf019278367sZoO083eOI
rails active_storage:install
rails db:migrate
config/storage.yml ๐ป
cloudinary:
service: Cloudinary
folder: <%= Rails.env %>
config/environments/development.rb ๐ป
config.active_storage.service = :cloudinary
Upload photos
app/models/property.rb ๐ป
class Property < ApplicationRecord
has_many_attached :photos
end
app/views/properties/_form.html.erb ๐ป
= simple_form_for @property do |f|
= f.input :photos, as: :file, input_html: { multiple: true }
app/controllers/properties_controller.rb ๐ป
def property_params
params.require(:property).permit(:name, :description, photos: [])
end
Show photos
app/views/properties/show.html.erb ๐ป
- @property.photos.each do |photo|
= cl_image_tag photo.key, height: 500, width: 1108, crop: :fill
Delete photos
config/routes.rb ๐ป
resources :properties do
resources :photos do
match '/remove', to: 'properties#remove', via: 'delete'
end
end
app/controllers/properties_controller.rb ๐ป
def remove
# TODO: for security reasons delete in the scope of the account
# For instance: current_account.properties.find(params[:property_id])
# Disclaimer: currently I don't have an account so I can't do it now
@property = Property.find(params[:property_id])
@photo = @property.photos.find(params[:photo_id])
@photo.purge
redirect_to property_path(@property), notice: "Photo was successfully removed."
end
app/views/properties/_form.html.slim ๐ป
.card-columns.mt-3
- @property.photos.each do |photo|
.card
.card-body
= cl_image_tag photo.key, height: 200, width: 400, crop: :fill, class: 'img-fluid'
.card-footer
= link_to "Remove", property_photo_remove_path(@property, photo), \
method: :delete, data: { confirm: 'Are you sure you want to delete this photo?' }, \
class: 'btn btn-light btn-block'
ย