[Ting's笔记Day6] 活用套件carrierwave gem: (1)在Rails实现图片上传功能

carrierwave是一款经典的图片上传套件,本篇的目标是先在本地端(development)的rails专案试成功gem。
(预计中集的进度会练习怎么利用Amazone S3架设图片上传Host,
并再下集远端(production)实作上传,敬请期待!)

http://img2.58codes.com/2024/20111177jA3W9YiK5l.png

在阅读任何Github上的README.md,有一点很重要的是知道因为环境设定的不同,必须渐渐了解哪些步骤可以跳过、哪些变数需要修改成符合自己专案性质的名称,这点身为新手的我,将会靠练习活用各式各样的gem来进步。:)

这次我们会更动的档案/资料夹如下:

Rails的架构说明Gemfile设定Rails应用程式使用了哪些Gems套件app放Controllers、Models和Views档案

接下来就按造步骤来实作吧!

A. 在gemfile加入套件,重启rails server:

首先我们按照carrierwave在githhub上说明档的指示,前往/专案名称/gemfile,新增程式码:
gem 'carrierwave', '~> 1.0'

README.md告诉我们CarrierWave的版本需求:Rails 4.0 or higher and Ruby 2.0,我的ruby 2.4.2 Rails 5.1.6,所以没有问题~

每次新增任何新的Gem到Gemfile,就要在Terminal输入bundle install处理相依性,然后rails s重启伺服器。
tingdeMacBook-Air:yelpdemo tingtinghsu$ bundle installtingdeMacBook-Air:yelpdemo tingtinghsu$ bundle info carrierwave  * carrierwave (1.2.3)Summary: Ruby file upload libraryHomepage: https://github.com/carrierwaveuploader/carrierwavePath: /Users/tingtinghsu/.rvm/gems/ruby-2.4.2/gems/carrierwave-1.2.3

B. 用rails g指令,新增Image uploader功能

接下来就可以看到carrierwave的厉害之处了,在此我需要将自己的餐厅(restaurants)资料库建立新的图片(image)栏位,所以把carrier的指令客製化成自己的专案。
指令rails g uploader Image帮助我们在此路径:app/uploaders/image_uploader.rb新增了档案。
打开image_uploader.rb看看里面的类别写法:

class ImageUploader < CarrierWave::Uploader::Base  storage :file  #storage :fog  # Override the directory where uploaded files will be stored.  # def store_dir    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"end

这个部分指的是:
如果我把储存档案的地方放在本地端(localhost),就要把storage :file前的#注解拿掉
相对的,想要把储存档案的地方放在远端(Heroku),把storage :fog前的#注解拿掉

在本篇里,CarrierWave会把我上传的图片将会放在/public/uploads/restaurant/image

C. 建立资料库上传Image所需栏位

建立迁移档(migration,修改资料库结构)
rails g migration add_image_to_restaurants image:string并在资料库增加上传图片的栏位:
rake db:migrate然后重启伺服器:rails s

顺利的在db/migrate跑出了add_image_to_restaurants.rb档案。打开来瞧瞧:

class AddImageToRestaurants < ActiveRecord::Migration[5.1]  def change    add_column :restaurants, :image, :string  endend

D. 修改Models,让资料库準备好存取图片的功能

接下来我们修改跟ActiveRecord有关的Models。mount Model里面,这个名为uploader上传功能小帮手,未来它会帮我们翻译资料库语言(SQL)跟资料库要资料(餐厅图片)。:

Models: app/models/restaurant.rb

class User < ActiveRecord::Base  mount_uploader :image, ImageUploaderend

在rails官网提到:

Active Record 是MVC的M(Model)表现商业逻辑与资料的层级,负责新增与操作需要持久存在资料库里的资料。Active Record本身是ORM(Object Relational Mapping,物件关联映射)系统的描述。

E. 修改Views

资料库的上传功能已经準备好了,接下来到Views跟表单沟通,请让表单能够接受上传的图片。
app/views/restaurants/_form.html.erb,修改成可以上传照片的form type(表单型态)。
<%= form_with(model: restaurant, local: true, :html => { multipart: true }) do |form| %>

我们来增加:「上传图片」栏位,让使用者能在视觉上看得见新栏位,并修改上传图片的档案(file)类型为form.file_field,不同于其他纯文字(text)栏位如地址、电话的form.text_field

  <div class="form-group">    <%= form.label :name %>    <%= form.text_field :name, id: :restaurant_name, class: "form-control" %>  </div>  ...  <div class="form-group">    <%= form.label :image %>    <%= form.file_field :image, id: :restaurant_image, class: "form-control" %>  </div> 
告诉rails何时取得image。我们来到app/views/restaurants/show.html.erb,在餐厅资料前面加上程式码:
<p id="notice"><%= notice %></p><%= image_tag @restaurant.image_url if @restaurant.image_url.present? %><p>...<p>  <strong>Name:</strong>  <%= @restaurant.name %></p>

image_tag:Rails内建的Helper静态辅助方法,可以让我们建构HTML更为容易。参考这里
@restaurant.image_url:显示目前这笔餐厅资料的图片位置。

[新手常见Bug!]检查图片为nil写法:if @restaurant.image_url.present?。可以防止当某位使用者新增一笔餐厅资料、但没有附上图片的时候,show.html.erb这页网页直接当掉给你看...

F. 修改Controllers

最后,我们在Controllers: app/controllers/restaurants.controller.rb加上允许上传至栏位的参数,告诉rails,新的image栏位是安全的。

    def restaurant_params      params.require(:restaurant).permit(:name, :address, :phone, :website, :image)    end

**大功告成 **

观看结果:

http://img2.58codes.com/2024/20111177bgD1sd8o0E.png


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章