Uploading multiple images - ruby-on-rails

I have problem with uploading multiple images using dropzone.js
I'm getting this error:
Paperclip::AdapterRegistry::NoHandlerError (No handler found for "0"):
This is how look parameters when I'm submitting form with dropzone
Processing by CarsController#create as JSON
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ND6DrphXI6sYZ+IGZd8HllyGR/74PbmBsyRCHqsRZO2BpgVNLCqJpkokW57pQ5lVaPm9AVzredrHNg9Lc8y1eQ==", "car"=>{„brand”=>"Audi ", "model"=>"A6"}, "null"=>"", "commit"=>"Create Car", "images"=>{"0"=>#<ActionDispatch::Http::UploadedFile:0x007fc42bcc4308 #tempfile=#<Tempfile:/var/folders/f5/x2w5mbln30q9q70f1mqxy3hc0000gn/T/RackMultipart20170926-645-1hajljx.png>, #original_filename=„car.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"images[0]\"; filename=\”car.png\"\r\nContent-Type: image/png\r\n">}}
And without dropzone
Processing by CarsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Pwp4IlmBXuaKN8GZ5TGckKpxRlpteKtsGqgVPE/rK3yKkv7B7fz063h0eAFprQJTmxe8pcm+azduullplzbz7A==", "car"=>{„brand”=>"Audi ", "model"=>"A6"}, "images"=>[#<ActionDispatch::Http::UploadedFile:0x007fc428b41b50 #tempfile=#<Tempfile:/var/folders/f5/x2w5mbln30q9q70f1mqxy3hc0000gn/T/RackMultipart20170925-645-sxrzzm.png>, #original_filename=„car.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"images[]\"; filename=\”car.png\"\r\nContent-Type: image/png\r\n">], "commit"=>"Create Car"}
Without dropzone everything works fine.
This is my form
<%= form_with(model: car, local: true, :html => {:multipart => true, :class => "dropzone", :id => 'myAwesomeDropzone'}) do |form| %>
<%= file_field_tag "images[]", multiple: true %>
<%= form.submit :id => „submit” %>
<% end %>
Dropzone settings
Dropzone.options.myAwesomeDropzone = {
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
paramName: "images",
maxFiles: 100,
init: function() {
var myDropzone = this;
this.element.querySelector(„#submit”).addEventListener("click", function(e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
}
}
Car Controller
def create
#car = Car.new(car_params)
respond_to do |format|
if #car.save
if params[:images]
params[:images].each { |image|
#car.pictures.create(image: image)
}
end
format.html { redirect_to #car, notice: 'Car was successfully created.' }
format.json { render :show, status: :created, location: #car }
else
format.html { render :new }
format.json { render json: #car.errors, status: :unprocessable_entity }
end
end
end
Picture model
class Picture < ApplicationRecord
belongs_to :car
has_attached_file :image, :processors => [:watermark],
:styles => {
:thumb => '150x150>',
:original => { :geometry => '1920x1080#', :watermark_path => "#{Rails.root}/public/images/logo.png" }
},
:url => '/assets/attachment/:id/:style/:basename.:extension',
:path => ':rails_root/public/assets/attachment/:id/:style/:basename.:extension',
:default_url => "/images/:style/mising.png"
validates_attachment :image,
content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
end
I haven't any idea how to solve this problem, I'm counting on yours help

It seems that since you use dropzone the parameters changed from being an array of files to a hash, where the keys are files. A simple trasnformation may solve your problem:
params[:images].each do |_i, image|
#car.pictures.create(image: image)
end
I've just changed the each loop to iterate over a hash instead of an array. This could also work:
params[:images].keys.each do |image|
#car.pictures.create(image: image)
end

Related

Response for Form with custom action using ajax

I want to upload the user avatar (carrierwave) using a custom action like this:
= form_for user, url: update_user_avatar_path(id: user.id), :html => {:class => "up-cl-ava-form", data: {type: :json}, novalidate: true, method: :put}, remote: true do |f|
= f.file_field :avatar_picture
= f.submit "Update", remote: true
In UsersController
def update_user_avatar
#user = User.find(params[:id]) || current_user
respond_to do |format|
if #user.update_attributes!(avatar_picture: params[:user][:avatar_picture])
format.json { render json: {}, status: :ok}
else
format.json { render json: {}, status: :unprocessable_entity}
end
end
end
Params in #update_user_avatar
{"utf8"=>"✓", "_method"=>"put",
"authenticity_token"=>"BPGeN5mpRCYwIco1YSsBx6IT7MfIBOdSlwS9Y5WJZeU=",
"user"=> {"avatar_picture"=>
#>}, "commit"=>"Update", "id"=>"30", "action"=>"update_user_avatar",
"controller"=>"users"}
Request
.... "CONTENT_TYPE"=>"multipart/form-data;
boundary=----WebKitFormBoundaryvz51HFYrromiuTS7" ....
In my JS
$(document).ready(function(){
$(".up-cl-ava-form").on("ajax:success", function(){
alert("success")
});
});
The problem here is that the image is uploaded correctly but the site redirects to lvh.me:3000/update_user_avatar?id=30 (blank page), instead staying in the same view.
This will be solve by adding remotipart gem
https://github.com/JangoSteve/remotipart

Ruby on Rails paperclip multiple upload with nested attributes

I was wondering if someone can help me with file uploading!
I'm trying to upload multiple images using paperclip and having nested attributes.
models
class Trip < ActiveRecord::Base
has_many :trip_images, :dependent => :destroy
end
class TripImage < ActiveRecord::Base
belongs_to :trip
has_attached_file :photo, :styles => { :large => "800x800>", :medium => "500x500>", :thumb => "150x150#" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :photo, content_type: /\Aimage\/.*\Z/
end
controller
def create
#trip = Trip.new(trip_params)
respond_to do |format|
if #trip.save
format.html { redirect_to #trip, notice: 'Trip was successfully created.' }
format.json { render :show, status: :created, location: #trip }
else
format.html { render :new }
format.json { render json: #trip.errors, status: :unprocessable_entity }
end
end
end
def trip_params
params.require(:trip).permit(
:user_id,
trip_images_attributes: [:id, :photo])
end
view
<%= simple_form_for #trip, html: { multipart: true } do |f| %>
<%= f.simple_fields_for :trip_images do |p| %>
<%= p.file_field :photo, as: :file, multiple: true %>
<% end%>
<%= f.button :submit %>
<% end %>
How do I save multiple images in my trip image database? When I submit the form, nothing gets saved into the database.
Add :trip_id to trip_images_attributes:
def trip_params
params.require(:trip).permit(
:user_id,
trip_images_attributes: [:trip_id, :id, :photo]) # :_destroy
end
Also you can add :_destroy if you plan to be able to remove photos.
What you also missed is to add accepts_nested_attributes_for :trip_images to Trip model.
Change your form to something like this:
= f.simple_fields_for :trip_images do |tp|
= render 'trip_photos_fields', f: photo
.links
%br= link_to_add_association 'Add another photo', f
And _trip_photos_fields.html.haml partial:
- unless f.object.new_record?
%br= link_to_remove_association "Delete photo", f
= link_to image_tag(f.object.photo.url(:medium)), f.object.photo.url, target: '_blank'
- if f.object.new_record?
= f.file_field :photo, as: :file

Paperclip Issue - can't update and create

CONTROLLER
CREATE
def create
set_cache_buster
#court_agency = CourtAgency.new(court_agency_params)
#court_agency.created_by = current_user
#court_agency.updated_by = current_user
binding.pry
respond_to do |format|
if #court_agency.save
flash[:success] = 'Court was successfully created.'
format.html do
redirect_to court_agencies_path
end
format.js { render :js => "window.location = '#{court_agencies_path}'" }
else
format.json { render json: #court_agency.errors, status: :unprocessable_entity }
end
end
end
UPDATE
def update
set_cache_buster
#court_agency = CourtAgency.find(params[:id])
#court_agency.updated_by = current_user
respond_to do |format|
if #court_agency.update_attributes(court_agency_params)
flash[:success] = 'Court was successfully updated.'
format.html do
redirect_to court_agencies_path
end
format.js { render :js => "window.location = '#{court_agencies_path}'" }
else
format.json { render json: #court_agency.errors, status: :unprocessable_entity }
end
end
end
STRONG PARAMETER
def court_agency_params
params.require(:court_agency).permit(
:type,
:subtype,
:division,
:associate_justice,
:presiding_justice,
:map,
:landmark_image,
]
) if params[:court_agency]
end
MY VIEW
= form_for(#court_agency, remote: true, html: { :multipart => true, class: 'form-horizontal ajax-form', style: 'margin-bottom: 0;', 'data-model-name' => 'court_agency'}) do |f|
.form-group
= f.label :landmark_image, 'Landmark', class: 'control-label'
%br/
= f.file_field :landmark_image, class: 'btn btn-warning'
- if #court_agency.map.present?
= image_tag #court_agency.map.url(:small), class: 'img-responsive img-thumbnail'
.form-group
= f.label :map, 'Map', class: 'control-label'
%br/
= f.file_field :map, class: 'btn btn-warning'
- if #court_agency.map.present?
= image_tag #court_agency.map.url(:small), class: 'img-responsive img-thumbnail'
MODEL
#Paperclip
has_attached_file :map,
:styles => { :large => "900x900>", :medium => "300x300>", :thumb => "196x196>", :small => '50x50>' },
:default_url => ActionController::Base.helpers.asset_path('missing.png'),
:url => "/assets/court_agencies/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/court_agencies/:id/:style/:basename.:extension"
validates_attachment_content_type :map, :content_type => /\Aimage\/.*\Z/
has_attached_file :landmark_image,
:styles => { :large => "900x900>", :medium => "300x300>", :thumb => "196x196>", :small => '50x50>' },
:default_url => ActionController::Base.helpers.asset_path('missing.png'),
:url => "/assets/court_agencies/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/court_agencies/:id/:style/:basename.:extension"
validates_attachment_content_type :landmark_image, :content_type => /\Aimage\/.*\Z/
Ok here's the problem:
When I create without file upload, it works. But when I attach file, params not working and it leaves blank. So when I binding.pry:
[1] pry(#<CourtAgenciesController>)> params
=> {"action"=>"create", "controller"=>"court_agencies"}
Params is missing.
When I update without file upload, it works. But when I attach file, the error is:
Started POST "/court_agencies/53" for 127.0.0.1 at 2015-04-08 16:03:21 +0800
ActionController::RoutingError (No route matches [POST] "/court_agencies/53"):
or just like
Routing Error
No route matches [POST] "/court_agencies/53"
on browser.
I have remotipart installed.
Also Paperclip.
Please help. Need it badly.
UPDATE:
ROUTES:
#COURT AGENCY
resources :court_agencies do
member do
get 'list'
put 'update_uin'
end
collection do
get 'get_court_agency_list'
get 'court_agency_list'
get 'add'
get 'get_uin'
end
end
This issue is about remote: true. How is it possible to create/update submitting via ajax with file upload?
do you have defined attr_accessible in your model...i didnt see that in your model
attr_accessible: :type,:subtype,:division,:associate_justice,:presiding_justice,:map,:landmark_image,

Rails 4: Multiple image upload using paperclip

I'm looking to upload multiple images to my 'locations' model. I've called the images model 'assets'. One location has multiple assets. I'm also using paperclip to handle the uploads and nested_form to allow selecting multiple assets.
Weirdly, the locations hash looks to be passing the variables correctly, but they don't appear to be being picked up by the assets model. Any help would be great!
Location model
class Location < ActiveRecord::Base
has_many :location_post
has_many :posts, :through => :location_post
has_many :assets, dependent: :destroy
attr_accessor :asset, :assets_attributes
accepts_nested_attributes_for :assets, :allow_destroy => true
end
Asset model
class Asset < ActiveRecord::Base
belongs_to :location
has_attached_file :asset,
:styles => {
:blurred => "600x300^",:large => "600x600>", :medium => "250x250^" , :thumb => "100x100^"},
#:source_file_options => {:all => '-rotate "-90>"'},
:convert_options => {
:all => '-auto-orient', :blurred => "-blur 0x6 +repage -resize 600x300^"
},
:storage => :s3,
:s3_credentials => "#{Rails.root}/config/s3.yml",
:bucket => "[bucketname]",
:path => "/:style/:id/:filename"
validates_attachment_content_type :asset, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
end
Locations Controller
class LocationsController < ApplicationController
...
def new
#location = Location.new
#location.assets.build
#georesult = Geocoder.search(params[:query])
end
def create
#location = Location.find_or_create_by(name: location_params[:name])
respond_to do |format|
if #location.save
format.html { redirect_to #location, notice: ' <borat voice> Great success! </borat voice>' }
format.json { render :show, status: :created, location: #location }
else
format.html { render :new }
format.json { render json: #location.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /locations/1
# PATCH/PUT /locations/1.json
def update
respond_to do |format|
if #location.update(location_params)
format.html { redirect_to #location, notice: 'Location was successfully updated.' }
format.json { render :show, status: :ok, location: #location }
else
format.html { render :edit }
format.json { render json: #location.errors, status: :unprocessable_entity }
end
end
end
...
private
# Use callbacks to share common setup or constraints between actions.
def location_params
params[:location].permit(:name, :notes, :longitude, :country, :latitude, :query, assets_attributes: [ :asset, :asset_content_type, :asset_file_name, :tempfile, :asset_file_size, :asset_updated_at, :_destroy])
end
end
Form View
<%= nested_form_for(#location, :html=> {:multipart => true}) do |f| %>
...
<%= f.fields_for :assets do |a| %>
<%= a.file_field :asset %>
<%= a.link_to_remove "Remove this image" %>
<% end %>
<%= f.link_to_add "Add an image", :assets %>
...
<%= f.submit "Submit", :class => "btn btn-success submit_location" %>
<% end %>
Log output
Processing by LocationsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"n4spoLjq4B3sZSJjqsGFRVjkseOwGgvquAHATBRG1Nk=", "location"=>{"name"=>"York", "notes"=>"", "lat
itude"=>"53.96230079999999", "longitude"=>"-1.0818844", "country"=>"", "assets_attributes"=>{"0"=>{"asset"=>#<ActionDispatch::Http::UploadedFile
:0x007ff739b7bb68 #tempfile=#<Tempfile:/var/folders/sc/gps8hkgj7yg31j81gpnfg9h00000gn/T/RackMultipart20140706-43312-kdpghs>, #original_filename=
"78509.max1024.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"location[assets_attributes][0][asset]\"; filen
ame=\"78509.max1024.jpg\"\r\nContent-Type: image/jpeg\r\n">, "_destroy"=>"false"}}}, "commit"=>"Submit", "id"=>"240"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Location Load (0.4ms) SELECT "locations".* FROM "locations" WHERE "locations"."id" = $1 LIMIT 1 [["id", 240]]
(0.2ms) BEGIN
(0.3ms) COMMIT
Redirected to http://localhost:3000/locations/240
Completed 302 Found in 9ms (ActiveRecord: 1.6ms)
I see couple of problems in your code:
First thing, you need to remove the following line from Location model:
attr_accessor :asset, :assets_attributes
as its making asset and asset_attributes as virtual attributes which is why they are not saved in database. Also, you don't need asset attribute in Location model as its been taken care by Asset model.
Then, update the location_params as suggested by #Pavan:
def location_params
## Use `require` method
params.require(:location).permit(:name, :notes, :longitude, :country, :latitude, :query, assets_attributes: [ :asset, :asset_content_type, :asset_file_name, :tempfile, :asset_file_size, :asset_updated_at, :_destroy])
end
Next, update the create action as below to ensure Locations are unique by name:
def create
#location = Location.find_by(name: location_params[:name])
unless #location
#location = Location.new(location_params)
end
respond_to do |format|
if #location.save
format.html { redirect_to #location, notice: ' <borat voice> Great success! </borat voice>' }
format.json { render :show, status: :created, location: #location }
else
format.html { render :new }
format.json { render json: #location.errors, status: :unprocessable_entity }
end
end
end
try using <%= a.file_field :asset, :multiple=>"true",:name=>"location[assets][asset][]"%> for handling multiple uploads.
Hope it helps

mutiple upload with rails and paperclip

I am following this tutorial here to use multiple uploads with paperclip.
However when I add the files I get the flash notice confirming the gallery was added succesfully but there are no images uploaded. I am sure its the implementation in my controller.
gallery_controller.rb
def update
#gallery = Gallery.friendly.find params[:id]
respond_to do |format|
if #gallery.save
if params[:exhibition_images_attributes]
params[:exhibition_images_attributes].each { |image|
#gallery.exhibition_images.create(image: image)
}
end
format.html { redirect_to #gallery, notice: 'Gallery was successfully updated.' }
format.json { render :show, status: :ok, location: #gallery }
else
format.html { render :edit }
format.json { render json: #gallery.errors, status: :unprocessable_entity }
end
end
end
def edit
#gallery = Gallery.friendly.find params[:id]
#image = #gallery.exhibition_images.new
end
private
def gallery_params
params.require(:gallery).permit(:title, exhibition_images_attributes: [:image])
end
upload form
<%= bootstrap_form_for(#gallery, :html => {:multipart => true}, layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10") do |f| %>
<%= f.text_field :title %>
<%= f.fields_for :exhibition_images do |f| %>
<%= f.file_field "image[]", type: :file, multiple: true %>
<% end %>
<%= f.submit "Create/Update", class: "btn btn-primary" %>
<% end %>
gallery.rb
class Gallery < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
belongs_to :guide
has_many :exhibition_images, :autosave => true
accepts_nested_attributes_for :exhibition_images
end
exhibition_image.rb
class ExhibitionImage < ActiveRecord::Base
belongs_to :gallery, :autosave => true
has_attached_file :image, styles: { small: "100x100", guide: "500x500" }
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
end

Resources