【问题标题】:After validation fails and a form redirects back to itself, why are instance variables empty?验证失败并且表单重定向回自身后,为什么实例变量为空?
【发布时间】:2012-06-10 17:43:50
【问题描述】:

在 Rails 3.2 应用程序中,当某个表单无法保存(验证失败)并重定向回该表单时,我会收到错误消息:

undefined method `map' for nil:NilClass

直接导航到新路径或编辑路径时,此表单不会显示任何错误。

错误来自使用自定义 options_from_collection_for_select 方法的选择字段。

<%= f.select(:user_ids, options_from_collection_for_select_with_attributes(@users, :id, :name, 'data-attributes', :attributes ), {include_blank:true}, {multiple:true}) %>

如果我将实例变量 @users 替换为 User.all,则重定向后不会出现错误。

我猜@users 在重定向后为空,因此出现错误。但为什么? @users 在 new 和 edit 控制器中定义。

我的控制器是:

def create
  --bunch of stuff
  if @model.save
    --bunch of stuff
    respond_to do |format|
      format.html { render :text => model_url(@model) }
      format.html { redirect_to(@model, :notice => 'Success!.') }
      format.xml  { render :xml => @model, :status => :created, :location => @model }
    end

  else
    respond_to do |format|
      format.html { render :action => "new" }
      format.xml  { render :xml => @model.errors, :status => :unprocessable_entity }
    end
  end
end

【问题讨论】:

  • 我也遇到了同样的问题。我猜实际的edit 方法不会在重定向时被调用。我必须在重定向之前重新初始化所有实例变量,例如您的 @users
  • 如果验证失败,您不应重定向。相反,您应该简单地渲染适当的视图(:如果创建失败则新建,如果更新失败则编辑)
  • 感谢@Adnan。我希望我不需要这样做,它会在复杂的表格上变得冗长!
  • @LarryK,谢谢。我渲染不重定向。很抱歉这个误导性问题。
  • 我通常定义一个包含所有初始化的方法(比如pre_requisites)。然后我在 editnew 操作中使用此方法(因为它们通常是相同的初始化,并且在验证失败的情况下调用渲染之前)

标签: ruby-on-rails


【解决方案1】:

这是因为如果“新”操作失败,您实际上并没有执行它。这是一个典型的控制器结构

class PotsController < ApplicationController

  def new
    @pot = Pot.new
    @users = User.all
  end

  def create
    @pot = Pot.new(params[:pot])
    if @pot.create
      redirect_to @pot, notice: "Created"
    else
      #****you are here****
      render :new
    end
  end
end

在上面,如果pot.create 失败,它只会渲染新模板。在这种情况下,你应该做的是获取你的实例变量

  def create
    @pot = Pot.new(params[:pot])
    if @pot.create
      redirect_to @pot, notice: "Created"
    else
      @users = User.all #this is the important line
      render :new
    end
  end

【讨论】:

  • 谢谢@Jesse,这个有短手吗?如果我需要在复杂表单上定义所有实例变量两次,这将变得复杂。
  • 您可以将所有 load_instance_variables 移动到一个方法中,并在两个地方调用该方法。如果您加载超过 1 个实例变量,这是非常标准的。
猜你喜欢
  • 2013-11-05
  • 1970-01-01
  • 2011-09-05
  • 2016-06-28
  • 1970-01-01
  • 1970-01-01
  • 2015-04-24
  • 2016-04-03
  • 1970-01-01
相关资源
最近更新 更多