Rails创建Product关联Category报错:undefined method `products_path'
这个错误的核心原因是Rails找不到处理产品创建请求的路由:
当你使用form_for [@product]时,Rails会默认生成一个指向products_path的POST请求(用于创建产品),但你的路由配置里并没有定义这个路由——你只添加了get 'products/new'(对应new_product_path),却没有配套的POST路由来处理Products#create。
同时,你的ProductsController里还有个小问题:before_action :set_category会在create方法执行时触发,但非嵌套的创建请求里并没有category_id参数,这会导致set_category报错,而且你用save!会直接抛出异常,不会进入else分支处理表单验证失败的情况。
修复步骤
1. 修正路由配置
替换原来的单独get 'products/new',添加非嵌套的products资源的:new和:create动作,这样Rails会自动生成products_path(POST请求):
# config/routes.rb resources :products, only: [:new, :create] # 替换原来的get 'products/new'... resources :categories, only: [:index, :show, :new, :edit] do resources :products, only: [:index, :show, :edit] end
2. 调整控制器的before_action和create方法
- 把
create方法排除在set_category之外,因为创建产品时我们是通过表单提交的category_id来关联分类,不需要从URL参数获取:
# app/controllers/products_controller.rb before_action :set_category, except: [:new, :create] # 新增:create到排除列表
- 修改
create方法的保存逻辑和跳转路径,同时把save!改成save(save!会在验证失败时抛出异常,无法触发render :new):
def create @product = Product.new(product_params) @product.user = current_user if @product.save # 通过产品关联的category来生成跳转路径,避免依赖@category变量 redirect_to category_product_path(@product.category, @product), notice: "Product has been successfully added to our database" else render :new end end
3. 确认表单逻辑没问题
你的products/new.html.erb里已经通过collection_select让用户选择分类,并且设置了required: true,结合模型里validates :category, presence: true,可以确保产品创建时一定会关联到分类,这部分逻辑是正确的。
额外说明
你完全可以先创建子模型(Product)再关联父模型(Category),只要在创建子模型时传入父模型的ID即可,这也是你当前表单的逻辑,是完全可行的。
内容的提问来源于stack exchange,提问作者Istvanlaz

