You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails表单多态字段用Signed Global IDs报错:String类无primary_key方法

解决Rails多态关联中使用Signed Global ID时的undefined method 'primary_key' for String:Class错误

错误原因

表单提交时,你给commentable属性传递的是Signed Global ID的字符串,但Rails的多态关联属性需要接收的是模型实例。Rails尝试对字符串调用仅模型类才有的primary_key方法,因此抛出该错误。

解决方案

需要把提交的SGID字符串解析为对应的模型实例后,再赋值给commentable属性,具体步骤如下:

1. 修改CommentsController逻辑

class CommentsController < ApplicationController
  def new
    # 从路由参数中获取要评论的对象(Post或Photo)
    @commentable = Post.find_by(id: params[:post_id]) || Photo.find_by(id: params[:photo_id])
    @comment = Comment.new
  end

  def create
    @comment = Comment.new(comment_params)
    # 解析Signed Global ID为模型实例
    commentable_sgid = params[:comment][:commentable]
    @comment.commentable = GlobalID::Locator.locate_signed(commentable_sgid)

    # 处理SGID解析失败的情况
    if @comment.commentable.nil?
      @comment.errors.add(:commentable, "无效的关联对象")
      render :new
      return
    end

    if @comment.save
      redirect_to @comment.commentable, notice: "评论创建成功"
    else
      render :new
    end
  end

  private

  def comment_params
    # 仅允许评论内容等字段,commentable单独处理
    params.require(:comment).permit(:content)
  end
end

2. 确保表单正确传递Signed Global ID

在评论表单中,通过模型实例的to_signed_global_id方法生成合法的SGID,作为隐藏字段传递:

<%# app/views/comments/new.html.erb %>
<%= form_with model: @comment do |form| %>
  <%# 传递关联对象的Signed Global ID %>
  <%= form.hidden_field :commentable, value: @commentable.to_signed_global_id %>

  <%= form.label :content %>
  <%= form.text_area :content %>

  <%= form.submit "提交评论" %>
<% end %>

3. 配置嵌套路由(可选)

为了更合理地传递关联对象的ID,建议配置嵌套路由:

# config/routes.rb
resources :posts do
  resources :comments, only: [:new, :create]
end

resources :photos do
  resources :comments, only: [:new, :create]
end

关键说明

  • GlobalID::Locator.locate_signed会自动验证SGID的合法性(防止篡改、过期),验证通过则返回对应模型实例,失败则返回nil。
  • Rails 5及以上版本默认支持Signed Global ID功能,无需额外配置。

内容的提问来源于stack exchange,提问作者user29559775

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:43:11