【问题标题】:Rails 3 + JQuery-File-Upload + Nested ModelRails 3 + JQuery-文件上传 + 嵌套模型
【发布时间】:2012-03-10 14:03:24
【问题描述】:

我一直在寻找一些例子,但没有找到:

我正在尝试在我正在处理的项目上实现 JQuery-File-Upload,但是对于如何让它与嵌套属性一起工作却迷失了方向。

快速概览:

2 个型号:

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

评论接受_nested_attributes_for :attachments。另外 - 我正在使用 Dragonfly。

我已经查看了 JQuery-File-Upload 站点上的 Rails 3 指南,但他们认为它是一个单一的模型,所以它都是围绕一个表单构建的。有没有人有他们的实现示例,或者是否有一个我还没有偶然发现的现有教程?

我确定有人遇到过类似的问题...是 JQuery-File-Upload 到适当的工具还是我应该看看其他东西?

【问题讨论】:

  • 嘿,我遇到了类似的问题,我似乎无法将 JQuery-File-Upload 与nested_form gem 一起使用。你能找到解决办法吗?
  • 您是在专门要求 AJAX 上传,就像在用户仍在填写表单的其余部分时发送的文件一样,是吗?您是在处理图像还是只是一般的文件?而且,附件模型中除了文件之外是否还有其他内容——任何验证等?

标签: ruby-on-rails file-upload nested-attributes dragonfly-gem


【解决方案1】:

我只是想把我的答案和斯通的答案一样扔在这里。我花了将近两天的时间让这个工作(斯通是对的,它是一个 PITA!),所以希望我的解决方案能对某人有所帮助。我所做的只是与 Stone 稍有不同。

我的应用有Features(漫画、拼图、文本栏等)和FeatureAssets(单独的漫画面板/彩色版本、特定填字游戏的问答文件等)。由于FeatureAssets 仅与一个Feature 相关,因此我嵌套了模型(您将在我的上传表单中看到)。

对我来说最大的问题是意识到发送到服务器的params[:feature_asset] 实际上是我的上传者file 对象的数组,而不仅仅是我习惯使用的对象。在迭代每个文件并从中创建一个 FeatureAsset 之后,它就像一个魅力!

希望我能清楚地翻译这个。我宁愿提供太多信息而不是不够。当您解释别人的代码时,一点额外的上下文永远不会受到伤害。

feature.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

features _form.html.erb(类似于 Stone,但不完全)

<%= 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>

它没有错误处理或它应该有的任何细节,但那是它的准系统版本。

希望这可以帮助那里的人。如果您有任何问题,请随时问我!

凯尔

【讨论】:

  • 我正在尝试与您和 Stone 一样的想法,但我需要将 feature_asset 包含在创建 @feature 的相同形式中。有什么指点吗?
  • @AlainGoldman - 就像您尝试在同一表单上创建 FeatureFeatureAssets 一样?这是我基于我的代码的教程和应用程序。它正是这样做的! github.com/tors/jquery-fileupload-rails
  • 我通过使用类似的解决方案解决了这个问题:railscook.com/recipes/…
【解决方案2】:

我在 Carrierwave 上运行了类似的设置。这就是我所拥有的。我使用图像作为项目的嵌套资源。

项目.rb:

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

图片.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

请注意,这是 *!@^%!开始工作。

更新: 项目/_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>

【讨论】:

  • 您好,感谢您的回答。我正在尝试使用相同的解决方案。您也可以发布表单视图吗?谢谢!
  • 这是一个巨大的 *#&*(# 才能开始工作。我正在尝试弄清楚如何构建表单。嵌套表单似乎不起作用...
  • 当然 Marc,很久没看这段代码了,这里是图片上传的表单代码。我只是将 project_id 传递到 hidden_​​field_tag 中,以便稍后获取。祝你好运!
  • PS - 我可能已经重写了表单代码以不嵌套现在我回头看它。不管怎样,这就是我的生活。希望这些额外的信息对您有所帮助。
  • 我明白了。所以你不是同时用图像创建项目吗?我正在尝试提交(使用您的示例)一个包含多个图像的新项目。有什么想法吗?
【解决方案3】:

我已经解决了这个问题并创建了demo app 来展示如何做到这一点。

简而言之,我有两个模型:item 和 upload。

item.rb:

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

上传.rb:

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

我将uploads_attributes 添加到项目控制器。

现在您可以将 jquery-file-upload 表单添加到您的视图中,但是有一个问题:它以单独的请求发送每张照片。所以有我的 jquery-file-upload 初始化程序,它在一个请求中上传所有照片(创建项目模型),然后重定向到您的应用程序的根目录(您需要使用项目表单):

<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>

【讨论】:

  • 请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(而不是另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
猜你喜欢
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
  • 2011-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
相关资源
最近更新 更多