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ư ...
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!