iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 26
1
自我挑戰組

關於 Ruby on Rails 的那些事系列 第 26

Day 26 - 上傳檔案 Carrierwave - 單一檔案

想架設一個聊天室,除了文字訊息之外,還會需要傳照片,除此之外,也會使用照片當作大頭貼,這樣上傳檔案的功能就必須要考慮到。因此今天要來介紹一個常用的套件,CarrierWave。這邊就用使用者的個人簡介( profile )頁面來加入大頭貼欄位為例。

前置作業:

為解說方便,我先快速建立基本的 CRUD 功能

$ rails generate scaffold profile nickname email avatar:string    

簡單來說,scaffold 會長出 model、controller、view...等檔案,並且寫好基礎的 CRUD 功能。這邊我自己用 profile 命名,欄位有匿稱、信箱、大頭貼。
記得在 routes.rb 新增路徑!

1. 起手式:

套件安裝:

# Gemfile
gem 'carrierwave', '~> 2.1'

別忘了!

$ bundle install

2. 在開始上傳圖檔前,先建立 uploader

先用 rails generate 出來

$ rails generate uploader Avatar

執行後,長出一個檔案avatar_uploader.rb

可以打開檔案看看裡面寫了些什麼~

3. 確認資料表中是否有這個欄位

在一開始設計時,就有先給欄位的話,這一步就不用做了!
若是後來要新增上傳大頭貼的功能,要記得開欄位儲存照片!
(本篇先來做單一檔案的上傳方式)

此篇建立的是 profile 資料表

$ rails g migration add_avatar_to_profile avatar:string

這只是建立 migration 檔案,記得要 rails db:migrate

小提醒:這邊存取照片為什麼資料型態是 string 呢?因為我們是存一段 url(網址),所以是個字串型態。

4. 在 model 中掛載 uploader 進來

# app/models/profile.rb

class profile < ApplicationRecord
  mount_uploader :avatar, AvatarUploader
end

mount 是掛載的意思,讓這個 model 可以有上傳文件功能。

5. controller 資料在儲存時,記得要讓合法的資料通關

先前在講 ActionCable,有提到強參數的問題,ruby 會避免使用者不小心或惡意寫入不該進資料庫的東西,所以需要經過清洗才能進資料庫的設計。
剛剛我們建立了資料表欄位,也要記得回 controller 修改清洗條件

# app/controllers/profile_controller.rb
def profile_params
  params.require(:profile).permit(:nickname, :email, :avatar)
end

6. 修改 views

「new」和「edit」資料的表單畫面

用 scaffold 產生的表單,是只能輸入文字的表格

要改成可以選擇檔案的表格,重點是 4 行的 form.file.field

<!-- app//views/profiles/_form.html.erb -->

<div class="field">
  <%= form.label :avatar %>
  <%= form.file_field :avatar %>
</div>

點擊之後就會跳出選取檔案的視窗了!

「show」畫面

既然都上傳檔案了,就要在畫面顯示出來,那就來更改show.html.erb

<!-- app/views/profiles/ -->
<p id="notice"><%= notice %></p>

<p>
  <strong>Nickname:</strong>
  <%= @profile.nickname %>
</p>

<p>
  <strong>Email:</strong>
  <%= @profile.email %>
</p>

<p>
  <strong>Avatar:</strong>
  <br>
  <%= image_tag @profile.avatar.url if @profile.avatar.url.present? %>
</p>


<%= link_to 'Edit', edit_profile_path(@profile) %> |
<%= link_to 'Back', profiles_path %>

image_tag 是一個 helper,會自動長出 <img src="...">,後面的判斷式用意在於,可以避免只用者沒有上傳圖檔時,不會造成抓不到資料,而發生錯誤情況。使用者有上傳圖片就顯示出來,若沒有就當作沒有這回事。

檔案存在哪裏呢?

當使用者填完資料、選完檔案後,按下 submit,照片的連結就會傳送到資料庫儲存
CarrierWave 就會把檔案儲存在 public/uploads/profile/avatar

你可以打開這個資料夾,就會看到上傳的照片囉!

參考資料:
GitHub - CarrierWave
Ting's筆記 - carrierwave
PJCHENder未整理筆記

學無止盡,每天都要進步一點點!


上一篇
Day 25 - Devise 會員系統 - 客製化
下一篇
Day 27 - 上傳檔案 Carrierwave - 多個檔案
系列文
關於 Ruby on Rails 的那些事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
jrnalts
iT邦新手 5 級 ‧ 2020-10-11 00:59:52

很實用!/images/emoticon/emoticon12.gif

Mei iT邦新手 5 級 ‧ 2020-10-11 05:26:14 檢舉

謝 Andrew 大大! XD

我要留言

立即登入留言