Верстка содержит стили Bootstrap 4, что совершенно некритично и вовсе необязательно, а всплывающие popup окна создаются посредством lightbox2-rails.
Итак. Gemfile нашего приложения содержит (помимо всего прочего) эти джемы:
gem 'image_processing', '~> 1.2'
gem 'aws-sdk-s3'
gem 'lightbox2-rails'
gem 'activeadmin'
, нужен ли вам четвертый или пятый Bootstrap аналогичным образом, либо же посредством Webpacker - решайте сами.
Модель:
slideshow.rb
class Slideshow < ApplicationRecord
has_many_attached :images, dependent: :purge_later
scope :published, -> { where.not(published_at: nil) }
scope :unpublished, -> { where(published_at: nil) }
end
В качестве хранилища мы с вами намереваемся использовать Amazon S3, чуть более подробно о настройках здесь:
storage.yml
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
amazon:
service: S3
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
region: <%= ENV['REGION'] %>
bucket: <%= ENV['BUCKET'] %>
Добавим для удобства хелпер:
app/heplers/slideshows_helper.rb
module SlideshowsHelper
def slideshow_present?
@slideshow&.images&.attached?
end
def path_to_file(x)
Rails.application.routes.url_helpers.rails_blob_path(x, only_path: true)
end
end
, и теперь вьюха будет выглядеть просто и логично:
<div class="container">
<section class="section">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="row">
<% if slideshow_present? %>
<% @slideshow.images.each do |x| %>
<%= link_to(
path_to_file(x), html_options = {
"data-lightbox" => "photo", "class" => "col-sm-4"
}) do %>
<%= image_tag x.variant(
resize_to_limit: [300, 222],
kuwahara: '3%'
), "class" => "img-fluid" %>
<% end %>
<% end %>
<% end %>
</div>
</div>
</div>
</section>
</div>
Далее создаем в activeadmin удобную панель управления нашего слайдшоу; картинки способны загружаться как все вместе, так и путем добавления новых к уже существующим изображениям галереи, точно так же удаление изображений возможно как по одному, так и всех вместе:
ActiveAdmin.register Slideshow do
permit_params :published_at, :name, :options, images: []
remove_filter :images_attachments, :images_blobs, :options
scope :all
scope :published
scope :unpublished
action_item :publish, only: :show do
link_to 'Publish', publish_admin_slideshow_path(slideshow), method: :put unless slideshow.published_at?
end
action_item :unpublish, only: :show do
link_to 'Unpublish', unpublish_admin_slideshow_path(slideshow), method: :put if slideshow.published_at?
end
action_item :delete_images, only: :show do
if slideshow.images.attached?
link_to 'Delete Images', delete_images_admin_slideshow_path(slideshow), method: :delete
end
end
member_action :publish, method: :put do
slideshow = Slideshow.find(params[:id])
slideshow.update(published_at: Time.zone.now)
redirect_to admin_slideshow_path(slideshow)
end
member_action :unpublish, method: :put do
slideshow = Slideshow.find(params[:id])
slideshow.update(published_at: nil)
redirect_to admin_slideshow_path(slideshow)
end
member_action :delete_images, method: :delete do
slideshow = Slideshow.find(params[:id])
# asset = ActiveStorage::Attachment.find_by(params[:attachment_id])
slideshow.images.purge_later
redirect_to admin_slideshow_path(slideshow)
end
member_action :delete_image, method: :delete do
slideshow = Slideshow.find_by(params[:name])
slideshow.images[params[:id].to_i].purge_later
redirect_to admin_slideshow_path(slideshow)
end
form do |f|
f.inputs 'Slideshow' do
f.input :name
f.input :options,
input_html: { value: f.object.options || "{ resize_to_limit: [300, 222], kuwahara: '3%' }" },
label: 'Options. For example: { resize_to_limit: [300, 222], monochrome: true }'
f.input :images, as: :file, input_html: { multiple: true }
end
f.actions
end
show do |t|
attributes_table do
if t.images.attached?
t.images.each_with_index do |img, index|
span do
link_to delete_image_admin_slideshow_path(index), method: :delete do
image_tag img.variant(resize_to_limit: [100, 100])
end
end
end
end
row :name
row :created_at
row :updated_at
row :published_at
end
para 'Click the preview to delete the image.'
end
end
Небольшая, но немаловажная ремарка. По-умолчанию загрузка новых файлов означает замену старых и, чтобы изменить это поведение на добавление старых файлов к новым, используем эту опцию в application.rb:
config.active_storage.replace_on_assign_to_many = false
и - что у нас в итоге получилось. Актуальная версия кода - в гитхабе, ссылка на Live Demo (см. пункт меню "Slideshow") присутствует. Welcome.
Вы в любой момент можете клонировать репозиторий CRUD-Blog и самостоятельно поэкспериментировать с кодом.
Комментарии в блоге