使用malsup的respond_to ... format.json和jQuery Form Plugin

时间:2010-02-09 14:53:04

标签: ruby-on-rails json file-upload jquery-forms-plugin

我在使用文件上传字段使jQuery Form Plugin正常工作时遇到了一些麻烦。当我使用插件提交没有文件上传字段的表单时,format.json块的respond_to do |format|部分被正确调用。但是,通过添加文件上传字段,它只会执行format.html部分,这会使我的javascript代码认为发生了错误。

有没有人遇到这个或者知道一种强制插件总是使用json的方法?或者,我可以修改插件用来强制Rails渲染json的URL吗?

非常感谢您的帮助!代码如下:

# app/controllers/details_controller.rb
def create
  @detail = Detail.new(params[:detail])

  style = params[:detail_style].to_sym || :thumb
  data = { :id => '5', :url => 'test.rails' }

  respond_to do |format|
    if @detail.save
      flash[:notice] = 'Your image has been saved.'
      data = { :id => @detail.id, :url => @detail.data.url(style) }

      format.html { redirect_to :action => 'index' }
      format.json { render :json => "<textarea>#{data.to_json}</textarea>", :status => :created }
    else
      format.html { render :action => 'new' }
      format.json { render :json => @detail.errors, :status => :unprocessable_entity }
    end
  end
end

/* app/views/sidebar/_details.html.erb (excerpt) */

<% form_for(Detail.new, :html => { :multipart => true } ) do |f| %>
  <%= hidden_field_tag 'detail_style', 'thumb' %>

  <%= f.label :image, "Recent Images" %>
  <%= f.file_field :image%>

  <p> 
    <%= f.submit "Upload" %>
  </p>
<% end %>

<script>
$(document).ready(function() {
  var options = {
    dataType: 'json',

    success: function(json, statusText) {
      console.log("success: " + json);
    },

    error: function(xhr, statusText, errorThrown) {
      console.log("error: " + xhr.responseText);
    }
  };

  $('#new_detail').ajaxForm(options);
});

5 个答案:

答案 0 :(得分:7)

需要做一些事情才能使jQuery Form插件适用于带有JSON响应的文件上传。 在javascript中,.ajaxForm的选项应该是:

dataType: 'json', // evaluate return as JSON

浏览器需要告诉Rails操作将内容作为JSON返回, 一种方法是在文件上传表单模板中添加隐藏格式输入字段:

<%= hidden_field_tag 'format', 'json' %>

然后,Rails操作将在respond_to块中运行format.json方法。

在服务器操作

  • 将JSON封装在标记中, .ajaxForm将正确解包字符串和eval JSON
  • 将返回内容类型设置为“text / html”,否则设置为某些浏览器 (Firefox)将尝试将返回值下载到文件中。

e.g。

  respond_to do |format|
    format.json {
          render :json => "<textarea>#{data.to_json}</textarea>", :content_type => "text/html"
    }
  }

答案 1 :(得分:2)

我为这个问题做了一个解决方法。我只使用Rails 3测试了这个解决方案,但也许它适用于2.3.x

解决方案非常简单:

!#javascript

$('form#my_form').live('submit',function(){ 
 $(this).ajaxForm({ dataType: "script", success: processJson})
 return false;
})

//data arrive as a string but we can parse it correctly

function processJson(data, statusText, xhr, $form){
 my_data_parsed = JSON.parse(data); 

  }

!#ruby 
def create
....   
render :js =>  { :status => false,:messages => @myobject.errors.full_messages}.to_json 

end 

答案 2 :(得分:1)

您可以使用firebug检查服务器的帖子,并在此处粘贴请求标头。我们希望看到Accept标头设置为json。另外,您使用的是哪种版本的导轨?

答案 3 :(得分:1)

我仍然不确定为什么它不起作用,但我尝试了很多东西,最后找到了解决方案。

我尝试通过在结尾处添加.json来更改网址,这迫使Rails呈现format.json块,但它让我认为我想要下载文件而混淆了我的浏览器。

所以,然后我尝试通过传递参数?format=json来修改url,遗憾的是它完全相同。

最后,我尝试将format.json更改为format.js(Javascript)并将.js添加到网址,但仍然使用之前的render :json => ...在我的jQuery调用dataType中设置json参数。即使它不是最佳解决方案,这似乎也可行。

我希望别人觉得这很有用。如果我找到合适的答案,我会再次发帖。在此期间,如果其他人有正确的答案,请告诉我,我会接受你的答案!

答案 4 :(得分:1)

显然,当使用ajaxSubmit并上传文件时,无法设置Accept标头。

请参阅此帖子here中的malsup答案。

他说:

文件上传不使用ajax,表单插件只显示它 办法。上传文件时会发生真正的浏览器提交。