查询字符串参数应为 String -Rails Action Cable & graphql through apollo



我使用rails 6.1graphqlgem与Apollo执行订阅。它适用于正常的查询和更改,但rails抱怨订阅。

In my frontend:

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

rails中的GraphQL通道

# Channel used by the graphql schema
class GraphqlChannel < ApplicationCable::Channel
rescue_from StandardError, with: :report_error
@op_name
# To be called when a consumer subscribes to the GraphQL channel (ie when a user first opens the application).
def subscribed
# Store all GraphQL subscriptions the consumer is listening for on this channel
@subscription_ids = []
end
# To be called when a subscribed consumer registers for a subscription event on this channel. 
# This will be called once for every event the frontend wants to be notified about.
def execute(data)
query = data['query']
variables = ensure_hash(data['variables'])
@op_name = data['operationName']
operation_name = data['operationName']
puts "Executing #{operation_name}"
# puts "execute sub with query #{query}"
context = {
# Re-implement whatever context methods you need
# in this channel or ApplicationCable::Channel
# current_user: current_user,
# Make sure the channel is in the context
channel: self
# https://medium.com/@jerridan/implementing-graphql-subscriptions-in-rails-and-react-9e05ca8d6b20
# Note that current_application_context has been added to the context object. 
# As I mentioned earlier, the Connection instance will be the parent of the GraphqlChannel instance, 
# so we can get any authorization details that were set in the Connection here.
# current_application_context: connection.current_application_context
}
puts "executing schema query is a #{query.class}"
result = ContentManagementSchema.execute({
query: query,
context: context,
variables: variables,
operation_name: operation_name
})
payload = {
result: result.to_h,
more: result.subscription?
}
puts "result is #{result}"
# Track the subscription here so we can remove it
# on unsubscribe.
@subscription_ids << result.context[:subscription_id] if result.context[:subscription_id]
transmit(payload)
end
# To be called when a consumer unsubscribes from the GraphQL channel (ie when a user closes the application).
def unsubscribed
# Delete all of the consumer's subscriptions from the GraphQL Schema
@subscription_ids.each do |sid|
ContentManagementSchema.subscriptions.delete_subscription(sid)
end
end
private
def report_error(e)
puts "Error in graphql channel: #{e} - Op: #{@op_name}"
end
def ensure_hash(ambiguous_param)
case ambiguous_param
when String
if ambiguous_param.present?
ensure_hash(JSON.parse(ambiguous_param))
else
{}
end
when Hash, ActionController::Parameters
ambiguous_param
when nil
{}
else
raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
end
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

我搜索了我在https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/query.rb中发现的错误,这毫不奇怪地说查询是哈希而不是字符串。我真的不知道这是怎么可能的,或者我怎么能改变这个,因为我使用apollosuseSubscription钩子在我的前端代码:

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

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

我发现了这个问题。不确定API的差异是什么,但我从

更改调用
result = ContentManagementSchema.execute({
query: query,
context: context,
variables: variables,
operation_name: operation_name
})

result = ContentManagementSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
``
and it works now.

最新更新