##以商店product添加多图为例 ###paperclip
Step 1 1 2 gem 'paperclip' bundle install
重开rails s
Step 2 修改app/models/product.rb,加入
1 2 3 has_attached_file :image , styles: { medium: "300x300>" , thumb: "100x100>" }, default_url: "/images/:style/missing.png" validates_attachment_content_type :image , content_type: /\Aimage \/.*\Z/
Step 3 1 rails generate paperclip product image
确认生成的XXXXXXX_add_attachment_image_to_products.rb如下
1 2 3 4 5 6 7 8 9 10 11 class AddAttachmentImageToProducts < ActiveRecord::Migration def self .up change_table :products do |t | t.attachment :image end end def self .down remove_attachment :products , :image end end
Step 4 在app/views/admin/product相关页面加入如下
1 2 3 +<div> +<%= f.input :image , as: :file %> +</div>
Step 5 修改app/controllers/admin/products_controller如下
1 2 3 4 private def product_params params.require (:product ).permit(:title , :description , :quantity , :price , :image ) end
Step 6 图片调用方法
1 2 3 <%= image_tag @user .avatar.url %> <%= image_tag @user .avatar.url(:medium ) %> <%= image_tag @user .avatar.url(:thumb ) %>
carrierwave(我第一次实操的时候上面的paperclip和这个都进行了操作,所以不知道最后是那个起了作用,因而可以分开实验下) Step 1 1 2 +gem 'carrierwave' +gem 'mini_magick'
Step 2 1 2 $ convert -version $ brew install imagemagick
Step 3 1 2 3 $ rails g uploader image $ rails g model photo product_id:integer image:string $ rake db:migrate
Step 4 接著Photo中加入關係與mount_uploader
photo.rb 1 2 3 4 5 class Photo < ActiveRecord::Base belongs_to :product mount_uploader :image , ImageUploader end
在Product中也做相關宣告
product.rb 1 2 3 4 5 6 7 class Product < ActiveRecord::Base has_many :photos , dependent: :destroy accepts_nested_attributes_for :photos end
Step 5(这步可不做) 在Rails console確認關係
首先需要修正無法在 rails c 讀取到 uploader.rb 的問題:
config/appliaction.rb 1 2 3 4 5 6 7 module Artstore class Application < Rails::Application …(略) config.active_record.raise_in_transactional_callbacks = true + config.autoload_paths += %W(#{config.root} /app/uploaders) end end
接下來在Rails c輸入Product.first.photos應該就可以確認結果,如下結果就是成功,但因為目前我們還沒上傳任何圖片,回傳的是[ ],而到目前為止圖片上傳功能的Model端設定已經OK。
Step 6 設定上傳圖片時,同時切成各種尺寸的圖片供使用
然後編輯你的image_uploader.rb 讓MiniMagick可以用還可將照片切成各種尺寸
app/uploaders/image_uploader.rb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class ImageUploader < CarrierWave::Uploader::Base …(略) + include CarrierWave::MiniMagick …(略) + process resize_to_fit: [800 , 800 ] + version :thumb do + process resize_to_fill: [200 ,200 ] + end + version :medium do + process resize_to_fill: [400 ,400 ] + end end
Step 7 設定.gitignore (選擇性步驟,但建議作)
上傳處理後的圖片自動存放在public/uploads底下,而建議將public/uploaders 資料夾放入 .gitignore,因為commit這些上傳圖片的變更,事實上也不太有用。
1 2 3 .gitignore …(略) + public /uploads
Step 8 修改Controller與頁面
完成以上步驟後,接下來就只要在Controller與頁面加入對應的上傳欄位就可以啦~ 以我練習的專案來說,是在新增商品的步驟做圖片上傳,所以在Product#new底下,除了原本的@product之外,多宣告一個@photo,並且在product_params的底下允許存取image這個欄位,像這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def new @product = Product .new @photo = @product .photos.new end …(略) private def product_params params.require (:product ). permit(:title , :description , :quantity , :price , photos_attributes: [:image ]) end
然後在對應的new.html.erb,加入該上傳欄位:
new.html.erb 1 2 3 4 5 6 7 8 9 10 …(略) <div class ="form-group" > <%= f.simple_fields_for :photos do |c | %> <%= c.input :image , as: :file %> <% end %> </div> # 這邊是用我自己在練習的專案作說明,使用simple_form, # 然後是在已有的表單底下,增加額外的欄位,所以用的是fields_for指令, # 而要從本地端電腦上傳圖片,所以是as: :file。
或者你也可以給定圖片所在的遠端URL,來上傳圖片,CarrierWave已經很貼心的幫我們做好整合,也有固定的命名方式,所以只要更改上傳欄位的名稱為 :remote_xxx_url,並在product_params的底下允許存取remote_xxxx_url這個欄位,就OK啦,像這樣:
new.html.erb 1 2 3 4 5 6 7 8 …(略) <div class ="form-group" > <%= f.simple_fields_for :photos do |c | %> <%= c.input :image , as: :file %> <%= c.input :remote_image_url%> <% end %> </div>
Step 9 在頁面中選擇其中一種方式上傳後,專案底下public/uploads/photos/image應該就會有三張不同尺寸的圖片囉~
之後如果要在頁面中使用圖片路徑,像下面使用就可以指向圖片所在位置把對應圖片叫出來囉~
1 2 3 4 5 6 7 Photo .first.image.url =>"/uploads/photo/image/1/xxx.jpg" Photo .first.image.thumb.url =>"/uploads/photo/image/1/thumb_xxx.jpg" Photo .first.image.medium.url =>"/uploads/photo/image/1/medium_xxx.jpg"
附录 我在实现实现上传和显示是最终使用的是如下的语句
app/controller/admin/templates.rb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def new @template = Template .new @templatephoto = @template .templatephotos.build end def create @template = Template .new(template_params) if @template .save if params[:templatephotos ] != nil params[:templatephotos ]['image' ].each do |a | @templatephoto = @template .templatephotos.create(:image => a) end end redirect_to admin_templates_path else render :new end end private def template_params params.require (:template ).permit(:title , :description , :price , :version , :proportion , templatephoto_attributes: [:image , :id ]) end
new.html.erb 1 2 3 4 5 6 ...(略) <div class ="group" > <%= f.file_field :image , :multiple => true , name: "templatephotos[image][]" %>("请上传5张图片" )<br> </div> <%= f.submit "Submit", data: { disable_with: "Submitting..." } %>
edit.html.erb 1 2 3 4 5 6 7 8 9 10 <% if @template .templatephotos.present? %> <span>目前商品图</span><br> <% @template.templatephotos.each do |p| %> <%= image_tag p.image.thumb.url %><br / > <% end %> <% end %> <div class ="group" > <%= f.file_field :image , :multiple => true , name: "templatephotos[image][]" %>("请上传5张图片" )<br> </div>