使用Paperclip Rails 4多个文件附件

我知道Stackoverflow上有几篇post和几个关于这个主题的教程。 然而,他们都没有设法解决我的问题,其中大多数也已过时。

我正在尝试使用Rails 4中的paperclip gem将多个图像添加到项目中。当我尝试上传它时,我确实看到附加在params中的资产。

它们似乎没有添加到project_paramns但是..

希望有人可以帮助我。

这是我的projects_controller

class ProjectsController < ApplicationController before_filter :find_project, only: [:show, :edit, :update, :destroy] def index @projects = Project.all end def show end def new @project = Project.new end def create @project = Project.new(project_params) @project.save redirect_to project_path(@project) end def edit end def update @project.update(project_params) redirect_to project_path(@project) end def destroy @project.destroy redirect_to projects_path end protected def project_params params.require(:project).permit(:name, :description, :asset) end def find_project @project = Project.find(params[:id]) end end 

我的项目模型

 class Project  :destroy validates_associated :assets validates_presence_of :name, :on => :create, :update => "can't be blank" validates_presence_of :description, :on => :create, :update => "can't be blank" accepts_nested_attributes_for :assets end 

我的资产模型

 class Asset  { :thumb=> "100x100#", :small => "150x150>", :medium => "300x300>", :large => "400x400>" } validates_attachment :image, content_type: { content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif"] } end 

我的forms部分(抱歉,它在HAML)

 = simple_form_for @project do |f| %ul - @project.errors.full_messages.each do |error| %li= error .row .small-1.columns = f.label :name, :class => "left inline" .small-11.columns = f.input_field :name .row .small-1.columns = f.label :description, :class => "left inline" .small-11.columns = f.input_field :description, as: :text .row = f.simple_fields_for :asset do |a| .small-1.columns = a.label :image, :class => "left inline" .small-11.columns = file_field_tag :image, multiple: true, .row .small-9.small-offset-1.columns = f.submit nil ,:class => "button [radius round]" 

请求参数

 {"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"4iK1kUNvKvoJVOKoivz/pcLAe6LY0cUJikQioxa8BIs=", "project"=>{"name"=>"adf", "description"=>"adf", "asset"=>{"image"=>[#<ActionDispatch::Http::UploadedFile:0x007fb808357d80 @tempfile=#, @original_filename="enabling-gzip-compression.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"project[asset][image][]\"; filename=\"enabling-gzip-compression.jpg\"\r\nContent-Type: image/jpeg\r\n">, #<ActionDispatch::Http::UploadedFile:0x007fb808357d58 @tempfile=#, @original_filename="minimize_http_requests.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"project[asset][image][]\"; filename=\"minimize_http_requests.png\"\r\nContent-Type: image/png\r\n">]}}, "commit"=>"Update Project", "action"=>"update", "controller"=>"projects", "id"=>"11"} 

现在我的终端出现了错误:

 Unpermitted parameters: asset 

编辑:

@ pavan和@kiri thorat的答案的组合帮助我在project_params中显示了一些内容,它现在提供的输出是:

 {"name"=>"Test", "description"=>"Test", "assets_attributes"=>{"0"=>{}}} 

关于这里发生了什么的任何线索?

在@ kirithorat的最新更新之后,事情的参数方面似乎很好。

 {"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"4iK1kUNvKvoJVOKoivz/pcLAe6LY0cUJikQioxa8BIs=", "project"=>{"name"=>"Test", "description"=>"Test", "assets_attributes"=>{"0"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007fcd383c9a08 @tempfile=#, @original_filename="enabling-gzip-compression.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"project[assets_attributes][0][image]\"; filename=\"enabling-gzip-compression.jpg\"\r\nContent-Type: image/jpeg\r\n">}}}, "commit"=>"Update Project", "action"=>"update", "controller"=>"projects", "id"=>"13"} 

但资产仍然没有得到保存。

实施@ Valikiliy的建议后更新

 {"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"4iK1kUNvKvoJVOKoivz/pcLAe6LY0cUJikQioxa8BIs=", "project"=>{"name"=>"Test", "description"=>"Test", "image"=>#<ActionDispatch::Http::UploadedFile:0x007fcd3a08d0b8 @tempfile=#, @original_filename="minimize_http_requests.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"project[image]\"; filename=\"minimize_http_requests.png\"\r\nContent-Type: image/png\r\n">}, "commit"=>"Update Project", "action"=>"update", "controller"=>"projects", "id"=>"16"} 

