Hi Guys
Since I have been a big user of this API but haven't contributed much I thought I share some of the new helpers I have wrote. @rmosolgo happy to create a pull request to added them to documentation if you think these are good, but happy for feedback either way.
I am mostly using Relay these are very much relay centric, also I really don't like declaring my types in my model classes I rather have simple way to extend model class into graphql type
class BaseObject < GraphQL::Schema::Object
implements GraphQL::Relay::Node.interface
global_id_field :id
def self.field(*args, **kwargs, &block)
# Note(hemantv): this is for historical reason GraphqlRuby used not to camelize
# fields
kwargs[:camelize] ||= false
super
end
end
class BaseModelObject < BaseObject
def self.setup(model_name, included_fields)
model = model_name.to_s.classify.constantize
model_fields = model.columns_hash.except('id')
exposed_fields = model_fields.select do |column|
included_fields.include?(column.to_sym) || included_fields.include?(column.to_s)
end
# Make the fields available for this model
exposed_fields.each do |column, type|
field column, convert_type(type), null: true
end
field :errors, [String], null: true,
resolve: ->(obj, _args, _ctx) { obj.errors.full_messages }
field :model_id, Int, null: false,
resolve: ->(obj, _args, _ctx) { obj.id }
end
private
def self.convert_type(database_type)
case database_type.type
when :integer
Int
when :number
Int
when :decimal
Float
when :boolean
Boolean
else
String
end
end
end
example usage
class DemoType < BaseModelObject
setup :demo, %i[name email company_name]
end
btw love the new class-based API 馃挴
That's really cool! Thanks for sharing, I'm happy to see examples like that, where the new API empowers some really creative systems :D
My only suggestion would be to remove the resolve: procs where possible. Sometime in the future, execution may not support that kind of function. Fortunately in this particular case, the refactor is straightforward:
- field :errors, [String], null: true,
- resolve: ->(obj, _args, _ctx) { obj.errors.full_messages }
+ field :errors, [String], null: true
+ # Add a method for implementing this field:
+ define_method(:errors) { object.errors.full_messages)
field :model_id, Int, null: false,
+ method: :id # this will call `object.id`
- resolve: ->(obj, _args, _ctx) { obj.id }
Thanks for sharing these examples! It will be nice to have them here, and if more folks think these would be good to add to the website, I'm open to it. But first, we should see if any other uses emerge after the stable release.
@fameoflight Thanks for sharing, it helps with migration. Any way to disable camelize for arguments?
you might be able to do
def self.argument(*args, **kwargs, &block)
# Note(hemantv): this is for historical reason GraphqlRuby used not to camelize
# fields
kwargs[:camelize] ||= false
super
end
@fameoflight Thanks it works with BaseInputObject.
Still couldn't use it with BaseObject and argument nested within field
class PageQueryType < Types::BaseObject
field :pages, [Page], null: false, resolve: Graph::Resolvers::Pages do
argument :per_page, Integer, default_value: 20, required: false #, camelize: false
end
end
Would that be possible to use such approach to make dynamic resolvers and mutations ?
Most helpful comment
btw love the new class-based API 馃挴