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

Rails Action Cable+GraphQL Apollo订阅报错:查询参数应为字符串

Rails GraphQL订阅报错:Query string argument should be a String, got Hash instead.

问题场景

使用Rails 6.1的graphql gem搭配Apollo实现GraphQL订阅,普通查询、突变功能正常,但触发订阅时后端抛出错误。前端通过ActionCable创建连接并使用ActionCableLink,后端GraphqlChannel的execute方法日志显示query为String类型,却收到报错:「查询字符串参数应为String,实际为Hash」。

相关代码片段

前端ActionCable连接代码

const cable = ActionCable.createConsumer(
  `${process.env.GATSBY_CABLE_URL}/cable?token=${localStorage.getItem('apiToken')}`,
);
const actionCableLink = new ActionCableLink({ cable });

后端GraphqlChannel核心代码

class GraphqlChannel < ApplicationCable::Channel
  def execute(data)
    query = data['query']
    variables = ensure_hash(data['variables'])
    operation_name = data['operationName']
    context = { channel: self }

    # 此处为错误调用方式
    result = ContentManagementSchema.execute({
                                               query: query,
                                               context: context,
                                               variables: variables,
                                               operation_name: operation_name
                                             })
    # ... 后续逻辑
  end

  # ... 其他方法
end

Rails控制台报错

Executing PageComments
9:51:43 AM web.1    |  executing schema query is a String
9:51:43 AM web.1    |  Error in graphql channel: Query string argument should be a String, got Hash instead. - Op: SchedulePublishingStatus
9:51:43 AM web.1    |  Error in graphql channel: Query string argument should be a String, got Hash instead. - Op: PageComments

前端订阅代码

const { loading, error: subscriptionError } = useSubscription(PAGE_COMMENTS, {
    variables: { pageId },
    onSubscriptionData: (res) => {
      setComments(res.subscriptionData.data.pageComments);
    },
  });

GraphQL订阅定义

export const PAGE_COMMENTS = gql`
  subscription PageComments($pageId: ID) {
    pageComments(pageId: $pageId) {
      id
      body
      createdAt
      user {
        id
        email
      }
    }
  }
`;

问题原因

报错的核心是**ContentManagementSchema.execute的调用方式错误**:Rails graphql gem的execute方法要求第一个参数为String类型的查询字符串,后续参数为可选的关键字参数(如context、variables等)。当前代码把所有参数打包成一个Hash传入,导致gem将整个Hash识别为query参数,从而触发类型不匹配错误。

修复方案

修改GraphqlChannel#execute方法中调用execute的代码,将参数拆分为单独的查询字符串和关键字参数:

方案一:直接传递位置参数+关键字参数

result = ContentManagementSchema.execute(
  query,
  context: context,
  variables: variables,
  operation_name: operation_name
)

方案二:使用关键字参数展开(适用于参数较多的场景)

execute_params = {
  query: query,
  context: context,
  variables: variables,
  operation_name: operation_name
}
result = ContentManagementSchema.execute(**execute_params)

验证

修改后重启Rails服务,触发订阅请求,后端将正确解析String类型的query参数,不再抛出类型不匹配的错误,订阅功能可正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:05:35