#134 Paperclip
- Download:
- source codeProject Files in Zip (150 KB)
- mp4Full Size H.264 Video (11.5 MB)
- m4vSmaller H.264 Video (7.81 MB)
- webmFull Size VP8 Video (20.3 MB)
- ogvFull Size Theora Video (15.3 MB)
下面图片中的页面是一个电子商务应用程序的产品页面。我们想要给这个产品页面添加一个图片,我们先要修改后台管理系统以便我们在创建或修改一个产品的同时能够上传这个图片。在这一集中我们会展示如何用一个叫“Paperclip”的插件来做这件事情。
Paperclip 这个插件使我们给一个模型(model)添加一个附件变得非常容易。我们将给产品模型(Product
model)添加一个字段(field),用来让每一个产品都能有一张产品图片。
Paperclip 的安装方法和其他插件的安装是一样的。在我们的rails项目目录中我们可以通过Github下载安装:
script/plugin install git://github.com/thoughtbot/paperclip.git
修改模型
到目前为止我们已经成功安装Paperclip插件,可以运行插件的生成器来给产品模型(Product
model)添加附件字段。
script/generate paperclip product photo
这个生成器有两个参数。第一个是模型的名字,在例子中传入的是“Product”,第二个是新添加的附件字段的名字(photo)。这个生成器执行后会生成一个迁移任务(migration):给模型添加了4个新字段。
add_column :products, :photo_file_name, :string add_column :products, :photo_content_type, :string add_column :products, :photo_file_size, :integer add_column :products, :photo_updated_at, :datetime
Paperclip插件生成器添加的4个新字段 。
我们将运行命令:rake db:migrate
来更新数据库中的表products。
下一步 修改模型(model)代码。我们需要使用 has_attached_file
来告诉模型我们用迁移任务创建的附件字段(attachment field)的名字。
class Product < ActiveRecord::Base belongs_to :category has_attached_file :photo end
修改视图
创建和更新产品的表单需要添加一个上传文件的字段。
<% form_for @product, :html => { :multipart => true } do |form| %> <ol class="formList"> <!-- Other fields go here... --> <li> <%= form.label :photo, "Photo" %> <%= form.file_field :photo %> <li> <%= form.submit "Submit" %> </li> </ol> <% end %>
为表单添加了一个 file_field
字段之后,还需要修改form_for
来使表单能够接收文件附件,这是通过添加:multipart => true
给:html
hash参数,这个参宿会给生成的form标签添加enctype="multipart/form-data"
属性。
当然如果我们不去显示图片,那么我们上传图片是没有意义的,因此我们需要对显示产品的视图(show
)进行修改。我们只需要给页面添加一个image_tag
标签。我们的产品模型(Product
model)已经有一个属性,这个属性是一个带有能够生成正确图片路径url
方法的photo
对象。调用代码如下。
<%= image_tag @product.photo.url %>
我们可以编辑一个产品,为之添加一个图片,然后看看结果。
所做的修改生效了,我们的产品现在有一张图片显示了,但图片有点太大了。 当然我可以通过仅仅上传正确尺寸的图片来保证图片大小。如果我们可以在服务器上修改图片的尺寸,那么就能够很好的保证图片的尺寸了。Paperclip插件有方法可以做到。
设置图片尺寸
我们添加到产品模型(Product model)中的方法has_attached_file
有很多参数(options)。其中一个是允许我们给图片定义不同的尺寸的styles
参数。我们只需要定义style参数并指定尺寸就可以为每张图片创建一个缩略图。例如:
has_attached_file :photo, :styles => { :small => "150x150>" }
添加了新的style之后 Paperclip将会给每张图片生成一张适应150×150象素尺寸的缩略图。 尺寸参数结尾的大于号告诉Paperclip要保持图片的纵横比,避免图片拉伸变形。要注意的是你必须在服务器上安装 ImageMagick 来保证生成缩略图功能起作用。
为了让合适的尺寸的图片能够在产品视图(show
)中显示,我们需要修改image_tag
使图片标签的url指向小版本图片。
<%= image_tag @product.photo.url(:small) %>
给url方法传递刚刚设置的style :small参数正确的小图片将被返回。只有当上传的时候才能生成图片,因此为了重新生成图片尺寸我们只能编辑我们的产品重新上传图片文件。只有这样做了, 指定大小的图片才显示在产品页面。
设置 Paperclip 路径
Paperclip默认将附件保存在rails项目的public/system
目录下。
<img alt="Phone_large" src="http://asciicasts.com/system/photos/1/small/phone_large.jpg?1238845838" />
Paperclip 会根据产品的 id 和模型中设置的style来自动创建保存附件的自有目录层次。大多数情况下默认的目录层次是比较合适的,但是如果我们想将图片存储到其他目录,那么我们可以改变默认的存储位置。
只要给方法 has_attached_file 传递两个参数url和path就可以把图片文件保存到其他位置。
has_attached_file :photo, :styles => { :small => "150x150>" }, :url => "/system/:attachment/:id/:style/:basename.:extension", :path => ":rails_root/public/system/:attachment/:id/:style/:basename.:extension"
上面代码中的参数url和path是Paperclip使用的默认值。url指定了相对于public的路径位置,其中有附件字段的名字(attachment)、模型的id和style替换占位符(placeholders)。path参数值中也有相似的替换占位符。如果想要将图片存储到assets目录中,我们只要改变url和path的值。
has_attached_file :photo, :styles => { :small => "150x150>" }, :url => "/assets/products/:id/:style/:basename.:extension", :path => ":rails_root/public/assets/products/:id/:style/:basename.:extension"
现在我们上传的任何图片将会保存到assets目录目录而不是system/photos目录。
验证附件
Paperclip插件的最后一个重要特性是它可以验证我们上传的附件。可以通过给产品模型(Product
model)添加类似下面的校验器:
validates_attachment_presence :photo validates_attachment_size :photo, :less_than => 5.megabytes validates_attachment_content_type :photo, :content_type => ['image/jpeg', 'image/png']
通过上面的这些校验方法检查了:附件是否上传、文件大小小于5m、是否为JPEG或PNG格式。用这种办法验证附件可以和验证其他字段一样。有一点要注意的是:检查的文件类型的时候 Internet Explorer 可能与其他浏览器报告不同的MIME类型:IE会认为JPEG文件是image/pjpeg
而不是image/jpeg
文件。