Reputation: 2908
I have a photo and product model. Photo belong to product and product has_many photos. Also product accepts_nested_attributes_for photos. I have a form that creates both the product and photo at the same time. I'm using jQuery-file-upload gem which gives a nice thumbnail and a start cancel button. The problem is that when I click the start upload button it submits the whole goddam form asynchronously.
This is a problem because:
HALP!
product form
= form_for @product,:url => products_path, :html => { id: "fileupload", multipart: true } do |f|
= f.text_field :name, placeholder: "Name"
%br
= f.text_field :price, class: "auto", data: { a_sign: "$ " }, placeholder: "Price"
%br
= f.fields_for :photos do |fp|
=fp.file_field :image
%br
.files{"data-target" => "#modal-gallery", "data-toggle" => "modal-gallery"}
%p.button.start
= f.submit
product controller
def new
@product = Product.new
@product.photos.build
end
def create
@product = current_user.products.create(params[:product])
@photo = Photo.new(params[:photo])
respond_to do |format|
if @product.save
format.html {
render :json => [@photo.to_jq_image].to_json,
:content_type => 'text/html',
:layout => false
}
format.json { render json: {files: [@photo.to_jq_image]}, status: :created, location: @photo }
else
format.html { render action: "new" }
format.json { render json: @photo.errors, status: :unprocessable_entity }
end
end
end
method: to_jq_image
def to_jq_image
{
"name" => read_attribute(:image_file_name),
"size" => read_attribute(:image_file_size),
"url" => image.url(:original),
"delete_type" => "DELETE"
}
end
console output
SQL (1.2ms) INSERT INTO "products" ("created_at", "name", "price", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["condition", "a good conditon"], ["created_at", Sun, 14 Jul 2013 17:58:19 UTC +00:00], ["name", "An example name"], ["price", #<BigDecimal:b2ab920,'0.125E1',18(18)>], ["updated_at", Sun, 14 Jul 2013 17:58:19 UTC +00:00], ["user_id", 6]]
Binary data inserted for `string` type on column `image_content_type`
SQL (1.8ms) INSERT INTO "photos" ("created_at", "image_content_type", "image_file_name", "image_file_size", "product_id", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["created_at", Sun, 14 Jul 2013 17:58:19 UTC +00:00], ["image_content_type", "image/jpeg"], ["image_file_name", "DWadeCrop.jpg"], ["image_file_size", 97742], ["product_id", 140], ["updated_at", Sun, 14 Jul 2013 17:58:19 UTC +00:00]]
(317.0ms) commit transaction
(0.1ms) begin transaction
(0.1ms) commit transaction
Completed 201 Created in 849ms (Views: 2.4ms | ActiveRecord: 320.6ms)
product && photo models
class Product < ActiveRecord::Base
attr_accessible :description, :name, :price, :photo, :photos_attributes
has_many :photos, dependent: :destroy
accepts_nested_attributes_for :photos, allow_destroy: true
include Rails.application.routes.url_helpers
belongs_to :user
validates :user_id, presence: true
validates :name, presence: true, length: { minimum: 5 }
validates :price, presence: true
validates :description, presence: true, length: { minimum: 5 }
end
class Photo < ActiveRecord::Base
attr_accessible :image
has_attached_file :image
include Rails.application.routes.url_helpers
belongs_to :product
validates_attachment :image, presence: true,
content_type: { content_type: ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'] },
size: { less_than: 5.megabytes }
has_attached_file :image, styles: { medium: "320x240>", :thumb => "100x100>"}
end
Upvotes: 0
Views: 257
Reputation: 527
Forget the way your doing it. Instead what you need to do is to split the forms up and put the one create photo form on top and remove the submit button. Then when the create product happens you look for all the photos the user has updated and that is not associated to the current product id
new product page
= form_for @photo, :html => { :multipart => true, :id => "fileupload" } do |f|
%span Add files...
= f.file_field :image
%br
= form_for @product,:url => products_path, :html => { id: "fileupload", multipart: true } do |f|
%p
= f.text_field :name, placeholder: "Name"
%p
= f.text_field :price, class: "auto", data: { a_sign: "$ " }, placeholder: "Price"
%p.button.start
= f.submit
product controller
def new
Photo.where(:product_id => nil, :user_id => current_user).delete_all
@product = Product.new
@photo = Photo.new
raise "foo"
end
def create
@product = current_user.products.create(params[:product])
if @product.save
Photo.where(:product_id => nil, :user_id => current_user).update_all(:product_id => @product.id)
render "show", notice: "Product created!"
else
render "new", error: "Error submitting product"
end
end
photo controller
def create
@photo = Photo.new(params[:photo])
respond_to do |format|
@photo.user_id = current_user.id
if @photo.save
format.html {
render :json => [@photo.to_jq_image].to_json,
:content_type => 'text/html',
:layout => false
}
format.json { render json: {files: [@photo.to_jq_image]}, status: :created, location: @photo }
else
format.html { render action: "new" }
format.json { render json: @photo.errors, status: :unprocessable_entity }
end
end
end
Upvotes: 1