2012-02-20 27 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