Rails跨控制器使用form_for实例变量报错,如何解决?
解决Rails表单中@comment为nil的报错问题
咱们先来拆解下你遇到的问题:你在posts/show.html.erb里用@comment构建表单时出现First argument in form cannot contain nil or be empty错误,核心原因是你初始化@comment的位置错了。
为什么你的new方法没被调用?
你访问的是posts#show页面,这个请求对应的是PostsController的show方法,而不是posts#new或者comments#new方法。你在那两个new方法里定义的@comment,只有当用户访问对应的new页面时才会被执行,和show页面完全不相关,所以show页面里的@comment自然是nil。
正确的解决步骤
1. 在PostsController的show方法里初始化@comment
既然表单是在posts/show页面渲染的,那就要在渲染这个页面的动作(也就是show方法)里创建空的评论实例:
# app/controllers/posts_controller.rb def show # 保留你原本获取@post的代码,比如: @post = Post.find(params[:id]) # 新增这行,初始化空评论 @comment = Comment.new end
2. 调整表单的form_for写法(关联到所属的Post)
因为评论是属于某个Post的,推荐用嵌套资源的写法来构建表单,这样表单提交的路径才会正确指向CommentsController的create方法:
# app/views/posts/show.html.erb <%= form_for [@post, @comment] do |f| %> <%= f.label :content %> <%= f.text_field :content %><br/> <%= f.submit %> <% end %>
3. 更新路由,添加嵌套资源
为了让嵌套的表单路径生效,需要在routes.rb里把comments嵌套在posts下:
# config/routes.rb Rails.application.routes.draw do root to: 'posts#show' resources :posts do # 只需要create路由,因为我们不在单独页面创建评论 resources :comments, only: [:create] end resources :messages end
4. 完善CommentsController的create方法
确保创建评论时能关联到对应的Post,并处理保存成功/失败的情况:
# app/controllers/comments_controller.rb def create @post = Post.find(params[:post_id]) @comment = @post.comments.build(comment_params) if @comment.save redirect_to @post, notice: '评论创建成功!' else # 保存失败时回到post的show页面,重新渲染表单 render 'posts/show' end end private def comment_params params.require(:comment).permit(:content) end
这样调整后,你在posts/show页面的表单就能正常使用@comment来构建,而且提交后能正确关联到对应的Post啦。
内容的提问来源于stack exchange,提问作者reesaspieces
相关产品推荐
相关产品推荐

