Paperclip, multiple attachments and validation
Does anybody have a Rails 3 example of multiple attachments working with validation on a multipart form? I've been trying to get this working forever (and have found every blog post and message I开发者_如何学编程 could, but none cover this situation, and the docs don't help at all).
The first problem is that most examples use 'new_record?' in the view template, but this always returns true in a new/create sequence when validation fails because no model instances have been saved (so no 'id' value). So if you start with 5 model instances/file inputs and upload one file, you now have 6 file inputs presented when you re-render the new view, and the 'unless' clause fails for the same reason and no thumbnails are presented.
I want to preserve the link to the uploaded file (and I know this is possible--they're living in a temp directory) while presenting validation errors to the user for other required fields.
Somebody somewhere must have this working with Paperclip. ;)
The way I'm using:
I have properties that has many photos (10 in case). Going to the code whe have:
In properties controller:
def new
@search = Property.search(params[:search])
@property = Property.new
10.times { @property.photos.build }
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @property }
end
end
# GET /properties/1/edit
def edit
@search = Property.search(params[:search])
@property = Property.find(params[:id])
# Se o usuário atual for dono da propriedade
if current_user.id == @property.user_id
@photos = Photo.where("property_id = ?", @property.id)
@N = @photos.count
@N = 10-@N
@N.times { @property.photos.build }
else
render :action => "show"
end
end
10.times "render" 10 times the photo field in view. When in edit form, just apper photo fields lefting. For exemple: At 1st time I uploaded 3 photos, then if I want to upload more, just 7 fields appear.
In property model I have:
class Property < ActiveRecord::Base
attr_accessible :photos_attributes, :logradouro, :complemento, :wc, :negocio, :cep, :vagas, :valor,
:quartos, :uf, :area, :bairro, :suites, :salas, :numero, :cidade, :descricao,
:status, :tipoImovel
has_many :photos
accepts_nested_attributes_for :photos, :allow_destroy => true
end
This allow photos to be uploaded.
Photo model:
class Photo < ActiveRecord::Base
belongs_to :property
has_attached_file :photo, :styles => { :small => "100x100>", :medium => "530>x530", :large => "800x800>" }
validates_attachment_presence :photo
validates_attachment_size :photo, :less_than => 500.kilobytes
end
In my form partial:
<div id="new_up">
<%= f.fields_for :photos do |p| %>
<% if p.object.new_record? %>
<p><%= p.file_field :photo %>
<%= p.radio_button :miniatura, true -%>
</p>
<% end %>
<% end %>
</div>
<div id="old_up">
<h4>Imagens Atuais</h4>
<% f.fields_for :photos do |p| %>
<% unless p.object.new_record? %>
<div style="float: left;">
<%= p.radio_button :miniatura, true -%>
<%= link_to image_tag(p.object.photo.url(:small)), p.object.photo.url(:original) %>
<%= p.check_box :_destroy %>
</div>
<% end %>
<% end %>
</div>
The answer I went with is to use carrierwave instead of paperclip. It only took me about an hour to cut over, and it solves this problem out of the box.
Here's my answer in another thread with much more detail: Not losing paperclip attachment when model cannot be saved due to validation error
You could achieve this by using three models, and a bit of controller magic.
The first model is the model you actually want. Let's say Biography.
class Biography < ActiveRecord::Base
has_one :biography_fields
has_many :biography_attachments
end
class BiographyFields < ActiveRecord::Base
belongs_to :biography
# Validations
end
class BiographyAttachment < ActiveRecord::Base
belongs_to :biography
# Paperclip stuff
end
Now in your controller you can do something like this:
class BiographiesController
def some_method
@biography = Biography.find(params[:biography_id]) || Biography.create!
if @biography.biography_data.create(params[:biography_data])
# Try to save the uploads, if it all works, redirect.
else
# Still try the uploads, if they work, save them and make sure to pass the :biography_id as a hidden field so they can be used without re-uploading. Also reflect this in the form.
end
end
end
精彩评论