12/08/2018, 16:31

File upload using Paperclip

Ở bài trước Handling file upload using Ruby on Rails 5 API chúng ta đã cùng nhau tiềm hiểu về chủ đề "Gửi các dữ liệu JSON cơ bản được tạo ra từ các strings đến một API", và ở phần trước chúng ta đã làm việc với gem Carrierwave, tuy nhiên mình cũng có đọc một số bài trên Viblo và vẫn thấy thiếu ...

Ở bài trước Handling file upload using Ruby on Rails 5 API chúng ta đã cùng nhau tiềm hiểu về chủ đề "Gửi các dữ liệu JSON cơ bản được tạo ra từ các strings đến một API", và ở phần trước chúng ta đã làm việc với gem Carrierwave, tuy nhiên mình cũng có đọc một số bài trên Viblo và vẫn thấy thiếu thiếu.Tiếp tục chủ đề lần trước tuy nhiên chúng ta sẽ làm việc với gem Paperclip để chúng ta có cái nhìn toàn diện hơn về chủ đề lần trước và cũng là cơ hội để tìm hiểu thêm về gem Paperclip. Để cài đặt gem chúng ta sử dụng:

#Gemfile.rb
gem "paperclip", "~> 5.0.0.beta1"

và install nó:

 bundle install

Uploading a single file

Đầu tiên, generate migration sẽ tạo tập tin đính kèm trong database.Bạn sẽ tạo một model giống với phần tệp đính kèm trong trường hợp này của chúng ta là picture

rails g paperclip item picture

Ok, bạn cũng đừng quên migrate database nhé:

 rails db:migrateiles

Tiếp theo thêm các dòng sau vào trong model:

#app/models/item.rb
class Item < ApplicationRecord
  has_attached_file :picture, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
  validates_attachment :picture, presence: true
  do_not_validate_attachment_file_type :picture
end

Chúng ta cùng giải thích một chút về các method ở trên nhé:

  1. has_attached_file là main method cho việc tạo một attachment.First argument là attribute của model sẽ được sử dụng cho file attachment(trong trường hợp này là :picture, như chúng ta đã tạo trong database migration). style là một optional parameter sẽ được sử dụng để upload file trong folders khác dự trên file size của chúng.Trong ví dụ này medium photos có kích thước >= 300x300 pixels, sẽ được put trong thư mục: /images/medium. default_url cũng là một optional parameter được sử dụng để chỉ định đường dẫn mặc định của image sẽ được trả về nếu object từ model không có attached image.Bạn có thể put default image trong app/assets/images/(medium or thumb)/.Nếu bạn upload files khác ảnh, bạn có thể bỏ qua optional arguments.
  2. validates_attachment có thể can validate content-type, presence, và size của file.Bạn có thể nhìn thấy các check syntax cho tất cả validation.Trong ví dụ đơn giản này chúng ta chỉ check presence.
  3. do_not_validate_attachment_file_type được sử dụng như trong trường hợp sau với file type validations của paperclip.

Vấn đề thứ 3 chúng ta thêm permitted parametersẽ được accept ``:picture`:

#app/controllers/items_controller.rb
def item_params
  params.require(:item).permit(:name, :description , :picture) # Add :picture as a permitted parameter 
end

Bước cuối cùng là add :picture vào Jbuilder view, vì vậy khi chúng ta GET một item, nó sẽ trả về ảnh của nó:

json.extract! @item, :id, :name, :description, :picture, :created_at, :updated_at

Uploading multiple files

Attaching a document model to item

Để upload multiple files với Paperclip một cách hiệu quả, add model khác sẽ related với main model và sẽ chứa các files.Trong ví dụ thực tế này, chúng ta sẽ thêm tùy chọn có thể có nhiều file PDF.Đầu tiên chúng ta tạo model:

rails g model document item:references
rails g paperclip document file

Bước generator đầu tiên sẽ tạo ra một model tên là document với một tên là string, item:references sẽ tạo ra belongs_to :item reference điều đó có nghĩa là một item và document sẽ có một quan hệ one-to-many.generator thứ 2 sẽ tạo ra field cho attachment. Một reference cũng sẽ được thêm vào Item model như sau:

class Item < ApplicationRecord
  #app/models/item.rb has_many :documents
  #...
end

Migrate để thay đổi database schema:

rails db:migrate

Với bước kết thúc, document model đã có thể configure.Bạn nên add thêm method rất cần thiết sau đây và validates PDF documents.

#app/models/document.rb
class Document < ApplicationRecord
  belongs_to :item
  has_attached_file :file
  validates_attachment :file, presence: true, content_type: { content_type: "application/pdf" } 
end

Lúc này validates attachment sẽ check nếu như document type là application/pdf. Với các kết quả trên thì model document đã hoàn toàn sẵn sàng.Tiếp theo thứ cần handles trong controller và handle creation của multiple files.

Tham khảo: Handling file upload using Ruby on Rails 5 API

0