2013-07-02 23 views
0

我有一個創建產品頁面,其中嵌套創建照片。照片屬於產品和產品有很多照片。我正在使用the jQuery file upload plugin,但它需要您在上傳後點擊保存。這是一個問題,因爲它是以我的產品形式出現的,我無法在沒有產品的情況下保存照片。所以這是當我保存時發生的事情。 「內部服務器錯誤!」 (以上創建產品)使用jQuery文件上傳插件嵌套form_for

The error I see

而這正是在控制檯得到的輸出!

控制檯錯誤

Started POST "/products" for 127.0.0.1 at 2013-07-02 15:01:38 -0400 
Processing by ProductsController#create as JSON 
Parameters: {"utf8"=>"✓", "authenticity_token"=>"z5BnHkHTqPZGKt+uWQs10wUEKkGlphXth0rqM82tjR0=", "product"=>{"name"=>"", "description"=>"", "condition"=>"", "quantity"=>"", "price"=>"", "ship_method"=>"", "ship_price"=>"", "photos_attributes"=>{"0"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x9699c3c @original_filename="eye.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"product[photos_attributes][0][image]\"; filename=\"eye.jpg\"\r\nContent-Type: image/jpeg\r\n", @tempfile=#<File:/tmp/RackMultipart20130702-5814-cu2g3o>>}}}} 
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."auth_token" = 'eQOQkRRSnzfA51iiDQ-90w' LIMIT 1 
Command :: identify -format '%wx%h,%[exif:orientation]' '/tmp/eye20130702-5814-12toyjt.jpg[0]' 
Command :: identify -format %m '/tmp/eye20130702-5814-12toyjt.jpg[0]' 
Command :: identify -format %m '/tmp/eye20130702-5814-12toyjt.jpg[0]' 
Command :: identify -format %m '/tmp/eye20130702-5814-12toyjt.jpg[0]' 
Command :: convert '/tmp/eye20130702-5814-12toyjt.jpg[0]' -auto-orient -resize "320x240>" '/tmp/eye20130702-5814-12toyjt20130702-5814-vpw0ed' 
Command :: file -b --mime '/tmp/eye20130702-5814-12toyjt20130702-5814-vpw0ed' 
Command :: identify -format '%wx%h,%[exif:orientation]' '/tmp/eye20130702-5814-12toyjt.jpg[0]' 
Command :: identify -format %m '/tmp/eye20130702-5814-12toyjt.jpg[0]' 
Command :: identify -format %m '/tmp/eye20130702-5814-12toyjt.jpg[0]' 
Command :: identify -format %m '/tmp/eye20130702-5814-12toyjt.jpg[0]' 
Command :: convert '/tmp/eye20130702-5814-12toyjt.jpg[0]' -auto-orient -resize "100x100>" '/tmp/eye20130702-5814-12toyjt20130702-5814-b835qy' 
Command :: file -b --mime '/tmp/eye20130702-5814-12toyjt20130702-5814-b835qy' 
Rendered products/new.js.erb (5.2ms) 
Completed 500 Internal Server Error in 806ms 

AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".): 
app/controllers/products_controller.rb:34:in `block (2 levels) in create' 
app/controllers/products_controller.rb:32:in `create' 


Rendered /home/alain/.rvm/gems/ruby-1.9.3-head/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_trace.erb (39.6ms) 
Rendered /home/alain/.rvm/gems/ruby-1.9.3-head/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.2ms) 
Rendered /home/alain/.rvm/gems/ruby-1.9.3-head/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (52.8ms) 

新產品頁面(HAML)

= form_for @product,:url => products_path, :html => { :id => "fileupload", :multipart => true } do |f| 

    %p 
    = f.label :name 
    = f.text_field :name 
    %p 
    = f.label :description 
    = f.text_field :description 
    %p 
    = f.label :condition 
    = f.text_field :condition 
    %p 
    = f.select :quantity, [['Quantity', nil], '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] 
    %p 
    = f.label :price 
    = f.text_field :price, class: "auto", data: { a_sign: "$ " } 
    %p 
    =f.select :ship_method, [['Shipping', nil], 'usps', 'ups', 'fedex'] 
    %p 
    = f.label :ship_price 
    = f.text_field :ship_price, class: "auto", data: { a_sign: "$ " } 

    %p 
    = f.fields_for :photos do |fp| 
     =fp.file_field :image 
     %br 

    .files{"data-target" => "#modal-gallery", "data-toggle" => "modal-gallery"} 
    %p.button 
    = f.submit 

:javascript 
    var fileUploadErrors = { 
    maxFileSize: 'File is too big', 
    minFileSize: 'File is too small', 
    acceptFileTypes: 'Filetype not allowed', 
    maxNumberOfFiles: 'Max number of files exceeded', 
    uploadedBytes: 'Uploaded bytes exceed file size', 
    emptyResult: 'Empty file upload result' 
    }; 


/The template to display files available for upload 
%script#template-upload{:type => "text/x-tmpl"} 
    {% for (var i=0, file; file=o.files[i]; i++) { %} 
    <tr class="template-upload fade"> 
    <td class="preview"><span class="fade"></span></td> 
    <td class="name"><span>{%=file.name%}</span></td> 
    <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td> 
    {% if (file.error) { %} 
    <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td> 
    {% } else if (o.files.valid && !i) { %} 
    <td> 
     <div class="progress progress-success progress-striped active"><div class="bar" style="width:0%;"></div></div> 
    </td> 
    <td class="start">{% if (!o.options.autoUpload) { %} 
     <button class="btn btn-primary"> 
     <i class="icon-upload icon-white"></i> 
     <span>{%=locale.fileupload.start%}</span> 
     </button> 
     {% } %}</td> 
    {% } else { %} 
    <td colspan="2"></td> 
    {% } %} 
    <td class="cancel">{% if (!i) { %} 
     <button class="btn btn-warning"> 
     <i class="icon-ban-circle icon-white"></i> 
     <span>{%=locale.fileupload.cancel%}</span> 
     </button> 
     {% } %}</td> 
    </tr> 
    {% } %} 
/The template to display files available for download 
%script#template-download{:type => "text/x-tmpl"} 
    {% for (var i=0, file; file=o.files[i]; i++) { %} 
    <tr class="template-download fade"> 
     {% if (file.error) { %} 
     <td></td> 
     <td class="name"><span>{%=file.name%}</span></td> 
     <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td> 
     <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[ file.error] || file.error%}</td> 
     {% } else { %} 
     <td class="preview">{% if (file.thumbnail_url) { %} 
      <a href="{%=file.url%}" title="{%=file.name%}" rel="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}"></a> 
      {% } %}</td> 
     <td class="name"> 
      <a href="{%=file.url%}" title="{%=file.name%}" rel="{%=file.thumbnail_url&&'gallery'%}" download="{%=file.name%}">{%=file.name%}</a> 
     </td> 
     <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td> 
     <td colspan="2"></td> 
     {% } %} 
     <td class="delete"> 
     <button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}"> 
      <i class="icon-trash icon-white"></i> 
      <span>{%=locale.fileupload.destroy%}</span> 
     </button> 
     <input type="checkbox" name="delete" value="1"> 
     </td> 
    </tr> 
    {% } %} 
%script{:charset => "utf-8", :type => "text/javascript"} 
    $(function() { 
     // Initialize the jQuery File Upload widget: 
     $('#fileupload').fileupload(); 
     // 
     // Load existing files: 
     $.getJSON($('#fileupload').prop('action'), function (files) { 
     var fu = $('#fileupload').data('blueimpFileupload'), 
      template; 
     fu._adjustMaxNumberOfFiles(-files.length); 
     console.log(files); 
     template = fu._renderDownload(files) 
      .appendTo($('#fileupload .files')); 
     // Force reflow: 
     fu._reflow = fu._transition && template.length && 
      template[0].offsetWidth; 
     template.addClass('in'); 
     $('#loading').remove(); 
     }); 

    }); 

產品控制器

def new 
    @product = Product.new 
    @photo = Photo.new 
    @product.photos.build 
    end 

    def create 
    @product = current_user.products.new(params[:product]) 
    @photo = current_user.photos.new(params[:photo]) 

    if @product.valid? 
     @product.save 
     @photo.product_id = @product.id 
     @photo.save 
     render "show", :notice => "Sale created!" 
    else 
     @product.photos.build 
     render "new", :notice => "Somehting went wrong!" 
    end 


    respond_to do |format| 
     format.html 
     format.json { render json: @photo } 
    end 
    end 

我應該怎樣做?

回答

1

我同意@ jjay225在單個請求中上傳產品和圖像。

但是,您不必單獨保存它們。您可以將這兩項保存在一個保存命令中。

爲此,您可以使用accep_nested_attributes_for爲此。 這將是驗證的好處。如果保存一條記錄失敗,另一條記錄也失敗。

讓我知道你是否需要這樣一個例子。

+0

我很喜歡這個例子! –

+0

以下是圖片上傳的示例: https://gist.github.com/deepakdargade/5928404 – Deepak

1

避免出現複雜情況,創建產品時不顯示上傳字段,只在編輯頁面顯示。

另一種選擇是通過AJAX首先發送產品表單,並在AJAX成功時顯示圖像上傳字段。

+0

我認爲這是一個很好的建議。另一種方法是首先將圖像上傳到臨時路徑,並且僅當產品被保存時纔將它們移動到永久路徑。 – rineez

0

我會說瀏覽圖像,但不要上傳它。然後輸入您的產品詳細信息並將其發佈到服務器上,當然,請將ID保存到新創建的產品中,然後將鏈接保存到圖像中,以便能夠將圖像鏈接到您剛剛保存的產品。