Rails中基于两个1:n资源三角关系构建ActiveRecord的new操作问题
Rails关联模型表单实现方案
1. 生成路由辅助方法
首先在config/routes.rb中配置嵌套路由,Rails会自动生成对应的*_path辅助方法:
resources :ps do resources :us do resources :cs, only: [:new, :create, :show] end end
执行rails routes命令可查看完整路由列表,其中你需要的两个核心辅助方法为:
- 新建评论页面:
new_p_u_c_path(@p, @u) - 评论提交路径:
p_u_cs_path(@p, @u)
2. 同时关联三个模型的初始化方案
无需依赖单一关联的build方法,直接在控制器的new动作中初始化Comment时同时绑定Post和User:
# app/controllers/comments_controller.rb def new @p = P.find(params[:p_id]) @u = U.find(params[:u_id]) @c = C.new(post: @p, user: @u) end
这样@c已经完成了与@p、@u的关联,后续保存时会自动写入对应的外键值。
3. form_with配置细节
(1) model:参数关联@P与@U
直接将初始化好的@c传入model参数即可,因为@c已经绑定了对应的Post和User:
<%= form_with model: @c do |form| %> <!-- 评论内容等表单字段 --> <%= form.text_area :content %> <%= form.submit '提交评论' %> <% end %>
(2) url:参数使用创建辅助方法
如果需要显式指定提交路径,直接传入p_u_cs_path(@p, @u)即可:
<%= form_with model: @c, url: p_u_cs_path(@p, @u) do |form| %> <!-- 表单内容 --> <% end %>
实际上,由于@c已经关联了@p和@u,Rails会自动推断出正确的提交路径,所以也可以省略url参数。
(3) 是否需要隐藏字段存储P和U?
不需要额外添加隐藏字段。原因有两点:
- 嵌套路由中已经包含
p_id和u_id,表单提交时这两个参数会通过URL传递到控制器的create动作; - 即使路由中没有携带,只要
@c已经设置了post_id和user_id,form_with会自动生成对应的隐藏字段,但在当前嵌套路由场景下,URL参数已经足够,控制器可直接通过params[:p_id]和params[:u_id]获取值。
控制器的create动作示例:
def create @p = P.find(params[:p_id]) @u = U.find(params[:u_id]) @c = C.new(c_params.merge(post: @p, user: @u)) if @c.save redirect_to @c, notice: '评论创建成功' else render :new end end private def c_params params.require(:c).permit(:content) # 替换为你的Comment实际字段 end
内容的提问来源于stack exchange,提问作者Jon Lawton
相关产品推荐
相关产品推荐

