Upload image using Carrierwave

Carrierwave là một trong nhưng gem mà có thể giúp các bạn upload file lên server như Paperclip, Dragonfly, Shrine … Nhưng mình thích Carrierwave bởi nó có rất nhiều tính năng và cũng dễ sử dụng nữa. Trong bài viết này mình sẽ giới thiệu với các bạn một cách tổng quát về cách sử dụng carierwave.

Tạo một application Demo

Như mọi bài mình sẽ tạo một app demo giúp các bạn có thể follow dễ dàng hơn rails new demo Tiếp theo chúng ta tạo một model Post trong đó có các thuộc tính title, body, image rails g model Post title:string body:text image:string Sau khi hoàn tất bạn chạy rake db:migrate nhé

Tiếp theo mình sẽ tạo một controllers và view cho post posts_controller.rb

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update]
 
  def index
    @posts = Post.order "created_at DESC"
  end
 
  def show
  end
 
  def new
    @post = Post.new
  end
 
  def create
    @post = Post.new post_params
    if @post.save
      redirect_to posts_path
    else
      render :new
    end
  end
 
  def edit
  end
 
  def update
    if @post.update_attributes(post_params)
      redirect_to post_path(@post)
    else
      render :edit
    end
  end
 
  private
 
  def post_params
    params.require(:post).permit :title, :body, :image
  end
 
  def set_post
    @post = Post.find_by params[:id]
  end
end


views/posts/index.html.erb

<h1>Posts</h1>
 
<%= link_to "Add post", new_post_path %>
 
<%= render @posts %>

views/posts/_post.html.erb

<h2><%= link_to post.title, post_path post  %></h2>
 
<p><%= truncate post.body, length: 150 %></p>
 
<p><%= link_to "Edit", edit_post_path post %></p>
<hr>

Config Carrierwave

Trong file Gemfile bạn thêm dòng này vào nhé gem “carrierwave” và chạy bundle install Carrierwave nó lưu file config trong folder uploader. Trong file này bạn có thể cấu hình rất nhiều thứ ví dự địa chỉ lưu file trên server, validation extension, hay định nghĩa các version image thumn, origin …. Để tạo file này thì bạn dùng lệnh sau rails generate uploader Image Một file image_uploader sẽ được tạo trong app/uploaders.

class ImageUploader < CarrierWave::Uploader::Base

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{model.id}"
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end
end

Ở trong file config mình sẽ định nghĩa nơi lưu file trong hàm store_dir và mình định nghĩa nhưng định dang mà có thể upload được lên server trong hàm extension_white_list

Bước tiếp theo chúng ta phải mount file uploader này vào model .

Model/post.rb

mount_uploader :image, ImageUploader

trong câu lệnh trên thì image là trường db. ImageUploader là class của file uploader. đến đây thôi bạn có thể thao tác vơi image như một trường bình thường. views/posts/new.html.erb

<h1>Add post</h1>
 
<%= render "form", post: @post %>

để tiện cho việc update, create cho app mình sẽ tạo một partial _form.html.erb để tránh việc DRYcode views/posts/_form.html.erb

<%= form_for post do |f| %>
  <div>
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>
 
  <div>
    <%= f.label :body %>
    <%= f.text_area :body %>
  </div>
 
  <div>
    <%= f.label :image %>
    <%= f.file_field :image %>
  </div>
 
  <%= f.submit %>
<% end %>

views/posts/edit.html.erb

<h1>Edit post</h1>
 
<%= render "form", post: @post %>

views/posts/show.html.erb

<%= link_to "All posts", posts_path %>
<h1><%= @post.title %></h1>
 
<%= image_tag(@post.image.url, alt: "Image") if @post.image? %>
 
<p><%= @post.body %></p>
 
<p><%= link_to "Edit", edit_post_path @post  %></p>

Về cơ bản như vậy là bạn có thể chạy được app rồi . bạn thử khởi động rails s . và vào đường link: localhost:3000/posts để thử nhé

I18N Carrierwave

Đây là nhưng message khi bạn thao tác với carrierwave.bạn có thể thay đổi trong file ja.yml nhé.

errors:
  messages:
    carrierwave_processing_error: "Cannot resize image."
    carrierwave_integrity_error: "Not an image."
    carrierwave_download_error: "Couldn't download image."
    extension_whitelist_error: "You are not allowed to upload %{extension} files, allowed types: %{allowed_types}"
    extension_blacklist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"

Một số lệnh trong Console với Carrierwave

Gán ảnh cho một đối tượng

post = Post.first # giả sử  post tồn tại
image = File.open file_path
post.image = image
post.save!

Delete anh của một đối tượng

post.remove_image!
post.save
post.reload
post.image?
 >> nil

lấy path file storage

post.image.path

Kiểm tra đối tượng có image hay không

post.image?

Conclusion

Trên đây mình đã giới thiệu gem Carrierwave cách sử dụng và tùy biến. Hy vọng sẽ giúp ích được bạn 😄