验证失败后如何保留参数?丢失user_id引发NilClass错误求助
解决验证失败后丢失user_id参数的问题
这个问题的核心很明确:当create方法里的验证失败并执行render :new时,不会重新跑一遍new动作的逻辑——也就是说你的@user变量根本没被赋值,再加上表单提交时没带上user_id参数,后续调用@user.bank_account自然就会抛出undefined method 'bank_account' for nil:NilClass的错误。
下面给你两种靠谱的解决思路,优先推荐第一种:
方法一:表单携带user_id,create方法提前初始化@user
这是最直接的方案,确保不管是第一次访问new页面,还是验证失败回退,@user都能被正确赋值:
- 先在你的表单里加一个隐藏字段,把
user_id传进去:
# app/views/account_transactions/_form.html.erb <%= f.hidden_field :user_id, value: @user.id %>
- 然后修改
create方法,先从表单参数里取出user_id初始化@user,再处理交易对象:
# app/controllers/account_transactions_controller.rb def create # 先拿到用户,避免render :new时@user为nil @user = User.friendly.find(params[:account_transaction][:user_id]) @account_transaction = AccountTransaction.new(account_transaction_params) if @account_transaction.save redirect_to @account_transaction, notice: "Transfer Completed." else # 此时@user已经存在,表单里的@user.bank_account.id就能正常工作了 render :new end end
- 别忘了在参数白名单里加上
user_id:
private def account_transaction_params # 根据你实际需要的参数调整,务必加上user_id params.require(:account_transaction).permit(:target_bank_id, :source_bank_id, :amount, :user_id) end
方法二:通过关联反向获取用户(备选方案)
如果不想额外传递user_id,也可以从已有的target_bank_id反向关联到用户,但这个方案的前提是target_bank_id本身是有效的(如果验证失败是因为这个字段出错,那这个方法就会失效):
# app/controllers/account_transactions_controller.rb def create @account_transaction = AccountTransaction.new(account_transaction_params) # 从目标银行账户找到对应的用户 if @account_transaction.target_bank_id.present? @user = BankAccount.find(@account_transaction.target_bank_id).user end if @account_transaction.save redirect_to @account_transaction, notice: "Transfer Completed." else render :new end end
小提醒
你原来的link_to传递user_id: params[:id]是没问题的,但要确保从其他页面跳转过来时,params[:user_id]能正确传到new动作里,这样第一次加载表单时@user就是正常的。
总的来说,方法一的可靠性更高,能覆盖所有场景,推荐你优先采用。
内容的提问来源于stack exchange,提问作者Max Vinicius
相关产品推荐
相关产品推荐

