Kamis, 09 Agustus 2012

Upload Image di aplikasi Ruby on Rails dengan gem Paperclip


Pada tulisan kali ini di belajar Ruby on Rails akan membahas mengenai upload banyak file (multiple upload file). File yang diupload bisa berbagai macam type file, bisa berupa image, text, video, audio, dan dokumen.

Untuk mempermudah kita akan menggunakan gem paperclip. Contoh kasus yang akan dibahas adalah mengenai upload gambar, misal kita punya produk, dimana produk tersebut mempunyai banyak gambar, dan kita menginginkan bisa mengupload gambar-gambar tersebut saat create produk.

Langkah pertama:
pada gemfile tambahkan script berikut:
gem "paperclip", "~> 3.0"
gem "rmagick"
gem "jquery-rails"

Langkah kedua: 
Lakukan bundle install pada console
bundle install

Langkah ketiga:
Buat migration untuk menambahkan field-field yang dibutuhkan oleh paperclip
class AddDataToProductImage < ActiveRecord::Migration
  def self.up
    add_column :product_images, :data_file_name, :string
    add_column :product_images, :data_content_type, :string
    add_column :product_images, :data_file_size, :integer 
    add_column :design_images, :data_updated_at, :datetime 
  end
  
  def self.down
    remove_column :product_images, :data_file_name
    remove_column :product_images, :data_content_type
    remove_column :product_images, :data_file_size
    remove_column :product_images, :data_updated_at
  end
end

Langkah keempat:
Jalankan migration pada console
rake db:migrate

Langkah kelima:
Rubah model product, product_image menjadi seperti dibawah:
class Product < ActiveRecord::Base
  has_many :product_images
  accepts_nested_attributes_for :product_images, :allow_destroy => true
end

class ProductImage < ActiveRecord::Base
  belongs_to :product
  
  require 'RMagick' 
  has_attached_file :data  
end

Langkah keenam:
Perubahan pada view, yaitu me-load javascript default dan merubah form
edit file: app/views/products/_form.html.erb
<%= javascript_include_tag :defaults %>

<script type="text/javascript">
  function add_fields(link, association, content) {
    var new_id = new Date().getTime();
    var regexp = new RegExp("new_" + association, "g");
    $("#"+association).append(content.replace(regexp, new_id));
  }
</script>


<%= form_for(@product, :html => {:multipart => true}) do |f| %>
  <% if @product.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2>

      <ul>
        <% @product.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :description %><br />
    <%= f.text_area :description %>
  </div>
  <div id="product_images">
    <div class="field">
      <%= f.fields_for :product_images do |detail| %>
        <%= render "product_image", :f => detail %>
      <% end %>
    </div>
  </div>
  <div class="field">
    <%= link_to_add_fields "Tambah Gambar", f, :product_images %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
edit file: app/views/products/_product_image.html.erb
<% if !f.object.new_record? %>
  <%= image_tag f.object.data.url(:thumb) %>
<% end %>
<%= f.file_field :data %>
<%  if f.object.new_record? %>
  <%= link_to_function("Hapus", "$(this).parent('fieldset').remove()") %>
<%  else %>
  <%= link_to "Hapus gambar", delete_image_products_path(id: f.object.id), method: :delete,
  data: { confirm: 'Apakah Anda yakin untuk menghapus gambar?'  }
  %>
<% end %>

Langkah ketujuh:
Tambahkan script berikut pada app/helpers/application_helper.rb
def link_to_add_fields(name, f, association)
  new_object = f.object.class.reflect_on_association(association).klass.new
  fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
    render(association.to_s.singularize, :f => builder)
  end
  link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")", :class => "addField")
end

Langkah kedelapan:
Tambahkan modul delete image pada app/controllers/products_controller.rb
def delete_image
  @product_image = ProductImage.find(:first, :conditions => ["id = ?", params[:id]])
  @product = @product_image.product
  if @product  
    @product_image.destroy
    redirect_to :back, :notice => 'Gambar telah berhasil dihapus.'
  else
    redirect_to products_url, :notice => 'Gambar tidak ditemukan.'
  end
end

Langkah terakhir:
Tambahkan script berikut pada file app/views/products/show.html.erb
<% @product.photos.each do |photo| %>
  <%= image_tag photo.data.url %>
<% end %> 
Selamat mencoba :)

Referensi : http://shiningthrough.co.uk/Dynamic-multiple-image-uploads-with-Ruby-on-Rails

Tidak ada komentar:

Posting Komentar