2012-02-20 26 views
12

我有一些例子一直在尋找,但都拿出了短:的Rails 3 + jQuery的文件上傳+嵌套模式

我試圖執行一個項目,我jQuery的文件上傳正在努力工作,但是如何讓它與嵌套屬性一起工作,我正在迷失方向。

快速概覽:

2型號:

Comment [has_many :attachments] 
Attachment [belongs_to :comment] 

評論accepts_nested_attributes_for :attachments。另外 - 我正在使用蜻蜓。

我已經回顧了JQuery文件上傳網站上的Rails 3指南,但他們認爲它是一個單一模型,所以它都是圍繞一個表單構建的。有沒有人有他們的實施的任何例子,或者有一個我還沒有偶然發現的現有教程?

我敢肯定有人有類似的問題......是JQuery的文件上傳到適當的工具,或者我應該看看別的東西?

+0

嘿,我我有一個類似的問題,我似乎無法使用jQuery-File-Upload與nested_form gem。你能找到解決辦法嗎? – 2012-04-02 13:47:39

+0

你要求AJAX上傳專門,因爲在用戶仍然填寫表格的其餘部分的文件發送,是嗎?你是否在處理圖像或一般文件?而且,Attachment模型除了文件之外還有其他什麼 - 任何驗證等? – Andrew 2012-04-21 00:42:28

回答

1

我有一個與Carrierwave運行類似的設置。這是我的。我使用圖像作爲項目的嵌套資源。

Project.rb:

has_many :images, :dependent => :destroy 
accepts_nested_attributes_for :images, :allow_destroy => true 

Image.rb:

include Rails.application.routes.url_helpers 
    mount_uploader :image, ImageUploader 

    belongs_to :project 

    #one convenient method to pass jq_upload the necessary information 
    def to_jq_upload 
    { 
    "name" => read_attribute(:image), 
    "size" => image.size, 
    "url" => image.url, 
    "thumbnail_url" => image.thumb.url, 
    "delete_url" => image_path(:id => id), 
    "delete_type" => "DELETE" 
    } 
    end 

Images_controller.rb:

def create 
    @image = Image.new(params[:image]) 
    @image.project_id = params[:project_id] 
    @project = Project.find(params[:project_id]) 
    @image.position = @project.images.count + 1 
    if @image.save 
     render :json => [ @image.to_jq_upload ].to_json 
    else 
     render :json => [ @image.to_jq_upload.merge({ :error => "custom_failure" }) ].to_json 
    end 
    end 

要知道,這是一個* @ ^%!去工作。

UPDATE: 項目/ _form.html.erb

<div id="fileupload" class="image_add"> 
    <%= form_for Image.new, :html => {:multipart => true} do |f| %> 
     <div class="fileupload-buttonbar"> 
      <label class="fileinput-button"> 
       <span>Add files...</span> 
       <%= hidden_field_tag :project_id, @project.id %> 
       <%= f.file_field :image %> 
      </label> 
      <button type="submit" class="start">Start Upload</button> 
      <button type="reset" class="cancel">Cancel Upload</button> 
      <button type="button" class="delete">Delete Files</button> 
     </div> 
    <% end %> 
    <div class="fileupload-content"> 
     <div class="dropzone-container"> 
      <div class="dropzone">Drop Image Files Here</div> 
     </div> 
     <table class="files"></table> 
    </div> 
</div> 
+0

嘿,謝謝你的回答。我試圖得到相同的解決方案。你也可以發佈表單視圖嗎?謝謝! – Marc 2012-10-19 17:58:51

+0

這是一個巨大的*#&*(#開始工作,我試圖弄清楚如何構建表單,嵌套表單似乎沒有成功... Marc 2012-10-19 19:09:14

+1

Sure Marc,我看了這段代碼已經很長時間了,但這裏是Image上傳的表單代碼。只是將project_id傳遞到hidden_​​field_tag中,以便稍後抓取它。祝您好運! – Stone 2012-10-19 20:54:18

6

我只想把我的答案在這裏,以及石的。我花了將近兩天的時間來完成這項工作(Stone是對的,這是一個PITA!),所以希望我的解決方案能夠幫助某人。我做的只是一個不同於斯通的觸覺。

我的應用程序有Features(漫畫,益智,文字列等)和FeatureAssets(個人漫畫面板/顏色的版本,質疑&應答文件特定字謎等)。由於FeatureAssets僅與一個Feature相關,因此我嵌套了這些模型(正如您在我的上傳表單中看到的那樣)。

對我來說,最大的問題就是意識到我params[:feature_asset]正被髮送到服務器實際上是我uploader'd file對象的數組,而不是隻是一個我,以利用工作。在迭代遍歷每個文件並從中創建FeatureAsset之後,它會像魅力一樣工作!

希望我會把它清楚地翻譯出來。我寧願提供太多信息,也不夠。當你解釋別人的代碼時,一點額外的上下文不會受到傷害。

功能。RB

class Feature < ActiveRecord::Base 
    belongs_to :user 
    has_many :feature_assets 

    attr_accessible :name, :description, :user_id, :image 

    accepts_nested_attributes_for :feature_assets, :allow_destroy => true 

    validates :name, :presence => true 
    validates :user_id, :presence => true 

    mount_uploader :image, FeatureImageUploader 
