Ruby gem 'Carrierwave' 上傳檔案神器的簡易安裝與使用


Ruby版本:2.1.2
Rails版本:4.1.0
開發環境:MAC OSX 10.9.4

Carrierwave是Rails應用程式裏面上傳檔案的簡單工具,上傳的檔案種類不限,在這邊跟大家分享一下安裝與使用carrierwave的方法,主要針對圖片的上傳和簡易編修。主要是從Railscasts學來的,請各位多指教。

以下已經預先完成的項目: 1. 已經建立了一個rails的應用程式 2. 擁有一個product model,底下有title和description兩個項目 3. 已經有基本的products CRUD Controller及view

進入正題:

1. 設定及安裝

首先打開Gemfile,輸入

gem 'carrierwave'
gem 'rmagick'

備註1:在安裝rmagick的時候要確認有安裝ImageMagick,若無,則先進行安裝。 備註2:安裝ImageMagick需要使用Homebrew,如果還沒裝Homebrew則請先到該網站尋找指令進行安裝。如果沒有意外的話指令是:

ruby -e "$ (curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

已經安裝Homebrew的話接下來安裝ImageMagick

$  brew install imagemagick

carrierwave是用來上傳檔案的gem,至於rmagick是用來處理圖片的gem,其實用carrierwave內建的工具也可以,但rmagick提供比較方便的用法。

接著到Command Line 輸入

$  bundle

到這裡最基本的安裝算完成了。

2. 設定Uploader

接下來要使用Carrierwave來建立一個uploader,稍後所有上傳的圖片都會存放在這個uploader裡面。

$  rails generate uploader image

產生了一個uploader以後,我們在model當中也需要一個安置檔案的地方。如同剛才所說,目前我們的product model裡面只有title和description兩個項目,現在需要另一個image項目來安放圖片。如果你有未卜先知,早就知道要放圖片,那你的model裡應該會有一個image欄位,屬性是string,用以存放網址。那如果很不幸的沒有,那我們可以一起來增加這個欄位。

$  rails generate migration add_image_to_products

接著到新產生的migration檔案裡面進行修改,增加product中的欄位

class AddImageToProducts < ActiveRecord::Migration
  def change
    add_column :products, :image, :string
  end
end

每個人檔案名稱前面那串數字會長得不一樣,不過無妨,內容一樣就好。完成以後進行migration。

$  rake db:migrate

接下來到model檔案裡面,把剛才的image uploader與model做連結,如此一來,確認在此model中上傳的檔案,會傳到該uploader當中。如果你的model檔案跟我的一樣乾乾淨淨,濕亮有型,那把uploader安裝上去以後就會長得像下面那樣。

class Product < ActiveRecord::Base
  mount_uploader :image, ImageUploader
end

mountuploader是一個動作,而:image是我們剛剛在migrate時幫product這個model設定的新欄位(addcolumn),而ImageUploader是我們剛剛在command line使用的 $ rails generate uploader image 這個指令所形成的名稱,如果你打的指令是 $ rails generate uploader sperm,那你在這邊輸入的就會是SpermUploader,不過我相信不會有人想要upload那個東西的。

另外,因為要在model的image欄位更新,因此在controller裡面也要設定為允許更新,在controller最下方我們製作CRUD時private的地方。

private
    def product_params
      params.require(:product).permit(:title, :description, :quantity, :image)
    end
end

在最後方加上 :image,我們就可以對:image欄位進行存取。

3. 在View裡面進行設定

接下來就是到view裡面找到new.html.erb,讓我們在產生新的product時,使用者可以選擇上傳圖片檔案。修改大概如下:

app/views/products/new.html.erb

<%= form_for @product do |f| %>
  Title: <%= f.text_field :title %>
  Description: <%= f.text_area :description %>
  Quantity: <%= f.text_field :quantity %>
  <%= f.file_field :image %>
  <%= f.submit "Submit" %>
<% end %>

重點在於第5行要加上一個可以上傳圖片的表格欄位file_field,並註明是:image即可。接下來就到index.html.erb,在列表中加上可以呈現圖片的區塊。

app/views/products/index.html.erb

<%= image_tag @product.image_url.to_s %>

不管加在哪,只要確定@product有在controller中設定好即可,imageurl是預設的helper,tos是要確定把上傳的路徑轉變為字串,以免發生錯誤。

至此,基本的Carrierwave運作就算完成了,只要依照正常程序把product建立起來,並在選擇檔案時選擇一張圖片,就可以呈現在index頁面囉~

4. 利用RMagick將圖片微調

雖然上傳成功,但上傳的圖片大小不對,此時利用RMagick來進行小幅度的修正。

需要在Imageuploader裡面進行調整,檔案裡面有非常多的註解,我們需要把幾個東西解開,首先是第6行的內容。

include CarrierWave::RMagick

把前方的 # 符號拿掉,取消註解,就變成上方的樣子,此行會將rmagick這個gem整合到這個uploader裡面來,就可以使用rmagick的功能。接下來到約莫35行的位置,會看到以下內容

 # version :thumb do
 #   process :resize_to_fit => [50, 50]
 # end

這時要使用rmagick的公式,在上傳圖片以後,替我們裁切一個預覽的版本,不傷及原本的檔案。因此改為以下內容:

 version :thumb do
    process :resize_to_limit => [200, 200]
 end

藉此,ImageUploader會替我們使用rmagick,創造一個thumb的版本圖片,大小限制在長200寬200以內的圖片,不改變原本圖片的比例。我們要用這個版本的圖片來創造一個list,回到index.html.erb,把展示圖片的image_tag改成以下內容:

app/views/products/index.html.erb

<%= image_tag @product.image_url(:thumb).to_s %>

這樣一來,他就會去抓取:thumb版本的圖片,讓我們的圖片不至於過大。到這邊就是簡單的Carrierwave使用囉,希望大家都使用得順利!

(備註:如果上傳圖片後出現stack level too deep的錯誤,則需要修改Gemfile為gem “rmagick”, :require => “RMagick”,此為OSX會產生的錯誤)

希望大家都成功!