天天看點

[Ting's筆記Day6]活用套件carrierwave gem:(1)在Rails實作圖檔上傳功能

carrierwave是一款經典的圖檔上傳套件,本篇的目标是先在本地端(development)的rails項目試成功gem。

(預計中集的進度會練習怎麼利用Amazone S3架設圖檔上傳Host,

并再下集遠端(production)實作上傳,敬請期待!)

https://ithelp.ithome.com.tw/upload/images/20180904/20111177jA3W9YiK5l.png

在閱讀任何Github上的README.md,有一點很重要的是知道因為環境設定的不同,必須漸漸了解哪些步驟可以跳過、哪些變數需要修改成符合自己項目性質的名稱,這點身為新手的我,将會靠練習活用各式各樣的gem來進步。:)

這次我們會更動的檔案/檔案夾如下:

Rails的構架說明

Gemfile設定Rails應用程式使用了哪些Gems套件

app放Controllers、Models和Views檔案

接下來就按造步驟來實作吧(leafor)!

A.在gemfile加入套件,重新開機rails server:

首先我們按照carrierwave在githhub上說明檔的訓示,前往/項目名稱/gemfile,新增代碼:

gem 'carrierwave','~> 1.0'

README.md告訴我們CarrierWave的版本需求:Rails 4.0 or higher and Ruby 2.0,我的ruby 2.4.2 Rails 5.1.6,是以沒有問題~

每次新增任何新的Gem到Gemfile,就要在Terminal輸入bundle install處理相依性,然後rails s重新開機伺服器。

tingdeMacBook-Air:yelpdemo tingtinghsu$ bundle install

tingdeMacBook-Air:yelpdemo tingtinghsu$ bundle info carrierwave

* carrierwave(1.2.3)

Summary: Ruby file upload library

Homepage: https://github.com/carrierwaveuploader/carrierwave

Path: /Users/tingtinghsu/.rvm/gems/ruby-2.4.2/gems/carrierwave-1.2.3

B.用rails g指令,新增Image uploader功能

接下來就可以看到carrierwave的厲害之處了,在此我需要将自己的餐廳(restaurants)資料庫建立新的圖檔(image)字段,是以把carrier的指令客制化成自己的項目。

指令rails g uploader Image幫助我們在此路徑:app/uploaders/image_uploader.rb新增了檔案。

打開image_uploader.rb看看裡面的類别寫法:

class ImageUploader < CarrierWave::Uploader::Base

storage:file

#storage:fog

# Override the directory where uploaded files will be stored.

# def store_dir

“uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}”

end

這個部分指的是:

如果我把儲存檔案的地方放在本地端(localhost),就要把storage:file前的#注釋拿掉

相對的,想要把儲存檔案的地方放在遠端(Heroku),把storage:fog前的#注釋拿掉

在本篇裡,CarrierWave會把我上傳的圖檔将會放在/public/uploads/restaurant/image。

C.建立資料庫上傳Image所需字段

建立遷移檔(migration,修改資料庫結構)

rails g migration add_image_to_restaurants image:string

并在資料庫增加上傳圖檔的字段:

rake db:migrate

然後重新開機伺服器:rails s

順利的在db/migrate跑出了add_image_to_restaurants.rb檔案。打開來瞧瞧:

class AddImageToRestaurants < ActiveRecord::Migration[5.1]

def change

add_column:restaurants,:image,:string

end

end

D.修改Models,讓資料庫準備好存取圖檔的功能

接下來我們修改跟ActiveRecord有關的Models。mount Model裡面,這個名為uploader上傳功能小幫手,未來它會幫我們翻譯資料庫語言(SQL)跟資料庫要資料(餐廳圖檔)。:

Models: app/models/restaurant.rb

class User < ActiveRecord::Base

mount_uploader:image,ImageUploader

end

在rails官網提到:

Active Record是MVC的M(Model)表現商業邏輯與資料的層級,負責新增與操作需要持久存在資料庫裡的資料。Active Record本身是ORM(Object Relational Mapping,物件關聯映像)系統的描述。

E.修改Views

資料庫的上傳功能已經準備好了,接下來到Views跟表單溝通,請讓表單能夠接受上傳的圖檔。

到app/views/restaurants/_form.html.erb,修改成可以上傳照片的form type(表單型态)。

<%= form_with(model: restaurant,local: true,:html => { multipart: true })do |form| %>

我們來增加:「上傳圖檔」字段,讓使用者能在視覺上看得見新字段,并修改上傳圖檔的檔案(file)類型為form.file_field,不同于其他純文字(text)字段如位址、電話的form.text_field。

<div class=“form-group”>

<%= form.label:name %>

<%= form.text_field:name,id::restaurant_name,class:“form-control”%>

</div>

<div class=“form-group”>

<%= form.label:image %>

<%= form.file_field:image,id::restaurant_image,class:“form-control”%>

</div>

告訴rails何時取得image。我們來到app/views/restaurants/show.html.erb,在餐廳資料前面加上代碼:

<p id=“notice”><%= notice %></p>

<%= image_tag @restaurant.image_url if @restaurant.image_url.present?%>

<p>

<p>

<strong>Name:</strong>

<%= @restaurant.name %>

</p>

image_tag:Rails内置的Helper靜态輔助方法,可以讓我們建構HTML更為容易。參考這裡

@restaurant.image_url:顯示目前這筆餐廳資料的圖檔位置。

[新手常見Bug!]檢查圖檔為nil寫法:if @restaurant.image_url.present?。可以防止當某位使用者新增一筆餐廳資料、但沒有附上圖檔的時候,show.html.erb這頁網頁直接當掉給你看…

F.修改Controllers

最後,我們在Controllers: app/controllers/restaurants.controller.rb加上允許上傳至字段的參數,告訴rails,新的image字段是安全的(gdgfpy)。

def restaurant_params

params.require(:restaurant).permit(:name,:address,:phone,:website,:image)

end

**大功告成**

轉載于:https://www.cnblogs.com/lannyQ-Q/p/10349634.html