↓↓クリックして頂けると励みになります。
【45 | 会話表示】 << 【ホーム】 >> 【47 | Full Calendar】
購入した(された)仕事に対して、お互いに添付ファイル付きコメントを送信できるようにします。
モデル
コメントモデルを作成します。
コマンド
rails g model Comment content:text user:references order:references
「db\migrate\20200712092809_create_comments.rb」ファイルの記述を更新します。
記述更新 db\migrate\20200712092809_create_comments.rb
コードをコピーしてファイルの内容を置き換えて下さい。
class CreateComments < ActiveRecord::Migration[6.1] def change create_table :comments do |t| t.text :content t.references :user, foreign_key: true t.references :order, foreign_key: true, type: :uuid t.timestamps end end end
コマンド マイグレーション適用
rails db:migrate
「app\models\comment.rb」に以下の記述を追加します。
記述追加 app\models\comment.rb(5行目)
has_one_attached :attachment_file
記述追加 app\models\comment.rb
class Comment < ApplicationRecord belongs_to :user belongs_to :order has_one_attached :attachment_file end
コントローラー
「app\controllers」フォルダに「comments_controller.rb」ファイルを新規作成します。
app\controllers\comments_controller.rb(新規作成したファイル)
class CommentsController < ApplicationController before_action :authenticate_user! before_action :is_valid_order def create order = Order.find(comment_params[:order_id]) if comment_params[:content].blank? # 「無効なメッセージ」とアラートを返す return render json: {success: false} end @comment = Comment.new( user_id: current_user.id, order_id: order.id, content: comment_params[:content], attachment_file: comment_params[:attachment_file] ) if @comment.save redirect_to request.referrer, notice: "コメントを送りました" else redirect_to request.referrer, alert: "コメントすることができません" end end private def comment_params params.require(:comment).permit(:content, :order_id, :attachment_file) end def is_valid_order redirect_to dashboard_path, alert: "無効です" unless Order.find(comment_params[:order_id]).present? end end
「app\controllers\orders_controller.rb」ファイルの記述を更新します。
1.記述追加 app\controllers\orders_controller.rb(4行目)
before_action :is_authorised, only: [:show]
2.記述追加 app\controllers\orders_controller.rb(42行目)
def show @order = Order.find(params[:id]) @gig = @order.gig_id ? Gig.find(@order.gig_id) : nil @request = @order.request_id ? Request.find(@order.request_id) : nil @comments = Comment.where(order_id: params[:id]).order(updated_at: :desc) end
3.記述追加 app\controllers\orders_controller.rb(85行目)
def is_authorised redirect_to dashboard_path, alert: "You don't have permission" unless Order.where("id = ? AND (seller_id = ? OR buyer_id = ?", params[:id], current_user.id, current_user.id) end
記述更新 app\controllers\orders_controller.rb
class OrdersController < ApplicationController before_action :authenticate_user! before_action :is_authorised, only: [:show] def create gig = Gig.find(params[:gig_id]) pricing = gig.pricings.find_by(pricing_type: params[:pricing_type]) if (pricing && !gig.has_single_pricing) || (pricing && pricing.basic? && gig.has_single_pricing) if charge(gig, pricing) return redirect_to buying_orders_path end else flash[:alert] = "価格が間違っています。" end redirect_to request.referrer end def selling_orders @orders = current_user.selling_orders end def buying_orders @orders = current_user.buying_orders end def complete @order = Order.find(params[:id]) if !@order.completed? if @order.completed! flash[:notice] = "保存しました" else flash[:notice] = "問題が発生しました" end redirect_to request.referrer end end def show @order = Order.find(params[:id]) @gig = @order.gig_id ? Gig.find(@order.gig_id) : nil @request = @order.request_id ? Request.find(@order.request_id) : nil @comments = Comment.where(order_id: params[:id]).order(updated_at: :desc) end private def charge(gig, pricing) order = gig.orders.new order.title = gig.title order.due_date = Date.today() + pricing.delivery_time.days order.seller_name = gig.user.full_name order.seller_id = gig.user.id order.buyer_name = current_user.full_name order.buyer_id = current_user.id order.amount = pricing.price * 1.1 amount = pricing.price * 1.1 host_amount = (amount * 0.8).to_i # 売上の80%がホストに入る charge = Stripe::Charge.create({ amount: (amount).to_i, customer: current_user.stripe_id, source: params[:payment], currency: "jpy", transfer_data: { amount: host_amount, destination: gig.user.merchant_id, # ホストのストライプID }, }) order.save flash[:notice] = "決済が完了しました。。" return true rescue ActiveRecord::RecordInvalid flash[:alert] = "問題が発生しました。" return false end def is_authorised redirect_to dashboard_path, alert: "You don't have permission" unless Order.where("id = ? AND (seller_id = ? OR buyer_id = ?", params[:id], current_user.id, current_user.id) end end
ルートの設定をします。
1.記述追加 config\routes.rb(21行目)
get '/orders/:id', to: 'orders#show', as: "order_detail"
2.記述追加 config\routes.rb(30行目)
post '/comments', to: 'comments#create'
config\routes.rb
Rails.application.routes.draw do # ルートを app\views\pages\home.html.erb に設定 root 'pages#home' # get get 'pages/home' get '/dashboard', to: 'users#dashboard' get '/users/:id', to: 'users#show', as: 'user' get '/selling_orders', to: 'orders#selling_orders' get '/buying_orders', to: 'orders#buying_orders' get '/all_requests', to: 'requests#list' get '/request_offers/:id', to: 'requests#offers', as: 'request_offers' get '/my_offers', to: 'requests#my_offers' get '/search', to: 'pages#search' get 'settings/payment', to: 'users#payment', as: 'settings_payment' get 'settings/payout', to: 'users#payout', as: 'settings_payout' get '/gigs/:id/checkout/:pricing_type', to: 'gigs#checkout', as: 'checkout' get '/conversations', to: 'conversations#list', as: "conversations" get '/conversations/:id', to: 'conversations#show', as: "conversation_detail" get '/orders/:id', to: 'orders#show', as: "order_detail" # post post '/users/edit', to: 'users#update' post '/offers', to: 'offers#create' post '/reviews', to: 'reviews#create' post '/search', to: 'pages#search' post '/settings/payment', to: 'users#update_payment', as: "update_payment" post 'messages', to: 'messages#create' post '/comments', to: 'comments#create' # put put '/orders/:id/complete', to: 'orders#complete', as: 'complete_order' put '/offers/:id/accept', to: 'offers#accept', as: 'accept_offer' put '/offers/:id/reject', to: 'offers#reject', as: 'reject_offer' resources :gigs do member do delete :delete_photo post :upload_photo end resources :orders, only: [:create] end resources :requests resources :reviews, only: [:create, :destroy] # device devise_for :users, path: '', path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}, controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'} # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html end
ビュー
レンダーファイルを作成します。
「app\views\orders」フォルダに「_comment.html.erb」ファイルを新規作成します。
app\views\orders\_comment.html.erb(新規作成したファイル)
<div style="border: solid 1px #c0c0c0; margin-bottom: 0.3rem; border-radius: 5px;"> <ul class="list-group list-group-horizontal"> <li class="list-group-item bn" style="border:none;"> <figure class="figure"> <%= image_tag avatar_url(comment.user), style: "width: 40px;", class: "figure-img img-fluid rounded-pill" %> <figcaption class="figure-caption"> <div class="font2"><%= comment.user.full_name %></div> </figcaption> </figure> </li> <li class="list-group-item bn" style="width: 80%; border:none"> <span class="font2"><%= comment.content %></span> <span class="text-secondary font2"><small><%= time_ago_in_words(comment.created_at) %></small></span> </li> </ul> <ul class="list-group list-group-horizontal"> <% if comment.attachment_file.attached? %> <li class="list-group-item bn" style="width: 80%; border:none"> <%= link_to url_for(comment.attachment_file), class: "btn btn-warning", download: "Attachment_#{comment.attachment_file.id}" do %> <i class="fas fa-paperclip fa-lg p-r-5"></i><%= comment.attachment_file.filename %> <% end %> </li> <% end %> </ul> </div>
「app\views\orders」フォルダに「show.html.erb」ファイルを新規作成します。
app\views\orders\show.html.erb(新規作成したファイル)
<div class="container"> <div class="row"> <!-- 左側 --> <div class="col-md-8"> <div class="container mt-4"> <div class="card mb-4"> <div class="card-body"> <h4 class="font1"> コメント </h4> <div class="container mt-4"> <%= form_with model: Comment.new do |f| %> <%= f.hidden_field :order_id, value: @order.id %> <%= f.text_area :content, class: "form-control", placeholder: "コメントを入力して下さい", style: "height: 10rem;" %> <div class="mt-4"> <%= f.file_field :attachment_file, class: "file-input" %> </div> <div class="card mb-4"> <div class="card-body"> <div class="file-name" id="file-name">ファイルが選択されていません</div> </div> </div> <%= f.submit "コメントを送る", class: "btn btn-primary w-100" %> <% end %> </div> </div> </div> <div> <% @comments.each do |c| %> <%= render 'orders/comment', comment: c %> <% end %> </div> </div> </div> <!-- 右側 --> <div class="col-md-4"> <div class="card mt-4"> <%= image_tag gig_cover(@gig), style: "width: 100%;", class: "card-img-top" %> <div class="card-body"> <h5 class="font2 bg-light p-2" style="border-radius: 10px;"><%= @order.title %></h5> <div class="badge bg-danger font2"><%= number_to_currency(@order.amount) %></div> <div>フリーランサー: <%= @order.seller_name %></div> <div>オーダーID: <%= @order.id %></div> <div>購入日:<%= I18n.l(@order.created_at, format: :full_date) %></div> </div> </div> </div> </div> </div> <script> $(document).ready(function() { var file = $('.file-input'); file.change(function(e) { if (file[0].files.length > 0) { var attachment = file[0].files[0]; $('.file-name').text(attachment.name + " (" + attachment.size + " bytes)"); } }) }) </script>
作成したコメントページへのリンクをつけます。
「app\views\orders\buying_orders.html.erb」ファイルの記述を更新します。
記述更新 app\views\orders\buying_orders.html.erb
31行目に以下の記述を追加しています。
<li class="list-group-item" style="border: none;"> <%= link_to "コメント", order_detail_path(o), class: "btn btn-primary", data: { turbolinks: false} %> </li>
記述更新 app\views\orders\buying_orders.html.erb
<div class="container mt-4"> <div class="card"> <div class="card-body"> <h5 class="card-title text-danger h3 font1">依頼内容(クライアント)</h5> <% if @orders.blank? %> <h5 class="font1">表示できるオーダーはありません。</h5> <% end %> <% @orders.each do |o| %> <div class="card mt-4"> <div class="card-body"> <% if !o.request.nil? %> <div class="badge bg-info mb-4">リクエスト</div> <% else %> <div class="badge bg-dark mb-4">購入済みの仕事</div> <% end %> <div class="mt-2"> <% if o.inprogress? %> <span class="font1 alert alert-danger text-center">進行中</span> <%= link_to complete_order_path(o), method: :put, data: {confirm: "完了にしてもよろしいですか?"} do %> <i class="fa fa-thumbs-up fa-lg" style="color: green;"></i><span class="badge bg-success">完了</span> <% end %> <% else %> <span class="font1 alert alert-success text-center">完了</span> <%= render partial: "reviews/form", locals: {o: o} %> <% end %> </div> <ul class="list-group mt-4"> <li class="list-group-item" style="border: none;"> <%= link_to "コメント", order_detail_path(o), class: "btn btn-primary", data: { turbolinks: false} %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">依頼日:</span><%= I18n.l(o.created_at, format: :full_date) %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">フリーランサー</span> <%= link_to user_path(o.seller), class: "tootip", style: "text-decoration: none;" do %> <span class="btn btn-light"><%= o.seller_name %></span> <% end %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">仕事名:</span> <%= link_to o.title, gig_path(o.gig), class: "btn btn-light" if !o.gig.nil? %> <%= link_to o.title, request_path(o.request), class: "btn btn-light" if !o.request.nil? %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">期日:</span> <%= I18n.l(o.due_date) %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">価格:</span><%= number_to_currency(o.amount) %> </li> </ul> </div> </div> <% end %> </div> </div> </div>
ブラウザを確認します。
コメント表示ページが開くか確認してください。
http://localhost:3000/buying_orders
コメント表示ページです。
動作確認してください。
アドレスで渡されているパラメーターはオーダーのUUIDです。
http://localhost:3000/orders/84102071-8136-41f1-a79d-26f956d00d16
「app\views\orders\selling_orders.html.erb」ファイルの記述を更新します。
記述更新 app\views\orders\selling_orders.html.erb
28行目に以下の記述を追加しています。
<li class="list-group-item" style="border: none;"> <%= link_to "コメント", order_detail_path(o), class: "btn btn-primary", data: { turbolinks: false} %> </li>
<div class="container mt-4"> <div class="card"> <div class="card-body"> <h5 class="card-title text-danger h3 font1">オーダー内容(フリーランサー)</h5> <% if @orders.blank? %> <h5 class="font1">表示できるオーダーはありません。</h5> <% end %> <% @orders.each do |o| %> <div class="card mt-4"> <div class="card-body"> <div class="mt-2"> <div> <% if !o.request.nil? %> <div class="badge bg-info mb-4">リクエスト</div> <% else %> <div class="badge bg-dark mb-4">購入された仕事</div> <% end %> </div> <% if o.inprogress? %> <span class="font1 alert alert-danger text-center">進行中</span> <% else %> <span class="font1 alert alert-success text-center">完了</span> <% end %> </div> <ul class="list-group mt-4"> <li class="list-group-item" style="border: none;"> <%= link_to "コメント", order_detail_path(o), class: "btn btn-primary", data: { turbolinks: false} %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">依頼日:</span><%= I18n.l(o.created_at, format: :full_date) %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">クライアント</span> <%= link_to user_path(o.buyer), class: "tootip", style: "text-decoration: none;" do %> <span class="btn btn-light"><%= o.buyer_name %></span> <% end %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">仕事名:</span> <%= link_to o.title, gig_path(o.gig), class: "btn btn-light" if !o.gig.nil? %> <%= link_to o.title, request_path(o.request), class: "btn btn-light" if !o.request.nil? %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">期日:</span> <%= I18n.l(o.due_date) %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">価格:</span><%= number_to_currency(o.amount) %> </li> </ul> </div> </div> <% end %> </div> </div> </div>
ブラウザ確認
http://localhost:3000/selling_orders
動作を確認してください。
【45 | 会話表示】 << 【ホーム】 >> 【47 | Full Calendar】
↓↓クリックして頂けると励みになります。