Reputation: 600
This is quite a common error and I have went through many answers but nothing worked for me. Can you please help, where I am going wrong?
Scenario: I have an item and image table and when user adds an item, he/she must add at least one image. When I save the form after attaching an image it gives an error. The code snippets and error screenshot are attached below:
item.rb
class Item < ApplicationRecord
belongs_to :user, class_name: 'User', foreign_key: :user_id
has_many :images, class_name: 'Image', foreign_key: :item_id, dependent: :destroy
accepts_nested_attributes_for :images, allow_destroy: true
end
image.rb
class Image < ApplicationRecord
belongs_to :item, foreign_key: :item_id, optional: true
has_attached_file :image, styles: { small: '64x64', med: '100x100', large: '200x200' },
default_url: '/images/:id/:filename'
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
end
items_controller.rb
class ItemsController < ApplicationController
def new
@item = Item.new
@item.images.build
#new.html.erb
end
def create
@item = Item.new(item_params.merge(user_id: current_user.id))
if @item.save
redirect_to items_path
else
render :new
end
end
private
def item_params
params.require(:item).permit(:name, :category, :qty, :cost, :description,
:city, :postal_code, :country,
images_attributes: [:id, :item_id, :_destroy, image: []])
end
end
new.html.erb
<div class="container">
<h2> <% if current_user.items.blank? %> Become a seller! <% end %> Add a new item </h2> <br>
<%= form_for @item, url: {action: :create}, html: { multipart: true } do |f| %>
<%= item_error_messages! %>
<div class="form-group">
<%= f.label :name, class:'control-label col-sm-2' %>
<div class="col-sm-10">
<%= f.text_field :name, class: 'form-control', placeholder: 'Enter name' %>
</div>
</div>
<%= f.fields_for :images, @item.images.build do |img| %>
<%= img.file_field :image, multiple: true %>
<% end%>
<br><br>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10" style="margin-bottom: 40px;">
<%= f.submit 'Save', class:'btn btn-default' %>
</div>
</div>
<% end %>
</div>
Error:
What could be the possible issue? Most of the solutions I've read suggest adding multipart: true
in form tag but it is already there.
Thanks
Upvotes: 0
Views: 2526
Reputation: 1172
I think you problem is related with the fact that you are trying to save more than one attached file per model. Apparently, Paperclip don't treat this case very well, so you need to do it by your own hand.
If you want to save multiples files at the same time, you can follow the accept answer in the link below that example how to achieve that:
Just a resume from the link below:
1 - To save multiple files in the above example you, do not need add multiple: true option, it will cause an error when saving.
2 - About params: This will cause an error because the model does not know what to do with an array of images
3 - To save more than one file at the same time, you need to use your own handler
Rails 4 multiple file attachments with Paperclip
Good luck!
#UPDATE
Ideas about to how save multiples file at once:
1 - You will need to have a form with a dynamically input for files. So each input can get the entry for each file. You can achieve that writing your own .js lib or using a gem like "Cocoon". You will be using nested attributes here.
2 - The strong parameter in your controller will be accepting you Item model and an array of files.
3 - You will have to edit your method to save your data. E.g (in your case @item.save won't work because paperclips it's not design to accept an array of files). So, in your Item model you will have to write a method similar to the below:
(pseudo-code)
def save(item_attributes, array_of_files)
@item = Item.new( -- add here only Item attributes --)
@item.save
# Here you are creating a model file for each file you are saving.
# So there will be N file model for 1 item.
for file in array_of_files
@file = File.new( @item.id, file)
@file.save
end
# here you can implement transaction in case a error occurs.
# and shows the error to your client through Item model
# google how to do this (transaction and Active Record class).
end
Upvotes: 1