Reputation: 521
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
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