GraphQL-ruby has built-in Scalar types. Scalar types are used when the field or argument resolves the value. In some cases, these scalar types might not fit in our application requirement and that is when custom scalar types come into the picture. One such example is DateTime scalar type.
Problem statement
An application can have various requirement. It may need to display date in string format or need consider timezones or parse different format DateTime string/object, etc. Let’s take the example of DateTime custom scalars used by GitHub. GitHub has custom scalar for millisecond precise DateTime or GitTimestamp
GraphQL-ruby has ISO8601DateTime
and
ISO8601Date
built-in scalars which could be used for
ISO 8601-encoded DateTime and Date.
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :birthday, GraphQL::Types::ISO8601Date, null: false
These scalars can put a limitation when an application has some requirement that cannot be achieved by using built-in scalar types. A simple solution is to write a custom scalar as per our requirement and use it as necessary.
A custom scalar needs
coerce_input
and coerce_result
class methods.
DateTime which when used on GraphQL
argument
calls coerce_input
at runtime
and converts the date string to
DateTime object in the timezone.
Similarly, when a
GraphQL field
uses the custom scalar,
GraphQL calls coerce_result
at
runtime returning the DateTime in
MM/DD/YYYY
format.
# graphql/types/custom_scalars/date_time_type.rb
class Types::CustomScalars::DateTimeType < Types::BaseScalar
description "Formatted DateTime object"
def self.coerce_input(input_value, context)
Time.zone.strptime(input_value, "%m/%d/%Y")
rescue ArgumentError
nil
end
def self.coerce_result(ruby_value, context)
ruby_value.strftime("%m/%d/%Y")
end
end
Similarly, here is the example for Time custom scalar.
# graphql/types/custom_scalars/time_type.rb
class Types::CustomScalars::TimeType < Types::BaseScalar
description "Formatted Time object"
def self.coerce_input(input_value, context)
Time.zone.strptime(input_value, "%H:%M:%S %p")
rescue ArgumentError
nil
end
def self.coerce_result(ruby_value, context)
ruby_value.strftime("%H:%M:%S %p")
end
Happy Coding!!