I have a GraphQL enum like:
class MediaFilterType < Types::BaseEnum
value "TWITTER", value: :twitter
value "FACEBOOK", value: :facebook
value "YOUTUBE", value: :youtube
end
And a field that receives an array of this type or nil. Actually when we receive nil, we should pass along that we are going to use all available values in the enum:
def dashboard(media_types: nil)
if media_type.nil?
# Here is the problem below
media_types = MediaFilterType.values.values.map(&:value)
end
...
DashboardQuery.new(media_types).call
end
So I have to do this conditional sanitization for every field just like dashboard field. Not a big deal, except for the duplication. But I think this is a responsibility that should be inside the Query (there is a collaborator that can do that sanitizing inside the Query object). But I think it would be worse to extract the values from the GQL enum type inside a business object. Actually don't even know if I should be extracting these enum values anyway.
Is it good practice to extract values from the GQL type like that?
Appreciate any help.
There is no definitive 'right' answer here. The issue is, graphql-ruby requires a fair bit of duplication in many other cases - think of your models and types. I would not be too scared of a tiny bit of duplication. However...
But I think it would be worse to extract the values from the GQL enum type inside a business object
Depends. If the values are only used within the API and literally nowhere else your implementation is already as good as it gets.
Should I create an Enum with the same values in my business layer?
That is an option. If you forgo documentation for the GraphQL enum types you can get rid of any duplication fairly elegantly. Assuming you add your media filters as enums on some model:
class Dashboard
enum media_types: [:twitter :facebook :youtube]
end
You can then do:
class MediaFilterType < Types::BaseEnum
Dashboard.media_types.each { |media_type| value(media_type.upcase, value: media_type.to_sym)}
end
And for your field:
types = media_types || Dashboard.media_types
DashboardQuery.new(media_types).call
Your model enum now serves as a single source of truth.
However, it is not uncommon that your API diverges a bit from your models with time, so in that case there really isn't a nice way around duplicating at least some things. Just to keep that in mind.