Ryota400’s blog

エンジニアを目指して書いてます。

トップ画像をスライダー形式に変更

ActiveStorageとは

Amazon S3Google Cloud Storage、Microsoft Azure Storageなどの クラウドストレージサービスへのファイルのアップロードや、ファイルをActive Recordオブジェクトにアタッチする機能を提供しています。
development環境とtest環境向けのローカルディスクベースのサービスを利用できるようになっており、ファイルを下位のサービスにミラーリングしてバックアップや移行に用いることもできる。

Active Storageの実装

# マイグレーションファイルを作成
rails active_storage:install 

# マイグレーションファイルを実行
rails db:migrate

Active Storageを使って、複数画像ファイルをアップロード

site.rb

class Site < ApplicationRecord
    # Active Storage の「1対1」の画像アップロード
  has_one_attached :og_image
  has_one_attached :favicon

    # Active Storage の「1対多」の画像アップロード
  has_many_attached :main_images

・スライド画像用のパラメータがストロングパラメータに追加されていること
site_controller.rb

private

  def site_params
    params.require(:site).permit(:name, :subtitle, :description, :favicon, :og_image, main_images: [])#最後追加
  end

・各画像の削除ボタンが追加されていること
app/views/admin/sites/edit.html.slim

= image_tag @site.favicon_url('32x32')
        br
        br
        = link_to '削除', admin_site_attachment_path(@site.favicon.id),
          method: :delete, class: 'btn btn-danger'
        br
        br

      = f.input :og_image, as: :file, hint: 'JPEG/PNG (1200x630)'

        = image_tag @site.og_image_url(:ogp), class: 'img-responsive'
        br
        br
        = link_to '削除', admin_site_attachment_path(@site.og_image.id),
          method: :delete, class: 'btn btn-danger'
        br
        br
      = f.input :main_images, as: :file, input_html: {multiple: true}, hint: 'JPEG/PNG (1200x400)'

      - if @site.main_images.attached?
        .main_images_box
          - @site.main_images.each do |main_image|
            .main_image
              = image_tag main_image.variant(resize:'300x100').processed
              = link_to '削除', admin_site_attachment_path(main_image.id),
                method: :delete, class: 'btn btn-danger'

Active Storageでアップロードした画像を削除する

継承元を含めるコントローラーを生成するコマンド

bin/rails g controller Admin:Site:Attachments

admin/site/attachments_controller.rb

class Admin::Site::AttachmentsController < ApplicationController
  def destroy
    authorize(current_site)
    image = ActiveStorage::Attachment.find(params[:id])
    image.purge
    redirect_to edit_admin_site_path
  end
end

routes.rb

resource :site, only: %i[edit update] do
  resources :attachments, only: %i[destroy], controller: 'site/attachments'
end

モデルにバリデーションを作成

site.rb

 validates :og_image, attachment: { purge: true,content_type: %r{\Aimage/(png|jpeg)\Z}, maximum: 524_288_000 }
 validates :favicon, attachment: { purge: true,content_type: %r{\Aimage/(png|jpeg)\Z}, maximum: 524_288_000 }
 validates :main_images, attachment: { purge: true, content_type: %r{\Aimage/(png|jpeg)\Z},maximum: 524_288_000 }

app/validators/attachment_validator.rb

if options[:maximum]
      if value.is_a?(ActiveStorage::Attached::Many)
        # 画像が複数枚投稿された場合
        value.each do |v|
          unless validate_maximum(record, attribute, v)
            has_error = true
            break
          end
        end
      else
        # 画像が1枚投稿された場合
        has_error = true unless validate_maximum(record, attribute, value)
      end
end

if options[:content_type]
      if value.is_a?(ActiveStorage::Attached::Many)
        # 画像が複数枚投稿された場合
        value.each do |v|
          unless validate_content_type(record, attribute, v)
            has_error = true
            break
          end
        end
      else
        # 画像が1枚投稿された場合
        has_error = true unless validate_content_type(record, attribute, value)
      end
    end

・Siteの画像はadminユーザー以外は削除できないようにしておくこと
app/policies/site_policy.rb

def destroy?
    user.admin?
  end

Swiperとは

Swiperは「CSSやJS」を適用することで、画像のスライドを簡単に実装できる機能提供する「ライブラリ」です。

Swiper導入方法

設定方法として以下の3つあります。
①Swiperの公式サイトから必要なファイル(CSSやJS)をダウンロードしてアプリケーションに置いて、そいつを読み込む
CDNを使って毎回クラウド上に公開したファイルにアクセスして取得する
③npm、yarnのJSのパッケージ管理ツールを使用する

今回はnpmでSwiperをインストールする手順と読込例です

 npm install swiper

package.json

"dependencies": {
    "swiper": "^6.7.5",
}
``

config/initializers/assets.rb

Rails.application.config.assets.paths << Rails.root.join('node_modules')

node_modulesディレクトリまでのパスはデフォルトでは読み込んでくれないので、導入したnode_modulesディレクトリ以下のファイルを読み込むように設定を書きます。

app/asssets/javascripts/application.js

//= require swiper/swiper-bundle.js

上記のコードでnode_modules/swiper/swiper-bundle.jsファイルを application.jsファイルから読み込んでいます。


app/assets/stylesheets/application.css.scs

@import 'swiper/swiper-bundle';

application.css.scssファイルでnode_modules/swiper/swiper-bundle.cssファイルを読み込みます。  
どうして読み込む必要があるかというと、JSファイルはスライダーの動きを使えるコードがswiper-bundle.jsファイルに記載されているからです。  
また、デザインを当てるためにswiper-bundle.cssファイルを読み込む必要があります。  


## 必要なCSS

app/assets/stylesheets/admin.css.scss

.main_images_box { display: flex; .main_image { text-align: center; padding: 1rem; img { display: block; margin-bottom: 1rem; } } }

assets/stylesheets/application.css.scss

header { position: relative;

.swiper-container { img { width: 100%; height: 400px; object-fit: cover; } }

.blog-title { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; z-index: 10; a { color: white; } } }

参考文献

[https://swiperjs.com/get-started:title]


[https://weblog-tec.hatenablog.com/entry/2021/07/14/212732:title]


[https://www.webdesignleaves.com/pr/plugins/swiper_js.html:title]


[https://qiita.com/kenkentarou/items/bdf04d8ecab6a855e50f:title]