Воскресенье, 14 ноября 2021 16:47

Image Gallery in Ruby on Rails

Оцените материал
(3 голосов)

Простенькая, но вполне себе симпатичная галерея изображений, реализованная на основе Ruby on Rails 6 с использованием Active Storage (посредством которого будем, помимо размещения и хранения картинок в удаленном хранилище, также ресайзить и накладывать фильтры, формируя thumbnails, превью изображений).

 

Image Gallery in Ruby on Rails
Image Gallery in Ruby on Rails

 

Верстка содержит стили Bootstrap 4, что совершенно некритично и вовсе необязательно, а всплывающие popup окна создаются посредством lightbox2-rails.

Итак. Gemfile нашего приложения содержит (помимо всего прочего) эти джемы:

 

gem 'image_processing', '~> 1.2'
gem 'aws-sdk-s3'
gem 'lightbox2-rails'
gem 'activeadmin'

 

Dev banner 3

 

, нужен ли вам четвертый или пятый 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 и самостоятельно поэкспериментировать с кодом.

 

Последнее изменениеПонедельник, 29 января 2024 17:57

Оставить комментарий

Добавьте ваш комментарий

Poker onRails

Комментарии в блоге

Заказать сайт

Веб-разработка. Заказать сайт

Вы можете заказать сайт-визитку, блог, корпоративный сайт, интернет-магазин или коммерческий web-портал.