🔖

ActiveModelSerializersを利用しているRailsプロジェクトでgraphql-rubyを導入・共存させる

2022/07/07に公開

ActiveModelSerializersを利用してAPIのレスポンスを構築しているRailsプロジェクトで、一部のAPIでGraphQLを利用することになり、導入を進めていました。

rails g graphql:install で生成されたコントローラーに対してリクエストを送ると、以下のようなエラーが発生していました。

graphiqlでのリクエスト結果

エラーログ
     Failure/Error: render json: result
     
     NoMethodError:
       undefined method `model_name' for NilClass:Class
       Did you mean?  module_parent
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model/serializer.rb:388:in `json_key'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model/serializer.rb:370:in `serializable_hash'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/adapter/attributes.rb:14:in `serializable_hash'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/adapter/base.rb:61:in `as_json'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/serializable_resource.rb:10:in `to_json'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:71:in `block (3 levels) in notify'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:24:in `block (3 levels) in instrument_rendering'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:81:in `block in notify_render'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:80:in `notify_render'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:23:in `block (2 levels) in instrument_rendering'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:97:in `block in tag_logger'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:97:in `tag_logger'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:22:in `block in instrument_rendering'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/active_model_serializers/logging.rb:70:in `block (2 levels) in notify'
     # /usr/local/bundle/gems/active_model_serializers-0.10.13/lib/action_controller/serialization.rb:72:in `block (2 levels) in <module:Serialization>'
     # ./app/controllers/admin/api/v1/graphql_controller.rb:19:in `execute'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/deflater.rb:44:in `call'
     # /usr/local/bundle/gems/warden-1.2.9/lib/warden/manager.rb:36:in `block in call'
     # /usr/local/bundle/gems/warden-1.2.9/lib/warden/manager.rb:34:in `catch'
     # /usr/local/bundle/gems/warden-1.2.9/lib/warden/manager.rb:34:in `call'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/tempfile_reaper.rb:15:in `call'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/etag.rb:27:in `call'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/conditional_get.rb:40:in `call'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/head.rb:12:in `call'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/session/abstract/id.rb:266:in `context'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/session/abstract/id.rb:260:in `call'
     # /usr/local/bundle/gems/sentry-rails-5.3.1/lib/sentry/rails/rescued_exception_interceptor.rb:12:in `call'
     # /usr/local/bundle/gems/sentry-ruby-core-5.3.1/lib/sentry/rack/capture_exceptions.rb:26:in `block (2 levels) in call'
     # /usr/local/bundle/gems/sentry-ruby-core-5.3.1/lib/sentry/hub.rb:199:in `with_session_tracking'
     # /usr/local/bundle/gems/sentry-ruby-core-5.3.1/lib/sentry-ruby.rb:351:in `with_session_tracking'
     # /usr/local/bundle/gems/sentry-ruby-core-5.3.1/lib/sentry/rack/capture_exceptions.rb:17:in `block in call'
     # /usr/local/bundle/gems/sentry-ruby-core-5.3.1/lib/sentry/hub.rb:59:in `with_scope'
     # /usr/local/bundle/gems/sentry-ruby-core-5.3.1/lib/sentry-ruby.rb:331:in `with_scope'
     # /usr/local/bundle/gems/sentry-ruby-core-5.3.1/lib/sentry/rack/capture_exceptions.rb:16:in `call'
     # /usr/local/bundle/gems/rack-dev-mark-0.7.9/lib/rack/dev-mark/middleware.rb:19:in `call'
     # /usr/local/bundle/gems/railties-6.1.6/lib/rails/rack/logger.rb:37:in `call_app'
     # /usr/local/bundle/gems/railties-6.1.6/lib/rails/rack/logger.rb:26:in `block in call'
     # /usr/local/bundle/gems/railties-6.1.6/lib/rails/rack/logger.rb:26:in `call'
     # /usr/local/bundle/gems/request_store-1.5.1/lib/request_store/middleware.rb:19:in `call'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/method_override.rb:24:in `call'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/runtime.rb:22:in `call'
     # /usr/local/bundle/gems/rack-2.2.3.1/lib/rack/sendfile.rb:110:in `call'
     # /usr/local/bundle/gems/rack-cors-1.1.1/lib/rack/cors.rb:100:in `call'
     # /usr/local/bundle/gems/secure_headers-6.3.3/lib/secure_headers/middleware.rb:11:in `call'
     # /usr/local/bundle/gems/railties-6.1.6/lib/rails/engine.rb:539:in `call'
     # /usr/local/bundle/gems/rack-test-1.1.0/lib/rack/mock_session.rb:29:in `request'
     # /usr/local/bundle/gems/rack-test-1.1.0/lib/rack/test.rb:266:in `process_request'
     # /usr/local/bundle/gems/rack-test-1.1.0/lib/rack/test.rb:119:in `request'
     # ./spec/requests/admin/api/v1/graphql_spec.rb:10:in `block (3 levels) in <top (required)>'
     # ./spec/requests/admin/api/v1/graphql_spec.rb:29:in `block (5 levels) in <top (required)>'

ActiveModelSerializersがjsonのレンダリングをしようとしているように見えます。
MySchema.execute() の返り値のHashを、そのままJSONとして返却できるようにする必要があります。

解決策

以下のように設定することで解決できました。

+ render json: result, adapter: nil
- render json: result

参考情報

https://stackoverflow.com/questions/20101179/how-to-disable-activemodelserializers-for-a-specific-controller
https://github.com/rails-api/active_model_serializers/issues/2221

GitHubで編集を提案

Discussion