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

Rails7中CurrentAttributes报错:Unsupported argument type (User)求助

问题描述

在Rails 7项目中使用ActiveSupport::CurrentAttributes存储当前用户,具体实现如下:

定义Current类

class Current < ActiveSupport::CurrentAttributes
  attribute :user
end

ApplicationController设置当前用户

class ApplicationController < ActionController::Base
  before_action :set_current_user, if: :user_signed_in?
  private 
  def set_current_user
    Current.user = current_user
  end
end

Room模型中的相关方法

class Room < ApplicationRecord
  def send_partial_counter_and_users_list
    broadcast_update_to('users_in_room_list', target: 
    'users_room_' + self.id.to_s, partial: 
    "rooms/users_in_room", locals: {users_in_room: 
    users_in_room_list })
  end
  def users_in_room_list
      user = User.find_by(Current.user)
      banned_by_me = Ban.where('user_id =?',user.id).pluck(:ban_id)
      users = User.where('id not in (?)',banned_by_me)
      @users = users
      @users
  end
end

视图删除按钮

<% if @single_room %>
   <%= button_to '<i class="fa-solid fa-trash-arrow-up"> 
   </i>'.html_safe, room_path(@single_room.id), :method => 
    :delete%>
<% end %>

执行房间删除(RoomsController#destroy)、消息创建时更新房间状态(如Room.where('id =? and is_private =?',params[:room_id], true).update(:mark_as_closed => false))等操作时,出现以下错误:

ArgumentError in RoomsController#destroy
Unsupported argument type: #User:0x00007fabf9af8168 (User)
Extracted source (around line #28):

def users_in_room_list
    user = User.find_by(Current.user)

但Room模型的定时广播任务(每10秒执行send_partial_counter_and_users_list)运行时无此错误,需要解决该问题。

问题分析

错误核心原因是**User.find_by的使用方式错误**:

  • Current.user已经是完整的User实例对象,而find_by方法需要接收键值对形式的查询条件(如find_by(id: 1)),直接传入整个User对象会触发类型不支持的错误。
  • 定时任务无错误的概率原因:定时任务执行时Current.user未被设置(值为nil),find_by(nil)返回nil,但后续代码若调用user.id本应报错,推测定时任务场景未触发该代码分支,或任务有额外上下文处理。
解决方案

1. 直接使用Current.user,无需重复查询

Current.user已经是当前登录用户的实例,不需要再通过find_by查询,同时增加空值判断避免报错:

def users_in_room_list
  user = Current.user
  # 未登录时返回空集合,避免后续调用user.id报错
  return User.none unless user.present?
  
  banned_by_me = Ban.where(user_id: user.id).pluck(:ban_id)
  users = User.where.not(id: banned_by_me)
  @users = users
end

2. 补充请求上下文清理(可选)

为避免Current属性在请求间泄露,建议在ApplicationController中添加请求结束后的清理操作:

class ApplicationController < ActionController::Base
  before_action :set_current_user, if: :user_signed_in?
  after_action :clear_current_attributes

  private 
  def set_current_user
    Current.user = current_user
  end

  def clear_current_attributes
    Current.reset
  end
end

3. 定时任务的上下文处理(如果需要)

如果定时任务需要正确获取用户上下文,需在任务执行时手动设置Current.user:

class RoomBroadcastJob < ApplicationJob
  def perform(room_id)
    room = Room.find(room_id)
    # 根据任务逻辑设置目标用户,比如指定系统用户或任务关联用户
    Current.user = User.find(some_user_id)
    room.send_partial_counter_and_users_list
    Current.reset # 任务结束后清理上下文
  end
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:27:47