A
A
Askhat Bikmetov2014-05-14 12:05:30
ruby
Askhat Bikmetov, 2014-05-14 12:05:30

How to upload multiple files with one request in CarrierWave/Sinatra?

I'm not the first to ask, but I won't be the last either. How to implement multiple file upload in CarrierWave and Sinatra? I have this action:

post '/create' do
  params.delete 'submit'
  d = Dcmnt.new(
    :published   => params[:published],
    :name        => params[:name],
    :description => params[:description],
    :created_at  => Time.now
  )
  d.attachment = params[:attachments]
  d.save
  redirect '/success'
end

Here is such a model:
class Dcmnt
  include Mongoid::Document
  store_in collection: 'dcmnts'
  field :published,   type: Boolean
  field :name,        type: String
  field :description, type: String
  field :created_at,  type: Date
  mount_uploader :attachment, Uploader, type: String
end

With this form:
%form{:method => "post", :action => "/create", :enctype => "multipart/form-data"}
  %input{:type => "checkbox", :name => "published", :value => "true"} Published?
  %input{:name => "name"}
  %textarea{:name => "description", :rows => "5"}
  %div.form-group
    %label Attachments
    %input{:type => "file", :name => "attachments[]"}
    %input{:type => "file", :name => "attachments[]"}
    %input{:type => "file", :name => "attachments[]"}
    %input{:type => "file", :name => "attachments[]"}
    %input{:type => "file", :name => "attachments[]"}

CarrierWave is configured like this:
class Uploader < CarrierWave::Uploader::Base
  storage :file
  def store_dir
    'attachments/' + model.id
  end
end

Looks correct but doesn't work. When trying to upload multiple files, as well as a single file, Pow returns no implicit conversion of nil into String on the line d.attachment = params[:attachments] . By the way, .each and .map called on params[:attachments] don't help.
What to do, tell me?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Arkady Butermanov, 2014-05-18
@askhat

You're a little confused about how Carrierwave works. In the future, to solve such problems, it makes sense to read the source code of the library you use. The mount_uploader :attachment method adds a method to the model

def attachment=(blabla)
...
end

This does not expect blabla to be an array.
If I were you, I would bind your model with a one_to_many relationship like this:
class Dcmnt
  include Mongoid::Document
  ...
  has_many :attachments
  accepts_nested_attributes_for :attachments
end

class Attachment
  include Mongoid::Document
  ...
  belongs_to :dcmnt
  mount_uploader :file, Uploader
end

d = Dcmnt.new(
    :published   => params[:published],
    :name        => params[:name],
    :description => params[:description],
    :created_at  => Time.now
  )
  d.attachment = params[:attachments]

do:
d = Dcmnt.new(
    :published   => params[:published],
    :name        => params[:name],
    :description => params[:description],
    :attachments_attributes => params[:attachments_attributes]
    :created_at  => Time.now
  )

By the way, instead :created_at => Time.nowyou can add to the model include Mongoid::Timestamps::Created
%div.form-group
    %label Attachments
    %input{:type => "file", :name => "attachments_attributes[0][file]"}
    %input{:type => "file", :name => "attachments_attributes[1][file]"}
    %input{:type => "file", :name => "attachments_attributes[2][file]"}

1. For forms, it is still desirable to use helpers
2. The name of your model is too non-obvious. Rubies don't like that.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question