↓↓クリックして頂けると励みになります。
【37 | ActionText】 << 【ホーム】 >> 【39 | ホームページ】
SQLを利用した検索機能を実装していきます。
コントローラー
まずはコントローラーを編集します。
記述編集 【app/controllers/pages_controller.rb】
class PagesController < ApplicationController def home end def search @categories = Category.all @category = Category.find(params[:category]) if params[:category].present? @q = params[:q] @min = params[:min] @max = params[:max] @delivery = params[:delivery].present? ? params[:delivery] : "0" @sort = params[:sort].present? ? params[:sort] : "price asc" query_condition = [] query_condition[0] = "gigs.active = true" query_condition[0] += " AND ((gigs.has_single_pricing = true AND pricings.pricing_type = 0) OR (gigs.has_single_pricing = false))" if !@q.blank? query_condition[0] += " AND gigs.title ILIKE ?" query_condition.push "%#{@q}%" end if !params[:category].blank? query_condition[0] += " AND category_id = ?" query_condition.push params[:category] end if !params[:min].blank? query_condition[0] += " AND pricings.price >= ?" query_condition.push @min end if !params[:max].blank? query_condition[0] += " AND pricings.price <= ?" query_condition.push @max end if !params[:delivery].blank? && params[:delivery] != "0" query_condition[0] += " AND pricings.delivery_time <= ?" query_condition.push @delivery end @gigs = Gig .select("gigs.id, gigs.title, gigs.user_id, MIN(pricings.price) AS price") .joins(:pricings) .where(query_condition) .group("gigs.id") .order(@sort) end end
ルート設定
ルートを設定します。
「config/routes.rb」ファイルの15行目に以下の記述を追加します。
get '/search', to: 'pages#search'
「config/routes.rb」ファイルの21行目に以下の記述を追加します。
post '/search', to: 'pages#search'
記述追加 【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' # post post '/users/edit', to: 'users#update' post '/offers', to: 'offers#create' post '/reviews', to: 'reviews#create' post '/search', to: 'pages#search' 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\shared\_categories.html.erb」ファイルの記述を変更します。
記述変更 app\views\shared\_categories.html.erb
7行目の記述を「<%= link_to "#{item.name}", search_path(category: item.id), class: "btn btn-light font2" %>」に変更しています。
記述変更 app\views\shared\_categories.html.erb
<div class="container mt-4 mb-4"> <div class="card"> <div class="card-body"> <h5 class="badge bg-dark">カテゴリー</h5> <div> <% @categories.each do |item| %> <%= link_to "#{item.name}", search_path(category: item.id), class: "btn btn-light font2" %> <% end %> </div> </div> </div> </div>
「app\views\shared」フォルダに「_gigs.html.erb」ファイルを新規作成して下さい。
app\views\shared\_gigs.html.erb(新規作成したファイル)
<div class="row"> <% @gigs.each do |gig| %> <div class="col-md-4"> <div class="card mb-2"> <%= link_to gig_path(gig), data: { turbolinks: false} do %> <%= image_tag gig_cover(gig), style: "width: 100%;", class: "card-img-top" %> <% end %> <div class="card-body"> <span class="star-review"> <i class="fa fa-star text-warning"></i> <%= gig.average_rating %> <span class="has-text-primary">(<%= gig.reviews.count %>)</span> </span> <%= link_to gig_path(gig), data: { turbolinks: false} do %> <h5 class="card-title"> <span class="btn btn-light"><%= gig.title %></span> </h5> <% end %> <div> <%= link_to user_path(gig.user), style: "text-decoration:none;" do %> <%= image_tag avatar_url(gig.user), class: "bd-placeholder-img figure-img img-fluid rounded-pill", style: "width: 30px;" %> <span class="font2 text-dark"><%= gig.user.full_name %></span> <% end %> </div> <div class="badge bg-danger mt-2"> <span class="font2">最低価格</span> <strong><%= number_to_currency(gig.price) %></strong> </div> </div> </div> </div> <% end %> </div>
「app\views\pages」フォルダに「search.html.erb」ファイルを新規作成します。
app\views\pages\search.html.erb(新規作成したファイル)
<%= render 'shared/categories' %> <div class="container"> <!-- ヘッダー --> <div class="card w-100"> <div class="card-body"> <!-- カテゴリー --> <div class="mt-2 mb-3"> カテゴリー : <% if @category %><%= @category.name %> <% end %> </div> <!-- 並び替え --> <div class="font2"> <%= form_tag '', method: :post, id: "submit_form" do %> <%= select_tag 'sort', options_for_select( [ ['価格が低い順', 'price asc'], ['価格が高い順', 'price desc'], ['新着順', 'gigs.created_at desc'], ['古いもの順', 'gigs.created_at asc'] ], selected: @sort ), id: "submit_select" %> <% end %> </div> </div> </div> </div> <div class="container mt-4 mb-4"> <div class="row"> <!-- 左側 --> <div class="col-md-4"> <div class="card"> <div class="card-body"> <%= form_tag '', method: :get do %> <%= hidden_field_tag 'category', @category ? @category.id : '' %> <%= hidden_field_tag 'sort', @sort %> <!-- タイトル検索 --> <div class="mb-2"> <%= text_field_tag 'q', @q || '', class: "form-control", placeholder: "タイトルで検索" %> </div> <hr/> <!-- 価格帯 --> <label class="label font1">価格帯</label> <div class="input-group mb-3"> <%= number_field_tag 'min', @min || '', class: "form-control", placeholder: "最低" %> <span class="input-group-text">円</span> </div> <div class="input-group mb-3"> <%= number_field_tag 'max', @max || '', class: "form-control", placeholder: "最高" %> <span class="input-group-text">円</span> </div> <hr/> <!-- 期日 --> <label class="label font1">期日</label> <div> <%= radio_button_tag 'delivery', "1", checked = "1" == @delivery %> 1日以内 <br> <%= radio_button_tag 'delivery', "3", checked = "3" == @delivery %> 3日以内 <br> <%= radio_button_tag 'delivery', "7", checked = "7" == @delivery %> 7日以内 <br> <%= radio_button_tag 'delivery', "10", checked = "10" == @delivery %> 10日以内 <br> <%= radio_button_tag 'delivery', "15", checked = "15" == @delivery %> 15日以内 <br> <%= radio_button_tag 'delivery', "0", checked = "0" == @delivery %> 全て </div> <hr/> <!-- 下部 --> <div class="mt-4"> <button class="btn btn-danger w-100" type="submit"> 検索</button> </div> <% end %> <div class="mt-2"> <%= form_tag '', method: :get do %> <button class="btn btn-outline-dark w-100" type="submit"> 検索条件のクリア</button> <% end %> </div> </div> </div> </div> <!-- 右側 --> <div class="col-md-8"> <!-- 仕事のリスト --> <div class="container"> <%= render partial: 'shared/gigs', object: @gigs %> </div> </div> </div> <!-- 並び替え発火 --> <script type="text/javascript"> $(function(){ $("#submit_select").change(function(){ $("#submit_form").submit(); }); }); </script>
ページを確認します。
ブラウザ確認
http://localhost:3000/search
fakerでの仕事サンプル登録方法を書いておきます。。
「gig_cover_1.jpg」「gig_cover_2.jpg」「gig_cover_3.jpg」の3つの画像ファイルを「app\assets\images」フォルダに入れておいてください。何でも良いです。
「db\seeds.rb」ファイルの33から44行目をコメントアウトします。
その後、46行目からの記述を追加します。
コメントアウトは範囲選択して「Command+/」で一気にできます。
記述追加 db\seeds.rb
# This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). # # Examples: # # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) # テストカテゴリーを追加(10個) # 10.times do # Category.create( # name: Faker::Job.unique.field # ) # end # # テストユーザーを追加(5ユーザー パスワードは 123456) # 5.times do # user = User.create( # full_name: Faker::Name.name, # email: Faker::Internet.email, # about: Faker::Quote.matz, # password: '123456', # created_at: Date.today # ) # user.avatar.attach( # io: image = URI.open("https://i.pravatar.cc/300"), # filename: "avatar#{user.id}.jpg", # content_type: 'image/jpg' # ) # end # 10.times do # random_user = User.all.sample(1)[0] # category = Category.all.sample(1)[0] # request = Request.create( # title: Faker::Job.title, # description: Faker::Quote.matz, # budget: Faker::Number.between(from: 500, to: 5000), # delivery: Faker::Number.between(from: 1, to: 30), # user_id: random_user.id, # category_id: category.id # ) # end 10.times do random_user = User.all.sample(1)[0] category = Category.all.sample(1)[0] gig = Gig.create( title: Faker::Job.unique.title, description: Faker::Quote.matz, active: Faker::Boolean.boolean, user_id: random_user.id, category_id: category.id ) number = Faker::Number.between(from: 1, to: 3) gig.photos.attach( io: File.open("app/assets/images/gig_cover_#{number}.jpg"), filename: "category_#{number}.jpeg" ) gig.pricings.create( pricing_type: 0, title: Faker::Job.title, description: Faker::Quote.matz, price: Faker::Number.between(from: 500, to: 1500), delivery_time: Faker::Number.between(from: 1, to: 10), ) gig.pricings.create( pricing_type: 1, title: Faker::Job.title, description: Faker::Quote.matz, price: Faker::Number.between(from: 2000, to: 10000), delivery_time: Faker::Number.between(from: 11, to: 19), ) gig.pricings.create( pricing_type: 2, title: Faker::Job.title, description: Faker::Quote.matz, price: Faker::Number.between(from: 15000, to: 30000), delivery_time: Faker::Number.between(from: 20, to: 30), ) end
コマンド
rails db:seed
gigテーブルに10個の仕事が登録されているのが分かります。
Posticoで「active」カラムを全部「true」に変更してください。
【37 | ActionText】 << 【ホーム】 >> 【39 | ホームページ】
↓↓クリックして頂けると励みになります。