carrierwave是一款經典的圖片上傳套件,本篇的目標是先在本地端(development)的rails項目試成功gem。html
(預計中集的進度會練習怎麼利用Amazone S3架設圖片上傳Host,git
並再下集遠端(production)實做上傳,敬請期待!)github
https://ithelp.ithome.com.tw/upload/images/20180904/20111177jA3W9YiK5l.pngweb
在閱讀任何Github上的README.md,有一點很重要的是知道由於環境設定的不一樣,必須漸漸瞭解哪些步驟能夠跳過、哪些變數須要修改爲符合本身項目性質的名稱,這點身爲新手的我,將會靠練習活用各式各樣的gem來進步。:)數據庫
此次咱們會更動的檔案/文件夾以下:安全
Rails的構架說明ruby
Gemfile設定Rails應用程序使用了哪些Gems套件服務器
app放Controllers、Models和Views檔案app
接下來就按造步驟來實做吧(leafor)!ide
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
**大功告成**