Ruby on Rails中如何配置父对象链接跳转对应子对象列表
问题修复方案
你代码中有多处不符合Rails约定和逻辑错误的地方,按优先级逐一修正即可:
1. 路由配置错误
- 嵌套路由
child_objects未开启index权限,且存在语法拼写错误
修正后的routes.rb代码:
root 'parent_objects#index' resources :parent_objects do # 添加index到仅允许的动作列表 resources :child_objects, only: [:index, :create, :destroy] end
2. 模型关联命名错误
has_many关联必须使用复数形式,修正后的模型代码:
class ParentObject < ApplicationRecord belongs_to :someobject # 改为复数child_objects has_many :child_objects end class ChildObject < ApplicationRecord belongs_to :parent_object end
3. 父对象索引页链接错误
你当前使用的parent_object_path是父对象详情页路径,需要改为嵌套的子对象列表路径,同时修正页面中其他复制粘贴错误的变量:
修正后的视图代码:
<h1>Parent Objects</h1> <table> <thead> <tr> <th>Parent object name</th> <th>Parent object description</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @parent_objects.each do |parent_object| %> <tr> <!-- 改为子对象列表的嵌套路由路径 --> <td><%= link_to parent_object.parent_object_name, parent_object_child_objects_path(parent_object) %></td> <td><%= parent_object.description %></td> <td><%= link_to 'Show', parent_object%></td> <!-- 修正错误的todo_list变量为parent_object --> <td><%= link_to 'Edit', edit_parent_object_path(parent_object) %></td> <td><%= link_to 'Destroy', parent_object, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <!-- 修正错误的@todo_lists变量为@parent_objects --> <%= will_paginate @parent_objects %> <br> <!-- 修正错误的new_todo_list_path为对应父对象新建路径 --> <%= link_to 'New Parent Object', new_parent_object_path %>
4. 子对象控制器逻辑错误
- 控制器命名必须为复数
- 区分父对象ID参数
params[:parent_object_id]和子对象ID参数params[:id] - 集合变量统一使用复数命名
修正后的控制器代码:
# 控制器类名改为复数 class ChildObjectsController < ApplicationController # show/edit/update/destroy是单对象操作,index不需要这个前置回调 before_action :set_child_object, only: %i[ show edit update destroy ] # 嵌套路由下所有动作都需要先查询对应的父对象 before_action :set_parent_object, only: %i[ index create destroy ] def index # 直接通过关联获取子对象集合,变量用复数 @child_objects = @parent_object.child_objects end def show end private def set_parent_object # 嵌套路由下父对象ID参数名为parent_object_id @parent_object = ParentObject.find(params[:parent_object_id]) end def set_child_object # 单对象查询用find,参数id是子对象自身的ID @child_object = ChildObject.find(params[:id]) end def child_object_params params.require(:child_object).permit(:name, :description) end end
额外说明
你之前点击链接触发父对象show动作报错的原因是:父对象的show动作未定义对应实例变量,且模板中错误的将子对象集合当作单对象调用name方法,修正链接路径后会直接跳转到子对象的index页面,不会再触发父对象的show动作。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

