rails 上传附件

  今天做了个上传附件的功能,记录一下

       用的gem

gem 'carrierwave'
gem 'rmagick', '2.13.2'
gem 'mime-types'

      关于这些gem都是什么作用这里就不做解释了,github中有介绍。执行bundle,期间会出现一些问题,install rmagick的时候会报错,原因貌似版本的问题。我的系统是ubuntu 12.0.4,解决方法

1、sudo apt-get install libmagickwand-dev
2、sudo gem install rmagick

      直接上代码吧,其实上传附件的情景有很多,image、pdf等等,这里我以imag为例。

rails generate uploader Attachment

     有了carrierwave的gem包,创建一个uploader,这个uploader会跟普通的model有所区分。会生成一个attachment_uploader.rb的文件

# encoding: utf-8

class AttachmentUploader < CarrierWave::Uploader::Base

   include CarrierWave::RMagick
   include CarrierWave::MimeTypes
   #默认使用file系统
  storage :file
  #文件保持路径,这里就是用默认的
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
  #定依set_conditent_type的process
  process :set_content_type
  #定义thumb格式的style,可以通过rmagick来将上传的图片进行处理
  version :thumb, :if => :image? do 
    process :resize_to_fit => [50,50]
  end
  #同时定义一中thumb
  version :preview, :if => :image? do 
     process :resize_to_fit => [80,80]
  end
  #为了避免处理一些非image的附件
  def image?(file)
    file.content_type.include? 'image'
  end
end      

   创建一个attachment的model

rails g model attachment

         修改migration

class CreateAttachments < ActiveRecord::Migration
  def change
    create_table :attachments do |t|
      t.string :file_name
      t.string :content_type
      t.string :attachmentable_type
      t.string :file_size
      t.integer :attachmentable_id
      t.string :attachment

      t.timestamps
    end
  end
end

        需要指出的是这里用到了association中的多态方法,考虑到并不值一种model会有attachment,用多态最好了

class Attachment < ActiveRecord::Base
  mount_uploader :attachment, AttachmentUploader
  attr_accessible :attachment, :attachmentable
  #多态 ==>attachmentable表示多种实体
  belongs_to :attachmentable, :polymorphic => true
  validates :attachmentable, :presence => true
  validates :attachment ,:presence => true

  before_save :set_attachment_attributes


  protected
  #设置附件的属性
  def set_attachment_attributes
      if attachment.present?  && attachment_changed?
          self.content_type = attachment.file.content_type
          self.file_size = attachment.file.size 
          self.file_name = attachment.file.original_filename
      end
  end
end

         对应view中的_form.html.erb的局部模板

<!--关键地方设置:html => {:multipart => true } -->
<%= form_for(@base_info, :html => {:multipart => true}) do |f| %>
  <% if @base_info.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@base_info.errors.count, "error") %> prohibited this base_info from being saved:</h2>

      <ul>
      <% @base_info.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>
  <!-- 添加一个<input type="file"> -->
  <div class="field">
    <label>logo</label>
    <%= file_field_tag :attachment %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

  在对应的controller的create的方法中

def create
    @base_info = BaseInfo.new(params[:base_info])

    respond_to do |format|
      if @base_info.save
        Attachment.create(:attachment => params[:attachment],
          :attachmentable => @base_info) if params[:attachment]
        format.html { redirect_to @base_info, notice: 'Base info was successfully created.' }
        format.json { render json: @base_info, status: :created, location: @base_info }
      else
        format.html { render action: "new" }
        format.json { render json: @base_info.errors, status: :unprocessable_entity }
      end
    end
  end

       在显示中就可以得到上传的图片了

<% @base_info.attachments.each do |attachment| %>
      <%= image_tag attachment.attachment.thumb %>
      <%= image_tag attachment.attachment.url %>
      <%= image_tag attachment.attachment.preview %>
  <% end %>

      查看public就可以看到上传的图片,需要说明的是会有3套图片,因为使用了rmagick的gem。

还可以用

posted on 2013-05-07 18:40  小海少  阅读(706)  评论(0编辑  收藏  举报