Rails中has_one关联表单创建报错:undefined method `build' for nil:NilClass
问题解决:has_one关联表单报错
undefined method 'build' for nil:NilClass 错误原因
当Book还没有关联的SubDemo时,@book.sub_demo会返回nil,直接在nil上调用build就会触发这个错误。Rails的has_one关联有专门的构建方法,不能直接在空关联对象上调用build。
修复步骤
1. 修正表单代码
把表单中的模型构建改成@book.build_sub_demo,同时添加判断逻辑,只有当Book没有对应的SubDemo时才显示表单,满足“一次性提交后不再显示”的需求:
<% if @book.sub_demo.nil? %> <%= form_with model: [@book, @book.build_sub_demo], local: true do |form| %> <div class="col-md-3"> <%= form.label :name %> </div> <div class="col-md-3"> <%= form.text_field :name %> </div> <div class="col-md-3"> <%= form.label :age %> </div> <div class="col-md-3"> <%= form.text_area :age %> </div> <div class="text-start"> <%= form.submit class: "btn btn-info btn-sm" %> </div> <% end %> <% end %>
2. 调整路由配置
因为是has_one关联,路由应该用单数的resource而非复数resources,更符合RESTful设计,同时避免生成多余的路由:
resources :books do resource :sub_demo # 使用单数resource end
3. 确保控制器正确初始化对象
在对应的控制器action(比如BooksController#show)中,保证@book被正确加载:
class BooksController < ApplicationController def show @book = Book.find(params[:id]) # 可选:提前构建对象,避免视图中重复判断,不写也不影响功能 # @book.build_sub_demo unless @book.sub_demo.present? end end
4. 完善SubDemosController的create方法
确保创建SubDemo时正确关联到对应的Book:
class SubDemosController < ApplicationController def create @book = Book.find(params[:book_id]) @sub_demo = @book.create_sub_demo(sub_demo_params) if @sub_demo.save redirect_to @book, notice: 'SubDemo已创建' else render 'books/show' end end private def sub_demo_params params.require(:sub_demo).permit(:name, :age) end end
修改完成后,当Book没有SubDemo时会显示表单,提交后创建关联对象,再次访问该Book页面就不会再显示表单,同时彻底解决了build方法的报错问题。
内容的提问来源于stack exchange,提问作者Muhammad Fahad
相关产品推荐
相关产品推荐

