ruby-on-railsrubygraphqlgraphql-ruby

Ruby graphql resolver alternative: method hooking --- how does it work?


I need to add custom fields to graphql response, so I considered implementing my own custom resolver. However seeing this, I asked myself if I really need a custom resolver:

First, ask yourself ... Do you really need a Resolver? Putting logic in a Resolver has some downsides:

  • Since it's coupled to GraphQL, it's harder to test than a plain ol' Ruby object in your app
  • Since the base class comes from GraphQL-Ruby, it's subject to upstream changes which may require updates in your code

Well, I couldn't agree more. But I don't understand how the following alternative approach works.

Here are a few alternatives to consider:

  • Put display logic (sorting, filtering, etc.) into a plain ol' Ruby class in your app, and test that class
  • Hook up that object with a method, for example:
field :recommended_items, [Types::Item], null: false
def recommended_items
  ItemRecommendation.new(user: context[:viewer]).items
end

Unfortunately, it doesn't seem obvious to me.

I have a Request model that has has_many relationship with Messages.

def Request
   has_many :messages, -> { order(created_at: :desc, id: :desc) }

   def unread_message_count(user)
    return messages.unread(user).count
  end
end

I want to add unread_message_count field to graphql RequestType but I'm lost at:

class RequestType < Types::BaseObject
  field :unread_message_count, Integer, null: false

  def unread_message_count
    user = context[:current_user]
    // here
  end
end

Solution

  • OK, it was easy, you can refer to the actual model in graphql type using Types::BaseObject#object method.

    So in this case, it was:

    class RequestType < Types::BaseObject
      field :unread_message_count, Integer, null: false
    
      def unread_message_count
        user = context[:current_user]
        user.nil? ? 0 : object.unread_message_count(user)
      end
    end