Tìm hiểu về gem carrierwave
Bài đăng này đã không được cập nhật trong 3 năm
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 User
và Micropost
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.
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