+1

Tìm hiểu về gem carrierwave

1. Carrierwave là gì?

Gem CarrierWave cung cấp một giải pháp đơn giản và hiệu quả để upload một hay nhiều file trong ứng dụng Ruby.

2. Dùng Carrierwave khi nào?

Khi ứng dụng của bạn cần thiết để người dùng tải file lên từ máy của họ (ảnh, file tài liệu) thì CarrierWave được lựa chọn như một giải pháp đơn giản và hiệu quả nhất.

3. Dùng Carrierwave như thế nào?

Cài đặt

Thêm dòng sau vào Gemfile:

gem "carrierwave"

Sau đó cài đặt bằng lệnh

$ bundle install

Tiếp theo, chúng ta sẽ hoàn thiện một ví dụ về tải kèm ảnh trong bài viết giống như dạng đăng một status có kèm ảnh trên Facebook.

Trước hết, ta khởi tạo model UserMicropost với nội dung:

class User < ActiveRecord::Base
	has_many :microposts, dependent: :destroy
    # and more infomation about user
end
class Micropost < ActiveRecord::Base
	belongs_to :user
    validates :user_id, presence: true
    validates :content, presence: true, length: {maximum: 150}
end

Tạo một uploader bằng lệnh

$ rails generate uploader Picture

lệnh trên sẽ sinh ra một file app/uploaders/picture_uploader.rb có nội dung như sau:

class PictureUploader < CarrierWave::Uploader::Base
	storage :file
end

Tới đây, chúng ta cần có một model có thuộc tính picuture đơn giản dùng để lưu tên của ảnh. Trong ảnh là model Microposts, có chứa user_id để liên kết với model User, và chứa thuộc tính picture dạng string để lưu tên ảnh được upload.

micropost_model_picture.png

Trong model Micropost thêm dòng

mount_uploader :picture, PictureUploader

Trong đó PictureUploader đã được xác định trong file picture_uploader.rb nói trên.

Nội dung file models/micropost.rb

class Micropost < ActiveRecord::Base
  belongs_to :user
  default_scope -> { order(created_at: :desc) }
  mount_uploader :picture, PictureUploader
  validates :user_id, presence: true
  validates :content, presence: true, length: { maximum: 140 }
end

Form để tạo mới một bài viết được tạo đơn giản như sau:

<%= form_for @micropost do |f| %>
	<div class="field">
    	<%= f.text_area :content, placeholder: "Create new post ..." %>
    </div>
    <%= f.submit "Post", class: "btn btn-primary" %>
    <span class="picture">
    	<%= f.file_field :picture, accept: "image/jpeg, image/gif, image/png, image/jpg" %>
    </span>
<% end %>

<script type="text/javascript">
	$("#micropost_picture").bind("change", function(){
    	var size_in_megabytes = this.files(0).size/1024/1024;
        if (size_in_megabytes > 1) {
        	alert("Maximum file size is 1MB. Please choose an other file!");
        }
    });
</script>

Như trên chúng ta giới hạn các loại ảnh có thể upload là: jpeg, gif, png, jpg và kích thước tối đa là 1MB.

Trong phần view để hiển thị phần uploader, chúng ta cần thêm thẻ file_field trong form micropost:

<%= form_for(@micropost, html: { multipart: true }) do |f| %>
  <div class="field">
    <%= f.text_area :content, placeholder: "Compose new micropost..." %>
  </div>
  <%= f.submit "Post", class: "btn btn-primary" %>
  <span class="picture">
    <%= f.file_field :picture %>
  </span>
<% end %>

Khi ảnh đã được tải lên, chúng ta có thể hiển thị nó bằng cách sử dụng image_tag:

<%= image_tag micropost.picture.url if micropost.picture? %>

trong đó phương thức picture? được sinh tự động bởi CarrierWave, nó sẽ trả về giá trị false nếu không tồn tại ảnh, khi đó việc hiển thị ảnh được bỏ qua.

Upload nhiều file cùng một lúc

Carrierwave cũng hỗ trợ khả năng tải lên cùng lúc nhiều file. Tạo thêm một cột trong database để có thể lưu trữ một mảng dữ liệu:

rails g migration add_pictures_to_microposts pictures:json
rake db:migrate

Chỉnh sửa lại file model và thêm dòng:

class Micropost < ActiveRecord::Base
	mount_uploaders :pictures, PictureUploader
end

Khi đó trong form upload file cần sửa lại:

<%= form.file_field :pictures, multipule: true %>

Thay đổi thư mục lưu trữ file

Khi muốn thay đổi thư mực lưu trữ file, bạn chỉ cần override phương thức store_dir:

class MyUploader < CarrierWave::Uploader::Base
	def store_dir
    	"public/app/upload/"
    end
end

Nếu bạn muốn lưu file ở ngoài thư mục gốc của project, chỉ cần override phương thức cache_dir:

class MyUploader < CarrierWave::Uploader::Base
  def cache_dir
    '/tmp/projectname-cache'
  end
end

Xóa file đã upload

Khi muốn xóa một file bạn đã upload, bạn có thể thêm một checkbox vào form:

<%= form_for @micropost, html: { multipart: true } do |f| %>
  <p>
    <label>
      <%= f.check_box :remove_avatar %>
      Remove avatar
    </label>
  </p>
<% end %>

Hy vọng những gì mình chia sẻ có thể giúp các bạn làm quen được với CarrierWave.

Thanks for reading!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí