camillavk
camillavk

Reputation: 521

Uploading multiple images with paperclip?

I've looked at all the other questions on SO that look similar but I can't find an answer that will help me.

I'm working on upgrading an app that was written a while ago and am struggling to get the image upload section of it working. The relevant bits of code are as follows:

photos_controller.rb:

def create
    images = params[:an_image]
    if !images.nil?
      photos = []

      images.each do |image|
        photo = @trip.photos.build(:user => current_user, :trip => @trip, :image => image)
        if photo.save
          p 'saving ok'
          photos << photo
        else
          p 'ERROR saving'
        end


      end
      add_news('created_multiple', photos.first, {:photo_ids => photos.collect(&:id)})

      flash[:notice] = "Your photos were updated successfully!"
      redirect_to @trip
    else
      @photo.user = current_user
      @photo.trip = @trip
      if @photo.update_attributes(params[:photo]) || params[:photo][:an_image]
        add_news('created', @photo)
        redirect_to trip_photos_url(@photo.trip)
      else
        render :edit
      end
    end
  end

photo.rb:

def an_image=(file)
    self.trip.photos.create(:image => file)
  end

  attr_accessor :an_image

  # Photo image
  if Rails.env.test?
    has_attached_file :image, :path => "/tmp/:attachment-:id-:style.:extension"
  else
    has_attached_file :image,
                      # 200 x 160 for news
                      :styles => {
                          :list => "270x200>",
                          :feed_item => "75x60>",
                          :map => "30x30#",
                          :homepage => "160x110#",
                          :normal => "300x500",
                          :tiny => "20x20#"
                      },
                      :processors => [:auto_orient, :thumbnail],
                      :storage => :s3,
                      :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
                      :path => ":attachment/:id/:style.:extension",
                      :bucket => "saild-production",
                      :convert_options => {:map => '-bordercolor white -compose over -border 2'}
  end

and photos/new.html.erb:

<div id="content-four">
  <h1>Upload photos to <%= @trip.name %></h1>
  <%= form_tag trip_photos_path(@trip), :multipart => true %>
  <form id="post-photo" action="#">
    <fieldset class="multiple-uploads">
      <a href="#none" class="duplicate" rel=".file-upload">Add more files</a><br>
      <%= file_field_tag :an_image, :class => 'file-upload' %>
      <script type="text/javascript">
          $('.duplicate').click(function() {
              $('.file-upload:first').clone().appendTo($('.multiple-uploads'))
          })
      </script>
    </fieldset>
    <fieldset>
      <input type="submit" class="submit button" value="Publish"/>
    </fieldset>
  </form>
</div>

But when I try to upload a file I keep getting this error:

NoMethodError (undefined method `each' for #<ActionDispatch::Http::UploadedFile:0x007f971263b860>):
  app/controllers/photos_controller.rb:33:in `create'
  actionpack (3.0.7) lib/action_controller/metal/implicit_render.rb:5:in `send_action'
  actionpack (3.0.7) lib/abstract_controller/base.rb:150:in `process_action'
  actionpack (3.0.7) lib/action_controller/metal/rendering.rb:11:in `process_action'
  actionpack (3.0.7) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
  activesupport (3.0.7) lib/active_support/callbacks.rb:461:in `_run__1507672816926971504__process_action__674209566928286804__callbacks'
  activesupport (3.0.7) lib/active_support/callbacks.rb:410:in `_run_process_action_callbacks'
  activesupport (3.0.7) lib/active_support/callbacks.rb:94:in `run_callbacks'
  actionpack (3.0.7) lib/abstract_controller/callbacks.rb:17:in `process_action'
  actionpack (3.0.7) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
  activesupport (3.0.7) lib/active_support/notifications.rb:52:in `block in instrument'
  activesupport (3.0.7) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
  activesupport (3.0.7) lib/active_support/notifications.rb:52:in `instrument'
  actionpack (3.0.7) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
  actionpack (3.0.7) lib/action_controller/metal/rescue.rb:17:in `process_action'
  actionpack (3.0.7) lib/abstract_controller/base.rb:119:in `process'
  actionpack (3.0.7) lib/abstract_controller/rendering.rb:41:in `process'
  actionpack (3.0.7) lib/action_controller/metal.rb:138:in `dispatch'
  actionpack (3.0.7) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
  actionpack (3.0.7) lib/action_controller/metal.rb:178:in `block in action'
  actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:62:in `call'
  actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:62:in `dispatch'
  actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:27:in `call'
  rack-mount (0.6.14) lib/rack/mount/route_set.rb:148:in `block in call'
  rack-mount (0.6.14) lib/rack/mount/code_generation.rb:93:in `block in recognize'
  rack-mount (0.6.14) lib/rack/mount/code_generation.rb:75:in `optimized_each'
  rack-mount (0.6.14) lib/rack/mount/code_generation.rb:92:in `recognize'
  rack-mount (0.6.14) lib/rack/mount/route_set.rb:139:in `call'
  actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:493:in `call'
  hoptoad_notifier (2.4.11) lib/hoptoad_notifier/rack.rb:27:in `call'
  sass (3.4.12) lib/sass/plugin/rack.rb:54:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/head.rb:14:in `call'
  rack (1.2.8) lib/rack/methodoverride.rb:24:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/flash.rb:182:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/session/abstract_store.rb:149:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/cookies.rb:302:in `call'
  activerecord (3.0.7) lib/active_record/query_cache.rb:32:in `block in call'
  activerecord (3.0.7) lib/active_record/connection_adapters/abstract/query_cache.rb:28:in `cache'
  activerecord (3.0.7) lib/active_record/query_cache.rb:12:in `cache'
  activerecord (3.0.7) lib/active_record/query_cache.rb:31:in `call'
  activerecord (3.0.7) lib/active_record/connection_adapters/abstract/connection_pool.rb:354:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/callbacks.rb:46:in `block in call'
  activesupport (3.0.7) lib/active_support/callbacks.rb:416:in `_run_call_callbacks'
  actionpack (3.0.7) lib/action_dispatch/middleware/callbacks.rb:44:in `call'
  rack (1.2.8) lib/rack/sendfile.rb:106:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/remote_ip.rb:48:in `call'
  airbrake (4.1.0) lib/airbrake/rails/middleware.rb:13:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/show_exceptions.rb:47:in `call'
  railties (3.0.7) lib/rails/rack/logger.rb:13:in `call'
  rack (1.2.8) lib/rack/runtime.rb:17:in `call'
  activesupport (3.0.7) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
  rack (1.2.8) lib/rack/lock.rb:13:in `block in call'
  <internal:prelude>:10:in `synchronize'
  rack (1.2.8) lib/rack/lock.rb:13:in `call'
  actionpack (3.0.7) lib/action_dispatch/middleware/static.rb:30:in `call'
  airbrake (4.1.0) lib/airbrake/user_informer.rb:16:in `_call'
  airbrake (4.1.0) lib/airbrake/user_informer.rb:12:in `call'
  hoptoad_notifier (2.4.11) lib/hoptoad_notifier/user_informer.rb:12:in `call'
  railties (3.0.7) lib/rails/application.rb:168:in `call'
  railties (3.0.7) lib/rails/application.rb:77:in `method_missing'
  railties (3.0.7) lib/rails/rack/log_tailer.rb:14:in `call'
  rack (1.2.8) lib/rack/content_length.rb:13:in `call'
  rack (1.2.8) lib/rack/handler/webrick.rb:52:in `service'
  /Users/camillavk/.rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'
  /Users/camillavk/.rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
  /Users/camillavk/.rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'

What I think the code is trying to do is create an array of the images that are uploaded and then .build(which I've never come across -> I assume it is like .create?) with them individually, but it doesn't seem to want to put the uploaded files into an array...

Does anyone know how I can fix this?

(I'm running Rails 3.0.7 and Ruby 1.9.3)

Upvotes: 0

Views: 70

Answers (1)

Max Williams
Max Williams

Reputation: 32933

Your problem is that params[:an_image] is a single object, and you call .each on it as if it was an array.

I've not tried this with file data before, but try changing the name attribute of the file_field_tag to have square brackets at the end, like

file_field_tag "an_image[]"

When you have [] at the end of the name attribute, then the values from all inputs with the same name attribute will be collected together into an array. Might be as simple as that...on the other hand, there might be something about how the multipart data is structured which prevents this.

Another tip, if you have to deal with a variable that might be an array or a single object, is to wrap it in an array, and then call flatten on it. eg

#turns foos into an array, whether it is a single object or an array already
foos = [foos].flatten

Now you can do foos.each, safe in the knowledge that it will always be an array.

Also - tail your development.log file when your form submits and you can see what's in params, and compare it to what your code is expecting.

Upvotes: 1

Related Questions