[教學][JDStore] 5分鐘輕鬆做出「一個商品多張圖片」功能

成果

預計時間:5分鐘

使用gem carrierwave上傳多個圖片

  • 建立新的uploader,可以一次上傳多張圖片
    rails generate uploader Avatar
    rails generate model photo product_id:integer avatar:string
    rake db:migrate

  • 使用CarrierWave裡的MiniMagick製作不同大小縮圖

app/uploaders/avatar_uploader.rb
-#include CarrierWave::MiniMagick

+include CarrierWave::MiniMagick

 process resize_to_fill: [800, 800]

  version :thumb do
    process resize_to_fill: [200,200]
  end

  version :medium do
    process resize_to_fill: [400,400]
  end
  
 - storage :file
 + if Rails.env.production?
 +   storage :qiniu #或是aws

 + elsif Rails.env.development?
 +   storage :file
 + end
  • 將圖片與產品關聯
app/models/photo.rb
class Photo < ActiveRecord::Base
   mount_uploader :avatar, AvatarUploader
   belongs_to :product
end
app/models/product.rb
class Product < ActiveRecord::Base
   has_many :photos
   accepts_nested_attributes_for :photos
end
  • 修改Controller
app/controllers/admin/products_controller.rb
...
  def new
    @product = Product.new
+   @photo = @product.photos.build #for multi-pics


  end

  def create
    @product = Product.new(product_params)

    if @product.save
+     if params[:photos] != nil
+       params[:photos]['avatar'].each do |a|
+         @photo = @product.photos.create(:avatar => a)
+       end
+     end
      redirect_to admin_products_path
    else
      render :new
    end
  end

  def update
    @product = Product.find(params[:id])

+    if params[:photos] != nil
+      @product.photos.destroy_all #need to destroy old pics first


+      params[:photos]['avatar'].each do |a|
+        @picture = @product.photos.create(:avatar => a)
+      end

+      @product.update(product_params)
+      redirect_to admin_products_path

+    elsif @product.update(product_params)
-        if @product.update(product_params)   
      redirect_to admin_products_path
    else
      render :edit
    end
  end
...
app/controllers/products_controller.rb
...
  def show
    @product = Product.find(params[:id])
+   @photos = @product.photos.all
  end
  • [後台]
    • 商品頁面
app/views/admin/products/index.html.erb
...
          <%= link_to product_path(product) do %>
-           <% if product.image.present? %>
-           <%= image_tag(product.image.thumb.url, class: "thumbnail") %>
+           <% if product.photos.present? %>
+           <%= image_tag(product.photos[0].avatar.thumb.url, class: "thumbnail") %>
            <% else %>
              <%= image_tag("http://placehold.it/200x200&text=No Pic", class: "thumbnail") %>
            <% end %>
          <% end %>
  • 修改商品頁面
app/views/admin/products/edit.html.erb
...
-    <% if @product.image.present? %>
-   <span>目前商品圖</span> <br/>
-    <%= image_tag(@product.image.thumb.url) %>
-   <% end %>

-   <div class="group">
-      <%= f.input :image, as: :file %>
-   </div>

+  <% if @product.photos.present? %>
+    <span>目前商品圖</span> <br>
+    <% @product.photos.each do |p| %>
+      <%= image_tag p.avatar.thumb.url %><br>
+    <% end %>
+  <% end %>

+  <div class="group">
+    <%= f.label :avatar %><br>
+    <%= f.file_field :avatar, :multiple => true, name: "photos[avatar][]" %>
+  </div>
...略
  • 新增商品頁面
app/views/admin/products/new.html.erb
...
  <div class="group">
-    <%#= f.input :image, as: :file %>
+    <%= f.label :avatar %><br>
+    <%= f.file_field :avatar, :multiple => true, name: "photos[avatar][]" %>
  </div>
+  <br>
...略
  • 購物車顯示
app/views/carts/index.html.erb
...
              <%= link_to product_path(cart_item.product) do %>
-               <% if cart_item.product.image.present? %>
-               <%= image_tag(cart_item.product.image.thumb.url, class: "thumbnail") %>
+               <% if cart_item.product.photos[0].present? %>
+               <%= image_tag(cart_item.product.photos[0].avatar.thumb.url, class: "thumbnail") %>
                <% else %>
                  <%= image_tag("http://placehold.it/200x200&text=No Pic", class: "thumbnail") %>
                <% end %>
              <% end %>
...略
  • 商品主頁面
app/views/products/index.html.erb
...
 <%= link_to product_path(product) do %>
-       <% if product.image.present? %>
-       <%= image_tag(product.image.thumb.url, class: "thumbnail") %>
+        <% if product.photos.present? %>
+       <%= image_tag(product.photos[0].avatar.thumb.url, class: "thumbnail") %>
        <% else %>
...
  • 產品頁面顯示
app/views/products/show.html.erb
...
-  <% if @product.image.present? %>
-      <%= image_tag(@product.image.medium.url, class: "thumbnail") %>
-    <% else %>
-      <%= image_tag("http://placehold.it/400x400&text=No Pic", class: "thumbnail") %>
-    <% end %>
    
+     <% if @photos.present? %>
+       <% @photos.each_with_index do |p, index| %>
+         <% if index == 0 %>
+           <%= image_tag p.avatar.medium.url %>
+           <div style="letter-spacing: -8px">
+         <% else %>
+           <%= image_tag p.avatar.thumb.url %>
+         <% end %>
+       <% end %>
+       </div>
+     <% else %>
+         <%= image_tag("http://placehold.it/400x400&text=No Pic", class: "thumbnail") %>
+     <% end %>
...略

參考- 實作carrierwave上傳多個圖片


延伸教學 - [JDStore] 輕鬆使用seed.db 產生「多圖片商品」



希望您喜歡這篇文章,請抽空幫我投一票,謝謝!



如果获得2等奖,我会从投票给我的VIP学员里抽出1位赠送这本有香气的励志书


comments powered by Disqus