[22]仕事登録 << [ホームに戻る] >> [24]仕事の表示
複数の画像をアップロードできるようにします。
コマンド
yarn add dropzone@5.5.1
「app\assets\stylesheets\application.scss」ファイルに以下の記述を追加します。
記述追加 app\assets\stylesheets\application.scss(23行目)
@import 'dropzone/dist/basic.css'; @import 'dropzone/dist/dropzone.css';
app\assets\stylesheets\application.scss
/* * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. * * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's * vendor/assets/stylesheets directory can be referenced here using a relative path. * * You're free to add application-wide styles to this file and they'll appear at the bottom of the * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS * files in this directory. Styles in this file should be added after the last require_* statement. * It is generally better to create a new file per style scope. * *= require_tree . *= require_self */ @import 'bulma'; @import 'bulma-extensions'; @import 'noty/lib/noty'; @import 'noty/lib/themes/sunset'; @import 'dropzone/dist/basic.css'; @import 'dropzone/dist/dropzone.css';
「app\javascript\packs\application.js」ファイルに以下の記述を追加します。
記述追加 app\javascript\packs\application.js(12行目)
window.Dropzone = require("dropzone")
app\javascript\packs\application.js
// This file is automatically compiled by Webpack, along with any other files // present in this directory. You're encouraged to place your actual application logic in // a relevant structure within app/javascript and only use these pack files to reference // that code so it'll be compiled. require("@rails/ujs").start() require("turbolinks").start() require("@rails/activestorage").start() require("channels") window.Noty = require("noty") window.Dropzone = require("dropzone") $(document).ready(() => { $('.toggle').on('click', (e) => { e.stopPropagation(); e.preventDefault(); $('#' + e.target.getAttribute('aria-controls')).toggleClass('is-hidden'); }) }) // Uncomment to copy all static images under ../images to the output folder and reference // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) // or the `imagePath` JavaScript helper below. // // const images = require.context('../images', true) // const imagePath = (name) => images(name, true) require("trix") require("@rails/actiontext")
「app\controllers\gigs_controller.rb」ファイルを以下の手順で編集していきます。
1.86行目からの「upload_photo()」メソッド、「delete_photo()」メソッドの内容を以下の記述に編集します。
def upload_photo @gig.photos.attach(params[:file]) render json: { success: true } end def delete_photo @image = ActiveStorage::Attachment.find(params[:photo_id]) @image.purge redirect_to edit_gig_path(@gig, step: 4) end
2.3行目に「protect_from_forgery except: [:upload_photo]」の記述を追加します。
記述更新 app\controllers\gigs_controller.rb
変更箇所が多いのでコードをコピーしてファイルの内容を置き換えて下さい。
class GigsController < ApplicationController protect_from_forgery except: [:upload_photo] before_action :authenticate_user!, except: [:show] before_action :set_gig, except: [:new, :create] before_action :is_authorised, only: [:edit, :update, :upload_photo, :delete_photo] before_action :set_step, only: [:update, :edit] def new @gig = current_user.gigs.build @categories = Category.all end def create @gig = current_user.gigs.build(gig_params) if @gig.save @gig.pricings.create(Pricing.pricing_types.values.map{ |x| {pricing_type: x} }) redirect_to edit_gig_path(@gig), notice: "保存しました" else redirect_to request.referrer, flash: { error: @gig.errors.full_messages } end end def edit @categories = Category.all end def update if @step == 2 gig_params[:pricings_attributes].each do |index, pricing| if @gig.has_single_pricing && pricing[:pricing_type] != Pricing.pricing_types.key(0) next; else if pricing[:title].blank? || pricing[:description].blank? || pricing[:delivery_time].blank? || pricing[:price].blank? return redirect_to request.referrer, flash: {error: "価格が無効です"} end end end end if @step == 3 && gig_params[:description].blank? return redirect_to request.referrer, flash: {error: "詳細を空白にすることはできません"} end if @step == 4 && @gig.photos.blank? return redirect_to request.referrer, flash: {error: "写真がありません"} end if @step == 5 @gig.pricings.each do |pricing| if @gig.has_single_pricing && !pricing.basic? next; else if pricing[:title].blank? || pricing[:description].blank? || pricing[:delivery_time].blank? || pricing[:price].blank? return redirect_to edit_gig_path(@gig, step: 2), flash: {error: "価格が無効です"} end end end if @gig.description.blank? return redirect_to edit_gig_path(@gig, step: 3), flash: {error: "詳細を空白にすることはできません"} elsif @gig.photos.blank? return redirect_to edit_gig_path(@gig, step: 4), flash: {error: "写真がありません"} end end if @gig.update(gig_params) flash[:notice] = "保存しました" else return redirect_to request.referrer, flash: {error: @gig.errors.full_messages} end if @step < 5 redirect_to edit_gig_path(@gig, step: @step + 1) else redirect_to dashboard_path end end def show end def upload_photo @gig.photos.attach(params[:file]) render json: { success: true } end def delete_photo @image = ActiveStorage::Attachment.find(params[:photo_id]) @image.purge redirect_to edit_gig_path(@gig, step: 4) end private def set_step @step = params[:step].to_i > 0 ? params[:step].to_i : 1 if @step > 5 @step = 5 end end def set_gig @gig = Gig.find(params[:id]) end def is_authorised redirect_to root_path, alert: "あなたには権限がありません。" unless current_user.id == @gig.user_id end def gig_params params.require(:gig).permit(:title, :video, :description, :active, :category_id, :has_single_pricing, pricings_attributes: [:id, :title, :description, :delivery_time, :price, :pricing_type]) end end
ルートの設定を以下の内容に更新します。
記述更新 config\routes.rb(17行目)
resources :gigs do member do delete :delete_photo post :upload_photo end end
config\routes.rb
Rails.application.routes.draw do # ルートを app\views\pages\home.html.erb に設定 root 'pages#home' devise_for :users, path: '', path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}, controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'} get 'pages/home' get '/dashboard', to: 'users#dashboard' get '/users/:id', to: 'users#show' post '/users/edit', to: 'users#update' resources :gigs do member do delete :delete_photo post :upload_photo end end # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html end
ブラウザ確認
実際に仕事を登録してみます。
http://localhost:3000/gigs/new
概要を入力して「保存して続ける」ボタンを押します。
シングルプランの時はチェックをつけますが、今回はそのまま「保存して続ける」ボタンを押します。
項目を入力して「保存して続ける」ボタンを押します。
リッチテキストが使えます。
ファイルも添付できます。
写真のアップロードができます。
複数の写真も同時にアップロードできます。
「Youtubeコード」には動画のIDを入れます。
「公開ボタン」を押して公開します。
↓↓クリックして頂けると励みになります。