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

Rails应用中PaperTrail无法同时存储控制器与模型级元数据的问题求助

Rails PaperTrail 元数据存储问题:同时保存控制器与模型级元数据

问题场景

在Rails应用中使用PaperTrail时,尝试将控制器级(app_id、org_id)和模型级(acted_user)元数据同时存入versions表,但只有控制器级元数据被成功保存,模型生成的acted_user详情未被存储。已确认PaperTrail.request.controller_info包含正确的:metadata值。

现有配置代码

模型文件(Table类)

class Table < ApplicationRecord
  self.table_name = 'tablename '

  has_paper_trail meta: {
    metadata: lambda { |record|
      user = record.admin_apps_orgs_user.user
      acted_user = {
        id: user.id,
        name: "#{user.given_name} #{user.family_name}",
        email: user.email
      }
      controller_metadata = PaperTrail.request.controller_info.try(:[], :metadata) || {}

      {
        app_id: controller_metadata[:app_id],
        org_id: controller_metadata[:org_id],
        acted_user: acted_user
      }
    }
  }
end

控制器辅助模块

# frozen_string_literal: true

module PapertrailInfoHelper
  extend ActiveSupport::Concern

  def info_for_paper_trail
    {
      metadata: {
        app_id: params[:app_id],
        org_id: params[:org_id]
      }
    }
  end
end

控制器文件

module Api
  module V1
    class MyController < ApplicationController
      include PapertrailInfoHelper

      # Controller actions
    end
  end
end

解决方案

核心问题是模型定义的meta哈希与控制器info_for_paper_trail返回的哈希结构冲突:两者都使用:metadata作为顶级键,导致控制器的:metadata覆盖了模型生成的同名键值。以下两种调整方式均可解决问题:

方法1:直接合并元数据(推荐)

修改模型配置,让模型生成的元数据与控制器元数据直接合并,不再嵌套在:metadata下:

class Table < ApplicationRecord
  self.table_name = 'tablename'

  has_paper_trail meta: lambda { |record|
    # 安全获取关联用户,避免nil报错
    user = record.admin_apps_orgs_user&.user
    return {} unless user

    acted_user = {
      id: user.id,
      name: "#{user.given_name} #{user.family_name}",
      email: user.email
    }
    # 合并控制器传递的元数据
    controller_metadata = PaperTrail.request.controller_info || {}

    controller_metadata.merge(acted_user: acted_user)
  }
end

同时调整控制器辅助模块,直接返回元数据键值对:

module PapertrailInfoHelper
  extend ActiveSupport::Concern

  def info_for_paper_trail
    {
      app_id: params[:app_id],
      org_id: params[:org_id]
    }
  end
end

方法2:保留嵌套结构并手动合并

若需保留:metadata嵌套结构,修改模型中的lambda逻辑,将控制器与模型的元数据合并到同一:metadata键下:

class Table < ApplicationRecord
  self.table_name = 'tablename'

  has_paper_trail meta: {
    metadata: lambda { |record|
      user = record.admin_apps_orgs_user&.user
      return {} unless user

      acted_user = {
        id: user.id,
        name: "#{user.given_name} #{user.family_name}",
        email: user.email
      }
      controller_metadata = PaperTrail.request.controller_info.dig(:metadata) || {}

      # 合并两类元数据
      controller_metadata.merge(acted_user: acted_user)
    }
  }
end

控制器代码可保持不变,最终versions表的meta字段会包含一个:metadata键,其值包含所有目标数据。

验证要点

  • 确保record.admin_apps_orgs_user&.user不会返回nil,避免NoMethodError
  • 执行更新操作后,检查versions表的meta字段,确认app_id、org_id、acted_user均已存入

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:34:54