对象的错误和重定向

时间:2010-03-30 19:47:42

标签: ruby-on-rails validation redirect

我知道,如果我写“redirect_to”而不是“render:action”,我将失去@对象的错误。

我的代码:

  def play
    @room = params[:id][0,1]
    @current_players = CurrentPlayer.all(:conditions => {:room => @room})
  end

  def join
    @new_player = CurrentPlayer.new(:user_id => current_user.id, :team_id => nil, :room => params[:room], :mode => params[:mode], :ip => request.remote_ip)
    if @new_player.save
      @game = create_game(params[:room], params[:mode])
      if @game
        flash[:notice] = 'Game created'
        return (redirect_to :action => "game_details", :recent => true)
      else
        flash[:error] = 'Game not created'
      end
   else
     return render(:action => 'play')
   end
    redirect_to_back
  end 

如果用户点击play.html.erb中的“加入”链接,Rails会向“加入”操作发送请求,如果有错误,我需要向用户显示。

但我不能只写redirect_to,我的代码现在是:

  def join
    @new_player = CurrentPlayer.new(:user_id => current_user.id, :team_id => nil, :room => params[:room], :mode => params[:mode], :ip => request.remote_ip)
    if @new_player.save
      @game = create_game(params[:room], params[:mode])
      if @game
        flash[:notice] = 'Game created'
        return (redirect_to :action => "game_details", :recent => true)
      else
        flash[:error] = 'Game not created'
      end
   else
    # == Very ugly and not DRY (just copypaste from 'play' action) ==
    @room = params[:id][0,1]
    @current_players = CurrentPlayer.all(:conditions => {:room => @room})
    # ===
     return render(:action => 'play')
   end
    redirect_to_back
  end 

我该如何避免使用该代码?

2 个答案:

答案 0 :(得分:1)

只需将公共代码重构为私有方法即可。我在这里手动调用新方法,但您也可以通过before_filter为这两个操作调用它。

def play
  setup_play
end

def join
  @new_player = CurrentPlayer.new(:user_id => current_user.id, :team_id => nil, :room => params[:room], :mode => params[:mode], :ip => request.remote_ip)
  if @new_player.save
    @game = create_game(params[:room], params[:mode])
    if @game
      flash[:notice] = 'Game created'
      return (redirect_to :action => "game_details", :recent => true)
    else
      flash[:error] = 'Game not created'
    end
  else
    setup_play
    return render(:action => 'play')
  end
  redirect_to_back
end

private

def setup_play
  @room = params[:id][0,1]
  @current_players = CurrentPlayer.all(:conditions => {:room => @room})
end

答案 1 :(得分:1)

只需重复使用播放操作,因为参数相同。另外,我建议以下内容以避免这么多嵌套的if语句

def play
  @room = params[:id][0,1]
  @current_players = CurrentPlayer.all(:conditions => {:room => @room})
end

def join
  @new_player = CurrentPlayer.new(:user_id => current_user.id, :team_id => nil, :room => params[:room], :mode => params[:mode], :ip => request.remote_ip)
  if ! @new_player.save
    play
    return render(:action => 'play')
  end

  @game = create_game(params[:room], params[:mode])
  if ! @game
    flash[:error] = 'Game not created'
    return(redirect_to_back)
  end

  flash[:notice] = 'Game created'
  return redirect_to(:action => "game_details", :recent => true)
end