end 

feature_asset.rb

belongs_to :user 
    belongs_to :feature 

    attr_accessible :user_id, :feature_id, :file, :file_cache 

    validates :user_id,  :presence => true 
    validates :feature_id, :presence => true 
    validates :file,  :presence => true 

    mount_uploader :file, FeatureAssetContentUploader 

    # grabs useful file attributes & sends them as JSON to the jQuery file uploader 
    def to_jq_upload 
    { 
     "file" => file, 
     "file_name" => 'asdf', 
     "url" => file.url, 
     "delete_url" => id, 
     "delete_type" => "DELETE" 
    } 
    end 

feature_assets_controller.rb

def create 
    @feature = Feature.find(params[:feature_id]) 

    params[:feature_asset]['file'].each do |f| 
     @feature_asset = FeatureAsset.create!(:file => f, :feature_id => @feature.id, :user_id => current_user.id) 
    end 

    redirect_to @feature 
    end 

而且不是,它可能有助於多,但我feature_asset_uploader.rb如下。它相當精簡。

class FeatureAssetContentUploader < CarrierWave::Uploader::Base 

    storage :file 

end 

功能_form.html.erb(類似石頭的,但並不完全)

<%= form_for [@feature, @feature_asset], :html => { :multipart => true } do |f| %> 
    <div class="row" id="fileupload"> 
    <div class=" fileupload-buttonbar"> 
     <div class="progressbar fileupload-progressbar nofade"><div style="width:0%;"></div></div> 
     <span class="btn btn-primary fileinput-button"> 
     <i class="icon-plus"></i> 
     <span><%= t('feature_assets.add_files') %>...</span> 
     <%= hidden_field_tag :feature_id, @feature.id %> 
     <%= hidden_field_tag :user_id, current_user.id %> 
     <%= f.file_field :file, :multiple => true %> 
     </span> 
     <button type="submit" class="btn btn-success">Start Upload</button> 
     <button type="reset" class="btn btn-warning">Cancel Upload</button> 
     <button type="button" class="btn btn-danger">Delete Files</button> 
    </div> 
    </div> 

它沒有錯誤處理或任何它應該有大樂事,但是這就是準系統版本的。

希望能幫助那裏的人。隨意問我,如果您有任何問題!

凱爾

+0

我正在嘗試和你一樣思考,但是我需要feature_asset被包含在相同的表單中@feature被創建。任何指針? – 2013-07-13 12:07:19

+0

@AlainGoldman - 正如你試圖在同一個表單上創建'Feature'和它是'FeatureAssets'一樣?這是我基於我的代碼的教程和應用程序。它確實如此! https://github.com/tors/jquery-fileupload-rails – 2013-07-15 05:18:21

+0

我通過使用類似於以下解決方案解決了此問題:http://www.railscook.com/recipes/multiple-files-upload-with-nested-resource- using-paperclip-in-rails/ – Galaxy 2014-05-07 11:13:18

0

我已經應對了這一問題,並提出了demo app來說明如何做到這一點。

總之我有兩個模型:項目和上傳。

item.rb的:

has_many :uploads 
accepts_nested_attributes_for :uploads, :allow_destroy => true 

upload.rb:

belongs_to :item 
    has_attached_file :upload, :styles => { :large => "800x800", :medium => "400x400>", :small => "200x200>" } 

我加uploads_attributes項控制器。

現在您可以將jquery-file-upload表單添加到您的視圖中,但是存在一個問題:它會將每張照片發送到不同的請求中。所以我的jQuery的文件上傳初始化,其上傳的所有照片中的一個請求(創建項目模型),然後重定向到您的應用程序的根目錄(你需要使用項目表單):

<script type="text/javascript" charset="utf-8"> 
    var num_added = 0; 
    var added = 0; 
    var all_data = {}; 
    $(function() { 
     // Initialize the jQuery File Upload widget: 
     $('#fileupload').fileupload({ 
      complete: function (e, data) { 
      window.location = "<%= root_url %>"; 
     }, 
      singleFileUploads: false 
     }) .bind('fileuploadadd', function (e, data) {num_added++;}) 
      .bind('fileuploadsubmit', function (e, data) { 
      if(added < num_added) 
      { 
      if (added == 0) 
      all_data = data; 
      else 
      { 
      $.each(data['files'], function(i, file){ 
      all_data['files'].push(file); 
      }); 
      $.each(data['context'], function(i, context){ 
      all_data['context'].push(context); 
      }); 
      } 
      added++; 
      if (added == num_added) 
      { 
      added++; 
      all_data.submit(); 
      } 
      return false; 
      } 
      }) 
      .bind('fileuploadsend', function (e, data) {num_added = 0; added = 0;}); 

     // 
     // 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(); 
     }); 

    }); 
    </script> 
+0

請注意,[只有鏈接的答案](http://meta.stackoverflow.com/tags/link-only-answers/info)是不鼓勵的,所以SO答案應該是尋找一個解決方案(而不是另一個參考中途停留,這往往會隨着時間的推移變得陳舊)。請考慮在此添加獨立的摘要,並將鏈接保留爲參考。 – kleopatra 2013-10-06 10:01:52