简体   繁体   English

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

[英]Query string argument should be a String -Rails Action Cable & graphql through apollo

I am using rails 6.1 graphql gem with Apollo to execute a subscription.我将 rails 6.1 graphql gem 与 Apollo 一起使用来执行订阅。 It works for normal queries and mutations but rails complains about subscriptions.它适用于正常查询和突变,但 Rails 抱怨订阅。

In my frontend:在我的前端:

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

GraphQL channel in 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

What happens is that in rails console I get:发生的事情是在 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

I searched for the error which I found in https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/query.rb which, unsurprisingly says that the query is a hash not a string.我搜索了在https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/query.rb中发现的错误,毫不奇怪,查询是 hash 而不是字符串。 I don't really know how that is possible or how I can change this since I use apollos useSubscription hook in my frontend code:我真的不知道这是怎么可能的,也不知道我该如何改变它,因为我在我的前端代码中使用了 apollos useSubscription挂钩:

  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
      }
    }
  }
`;

I found the issue.我发现了问题。 Not sure what the API differences are, but I change the call from不确定 API 的区别是什么,但我将呼叫从

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

to

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

and it works now.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM