使用带有remote:true的表单上传Ruby on Rails文件

时间:2014-07-17 07:45:24

标签: javascript ruby-on-rails forms remotipart

我正在尝试使用Rails表单上传文件,其中遥控器设置为true。我正在使用Rails 4.1.1。假设我的模型是一个Message,它使用JavaScript,这样用户可以轻松发送多条消息而无需重新加载页面。表单设置如下:

<%= form_for @message, url: {action: "create"}, html: {:class => "message-form", multipart: true}, remote: true do |f| %>

如果愿意,用户可以使用消息上传图像。 MessageImage在表单中充当嵌套属性,并且声明为这样(http://railscasts.com/episodes/196-nested-model-form-revised方式):

<%= f.fields_for :message_images do |builder| %>
   <%= render 'message_image_fields', f: builder %>
   <%= link_to_add_fields "Add an image", f, :message_images %>
<% end %>

在我的控制器上,操作大致如下:

if @message.save
   flash.now[:success] = "Message sent"
else
   flash.now[:alert] = "Error sending the message"
end
respond_to do |format|
   format.html { render 'new' }
   format.js { render 'new' }
end

现在,只要用户不发送任何图像,这就完美无缺,但如果他们这样做,则使用format.html而不是format.js。删除format.html会产生ActionController :: UnknownFormat-exception。

现在,这显然与您无法将远程设置为true的文件一起提交。我试了一下,找到了这个宝石https://github.com/JangoSteve/remotipart,这似乎正是我正在寻找的。我按照说明安装它,但由于某种原因,如果我删除format.html,它仍然无法正常工作并提供ActionController :: UnknownFormat-exception。但是,我找不到涉及嵌套属性的任何示例。有没有替代这个宝石或任何其他方法来解决这个问题,或者我应该设置它如果用户提交文件它呈现HTML?

1 个答案:

答案 0 :(得分:1)

<强> JQuery的

我不知道如何获得嵌套模型方面的内容,但我们在here之前使用JQuery / asynchronicity完成了文件上传(注册帐户,登录到配置文件):< / p>

enter image description here

我们使用了jquery-file-upload gem - 基本上允许您通过Ajax将文件传递给控制器​​后端。为了让您清楚了解我们是如何做到的:

-

<强>代码

#app/assets/javascripts/application.js
$('#avatar').fileupload({

    url: '/profile/' + $(this).attr('data_id'),
    dataType: 'json',
    type: 'post',

    add: function (e, data) {
        $(this).avatar_loading('avatar_loading');
        data.submit();
    },
    success: function (data, status) {;
        $("#avatar_img").fadeOut('fast', function() {
            $(this).attr("src", data.avatar_url).fadeIn('fast', function(){
                $(this).avatar_loading('avatar_loading');
            });
        });
    }

});


#app/views/users/index.html.erb
<%= form_for :upload, :html => {:multipart => true, :id => "avatar"}, :method => :put, url: profile_path(current_user.id), "data_id" => current_user.id do |f| %>
    <div class="btn btn-success fileinput-button avatar" id="avatar_container">
            <%= f.file_field :avatar, :title => "Upload New" %>
            <%= image_tag(@user.profile.avatar.url, :width=> '100%', :id => "avatar_img", :alt => name?(@user)) %>
    </div>
<% end %>


#app/controllers/profile_controller.rb
Class ProfileController < ApplicationController
   def update
       def update
        @profile = User.find(current_user.id)
        @profile.profile.update(upload_params)

        respond_to do |format|
            format.html { render :nothing => true }
            format.js   { render :partial => 'profiles/update.js' }
            format.json { 
                render :json => @profile.profile.as_json(:only => [:id, :avatar], :methods => [:avatar_url])
            }
        end

        def upload_params
            params.require(:upload).permit(:avatar, :public, :description)
        end
   end
end

-

<强>实施

对于您的实施,我建议首先创建消息,然后让用户在另一个动作中附加一些图像

在您完成工作之后,您可以将其作为一个表单

工作