更新:根据要求添加新的表单代码

 = simple_form_for(@project, :html => { :multipart => true }) do |f| %ul - @project.errors.full_messages.each do |error| %li= error .row .small-1.columns = f.label :name, :class => "left inline" .small-11.columns = f.text_field :name .row .small-1.columns = f.label :description, :class => "left inline" .small-11.columns = f.text_area :description .row = f.simple_fields_for :assets do |a| .small-1.columns = a.label :image, :class => "left inline" .small-11.columns - if a.object.new_record? = a.input :image, as: :file - else = image_tag a.object.image.url(:thumb) = a.input_field '_destroy', as: :boolean .row .small-9.small-offset-1.columns = f.submit nil ,:class => "button [radius round]" 

更新

 def project_params params.require(:project).permit(:name, :description, images: [], assets_attributes: [:_destroy, :id, :image]) end def find_project @project = Project.find(params[:id]) @project.assets.build if %w[new edit].include?(action_name) end 

更新:添加了型号代码

 class Project  :destroy validates_presence_of :name, :on => :create, :update => "can't be blank" validates_presence_of :description, :on => :create, :update => "can't be blank" accepts_nested_attributes_for :assets, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true end 

要在上面的示例中保存多个文件,不需要添加multiple:true选项,保存时会导致错误, 一个文件 – 一个记录资产表。

要解决此问题,您可以添加多个文件字段,如下所示:add into controller:

 def new @project = Project.new 3.times{ @project.assets.build } end def edit 3.times{ @project.assets.build } end 

对于列表

 .permit(..., assets_attributes: [ :_destroy, :id, :image ]) 

并在这样看来:

 = f.simple_fields_for :assets do |a| .small-1.columns = a.label :image, :class => "left inline" - if a.object.new_record? .small-11.columns = a.file_field :image - else .small-11.columns = image_tag a.object.image.url(:thumb) = a.input_field '_destroy', as: :boolean 

如果您尝试发送多个这样的图像:

 # view a.file_field :image, multiple: true # controller .permit(..., assets_attributes: [ :_destroy, :id, image: [] ]) 

这将导致错误,因为Asset模型不知道如何处理图像数组。

要同时保存多个文件,您需要使用自己的处理程序,例如:

model:添加images=方法

 def images=(files = []) assets.create(image: f) end 

controller:移动images: []在assets_attributes之外

 .permit(..., images: [], assets_attributes: [ :_destroy, :id ]) 

view:删除fields_for和嵌套属性

  .row .small-1.columns =f.file_field :images, multiple: true .row = f.simple_fields_for :assets do |a| .small-1.columns = a.label :image, :class => "left inline" .... 

您在ProjectAsset模型之间拥有1-M关系,即

项目有很多资产

所以,在你的forms中,部分simple_fields_for应该是这样的

 = f.simple_fields_for :assets do |a| 

注意 复数 asset和非单数 asset

在您当前的代码中,您将simple_fields_forsingular asset一起使用,这就是为什么您的params生成错误并且您在params哈希中接收asset键而不是接收assets_attributes键,这会导致警告为Unpermitted parameters: asset

一旦您更正了表单部分,您将在表单提交时收到params哈希中的正确密钥。 现在,正如@Pavan指出我看到的下一个问题是你没有在控制器中正确地允许assets_attributes

您需要更新project_params方法,如下所示:

 def project_params params.require(:project).permit(:name, :description, assets_attributes: [:image]) end 

注意 assets_attributesassets复数

UPDATE

您需要在ProjectsController newedit操作中添加@project.assets.build ,以便在new视图和edit视图中查看资源的字段。 另外,我建议在project_params assets_attributes的允许属性列表中添加:id ,如下所示:

  params.require(:project).permit(:name, :description, assets_attributes: [:id, :image]) 

我看到的更多问题是form partial

  1. 在上传文件时,您应在表单中指定:html => {:multipart => true}

    更改

     = simple_form_for @project do |f| 

     = simple_form_for @project, :html => {:multipart => true} do |f| 
  2. 项目has_many资产 ,每个asset记录只有一个image ,所以删除multiple: true 。 另外,在使用simple_form ,建议使用simple_form helper方法上传文件。

    更改

     = file_field_tag :image, multiple: true, 

     = a.input :image, as: :file 

你的project_params应该是这样的

 def project_params params.require(:project).permit(:name, :description, assets_attributes: [:image]) end 

而且,为什么你使用protected ? 我想你应该使用private