Upload hình ảnh với Rails và Paperclip

Giới thiệu gem Paperclip

Paperclip có lẽ là giải pháp quản lý tập tin đính kèm phổ biến nhất cho Rails (hơn 13 triệu lượt tải về) nó được đánh giá khá cao trong việc upload cũng như thao tác ảnh. Những điều để đưa gem này trở nên thành công vì nó có một cộng đồng lớn sử dụng, có nhiều tính năng và tài liệu hướng dẫn dễ hiểu và kỹ lưỡng.

1. Cài đặt

trước khi chúng ta có thể bắt đầu và sử dụng được paperclip trước hết chúng ta phải cài đặt ImageMagick. ImageMagick là backend tool của paperclip. bạn có thể tải về các phiên bản của ImageMagick ở ĐÂY đầu tiên chúng ta sẽ tạo project mẫu: rails new UploadingWithPaperclip -T sau đó tích hợp gem paperclip vào project

gem "paperclip", "~> 5.1"

chạy bundle để cài đặt

bundle install

Tiếp theo chúng ta có thể tạo một dữ liệu mẫu quản lý sách làm ví dụ . quản lý sách sẽ bao gồm mỗi cuốn sách sẽ có tiêu đề mổ tả tên tác giả và ảnh bìa. để bắt đầu tạo ta sử dụng như sau

rails g model Book title:string description:text image:attachment author:string
rails db:migrate

dòng lệnh trên sẽ tạo cho chúng ta một model book với những trừng ta đã nêu ở trên và đồng thời tạo thêm các trường để làm việc với paperclip là

image_file_name
image_file_size
image_content_type
image_updated_at

trái ngược với Carrierwave, Paperclip không có tiệp riêng để cấu hình thay vào đó tất các thiết lập được định nghĩa bên trong mô hình bằng cách sử dụng has_attached_file chúng ta bắt đầu thêm nó vàomodel/book.rb

has_attached_file :image

tiếp theo chúng ta tạo controller và view

Controller

Books_controller.rb

class BooksController < ApplicationController
  before_action :set_book, only: [:show, :download]

  def index
    @books = Book.order('created_at DESC')
  end

  def new
    @book = Book.new
  end

  def show
  end

  def create
    @book = Book.new(book_params)
    if @book.save
      redirect_to books_path
    else
      render :new
    end
  end

  private

  def book_params
    params.require(:book).permit(:title, :description, :image, :author)
  end

  def set_book
    @book = Book.find(params[:id])
  end
end

View

views/books/index.html.erb

<h1>Bookshelf</h1>
 
<%= link_to 'Add book', new_book_path %>
<ul>
  <%= render @books %>
</ul>

chúng ta tạo thêm partial:

<li>
  <strong><%= link_to book.title, book_path(book) %></strong> by <%= book.author %>
</li>

bây giờ chúng ta bắt đầu thêm vào routes: config/routes.rb

    resources :books
    root to: 'books#index'

tạm thời đã xong bây giờ chúng ta bắt đầu công việc upload files nhé.

uploading file

việc tải lên bằng Paperclip khá dễ dàng chúng ta chỉ cần cho phép các thuộc tính tương ứng. đầu tiên chúng ta cần tạo 1 form để nhập các trường như chúng đã quy ước lúc đầu. views/books/new.html.erb

<h1>Add book</h1>
 
<%= render 'form', book: @book %>

chúng ta nên tạo một partial cho việc này views/books/_form.html.erb

<%= form_for book do |f| %>
    <div>
      <%= f.label :title %>
      <%= f.text_field :title %>
    </div>

    <div>
      <%= f.label :author %>
      <%= f.text_field :author %>
    </div>

    <div>
      <%= f.label :description %>
      <%= f.text_area :description %>
    </div>

    <div>
      <%= f.label :image %>
      <%= f.file_field :image %>
    </div>

    <%= f.submit %>
<% end %>

thêm Validations

Validations trong paperclip bạn có viết bằng cách sử dụng các helpers có sẳn như validates_attachment_presencevalidates_attachment_content_type hoặc validates_attachment một method đễ xác định nhiều quy tắc cùng một lúc. ở đây chúng ta sử dụng validates_attachment models/book.rb

validates_attachment :image,
    content_type: { content_type: /\Aimage\/.*\z/ },
    size: { less_than: 1.megabyte }

ở đoạn code trên chúng ta chỉ yêu cầu tiệp tin phải là hình ảnh có kích thước dưới 1 megabyte. nếu Validations fail se có thông báo lỗi xuất hiện. để quản lý những lỗi do validation trả về chúng ta xây dựng thêm 1 form để hiển thị nó. views/shared/_errors.html.erb

<% if object.errors.any? %>
    <h3>Some errors were found:</h3>
    <ul>
      <% object.errors.full_messages.each do |message| %>
          <li><%= message %></li>
      <% end %>
    </ul>
<% end %>

thêm nó vào file _form_html_erb:

<%= render 'shared/errors', object: book %>
<%= form_for book do |f| %>
    .....

Hiển thị hình ảnh

bây giờ chúng ta sẽ xây dựng form để hiển thị hình ảnh và thông tin sau khi đã upload thành công bằng cách sử dụng image_tag helper và method url: views/books/show.html.erb

<h1><%= @book.title %> by <%= @book.author %></h1>
<%= image_tag(@book.image.url) if @book.image.exists? %>
<p><%= @book.description %></p>

demo.

đầu tiên chúng ta màn hình index hiển thị click vào add books để tiến thành thêm sách mới upload thành công sẽ chuyển chúng ta về lại trang index đồng thời hiển thị cuốn sách mà chúng ta vừa mới thêm