2012-09-24 37 views
1

我只是在学习Rails,并希望得到任何帮助。我已经在form_for上查看了:remote => true的10个教程,它们似乎都是相互复制的(同样令人困惑)。:remote =>真正的混淆与form_for

本教程是其中之一:http://tech.thereq.com/post/18910961502/rails-3-using-form-remote-true-with-jquery-ujs

我的web应用程序是几乎所有在一个页面上,和我的“提交表单”是一个弹出式灯箱内。这意味着form_for代码实际上在我的index.html.erb中。这也意味着index创建一个新的@playlist实例变量(而不是有这是new

我的最终目标是这样的

if @playlist.save回报true,我想将用户重定向到root_path WITH a:notice。没有必要用成功消息或类似的东西来更新表单。我想要保存成功的硬重定向。

if @playlist.save返回false,我想渲染create.js.erb中的代码,它会将错误追加到lightbox窗体中而不刷新页面。 note很多教程似乎都希望将整个表单重新渲染为html,然后替换内容。我宁愿(如果可以的话),只是将错误发送到表单并插入它们,我认为重新渲染和替换整个表单似乎比它更复杂。

截至目前,我的代码是一种糊涂的,尤其是:

  • respond_to块。这是关于什么实际上在这里混淆最大的一点,我已经尝试了很多不同的代码,没有任何作品
  • 我不知道如果create.js.erb是正确的
  • 我没有create.html.erb - 我认为这是正确的,因为我只是想我的重定向形式的

第一行:

<%= form_for @playlist, :remote => true do |f| %> 

我的整个PlaylistsController

class PlaylistsController < ApplicationController 

    before_filter :load_genres, :only =>[:index, :user] 
    before_filter :new_playlist, :only => [:index, :new, :create] 

    def index 
    @playlists = Playlist.order('created_at DESC').page(params[:page]).per(30) 
    end 

    def new 
    end 

    def create 
    respond_to do |format| 
     if @playlist.save 
     # ??? 
     format.html { redirect_to root_path, :notice => "Playlist submitted" } 
     else 
     # ??? 
     format.js { render :js => @playlist.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 

    def user 
    @playlists = Playlist.order('created_at DESC').where(:username => params[:username]).page(params[:page]).per(30) 
    end 

    def listen 
    playlist = Playlist.find(params[:playlist_id]) 
    playlist.update_attribute(:listens, playlist.listens + 1) 
    render :nothing => true 
    end 

    private 

    def load_genres 
    @genres = Genre.order(:name) 
    end 

    def new_playlist 
    @playlist = Playlist.new(:title => params[:title], :url => params[:url], :description => params[:description]) 
    end 

end 

create.js.erb

jQuery(function($) { 
    alert('createjs called'); 
    $('#submit-form form').on('ajax:error', function(event, xhr, status, error){ 

     var responseObject = $.parseJSON(xhr.responseText), 
      errors = $('<ul />'); 

     $.each(responseObject, function(index, value){ 
      errors.append('<li>' + value + '</li>'); 
     }) 

     $(this).find('.submit-playlist-errors').html(errors); 
    }); 
}); 
+0

我其实是有点困惑你使用,你需要达到什么样的挣扎什么。什么工作,什么不是。你能简化和打破你的问题吗? – simonmorley

+0

相信我我曾试图在其他论坛和其他论坛上将其分解。这很难解释,我试图让它真正清楚我在找什么。截至目前,它只是没有工作,时期。我知道这个问题是我的respond_to块,这主要是因为我不明白它和所有我读过的教程混淆了这个话题 – Tallboy

+0

我已经意识到一个错误是,我有这样的:'@playlist = Playlist.new( :title => params [:title],:url => params [:url],:description => params [:description])'。它应该是'params [:播放列表]'。我会在一瞬间给出确切的错误 – Tallboy

回答

2

如果我理解正确的话,你有一个表单,你想用flash通知重定向如果表单保存。如果表单无效,您希望显示错误。

您可以将表单(或任何请求)以不同格式(通常为html,json和js)发送到rails应用程序。这在您提供的网址中指定。

playlist_path(@playlist) 
# => /playlists/1 

playlist_path(@playlist, :format => "json") 
# => /playlists/1.json 

playlist_path(@playlist, :format => "html") 
# => /playlists/1.html 
# ... etc 

该格式告诉导轨在您的respond_to块中指定使用哪种响应。现在

如果这是明确的,你必须决定使用哪种格式。

如果指定js格式,响应将被视为script的执行。如果表单有效,您可以发送用户JavaScript,将其重定向到您所需的页面。如果表单无效,您可以修改HTML以便显示错误消息。没有客户端代码需要。

respond_to do |format| 
    if valid 
    format.js { render "valid" } 
    else 
    format.js { render "invalid", :status => :unprocessable_entity } 
    end 
end 

# valid.js.erb 
window.location = <%= your_path %> 

# invalid.js.erb 
// whatever to display errors 

当您使用json你可以返回重定向URL重定向用户或错误,如果形式是无效的。请注意,该解决方案需要客户端的Javascript来处理它。

# controller 
respond_to do |format| 
    if valid 
    format.json { render :json => your_path } 
    else 
    format.json { render :json => @object.errors, :status => :unprocessable_entity } 
    end 
end 

# client side javascript 
$("form") 
    .on("ajax:success", function(event, data, status, response) { 
    window.location = data 
    }) 
    .on("ajax:error", function(event, response, error) { 
    // logic to handle errors 
    }) 

您还可以使用html格式(通过设置格式html或不指定格式在所有)。但是,如果你使用:remote => true你也会有同样的方式来对待它作为json(有客户端的JavaScript)。如果您使用redirect_to作为回应,它将重定向请求,而不是您的用户。

我不知道该用户被重定向,但你可以尝试这种方式后显示提示信息:

respond_to do |format| 
    if valid 
    format.html { 
     flash[:notice] = "Playlist submitted" 
     render :json => your_path } 
    else 
    format.html { render :json => @object.errors, :status => :unprocessable_entity } 
    end 
end 

# client side javascript 
//... 

希望这会干你respond_to块。

+0

太棒了,谢谢。让我看看 – Tallboy

+0

有没有一种方法可以在不使用javascript的情况下重定向?就像服务器发回的响应重定向它们一样? – Tallboy

+1

恐怕没有这种方式。您可以通过调用'render:js =>“window.location =#{your_path}”''''''''''''''''''''''''' – DaveTsunami