Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commonize collection field arguments #138

Open
acro5piano opened this issue Jul 2, 2022 · 1 comment
Open

Commonize collection field arguments #138

acro5piano opened this issue Jul 2, 2022 · 1 comment

Comments

@acro5piano
Copy link

acro5piano commented Jul 2, 2022

Hi, first of all, thank you for the great library.

Describe the solution

It is verbose to write every pagination arguments if we have lots of fields. I would like to have less verbose way to do it.

    argument :page, Integer, required: false
    argument :limit, Integer, required: false

Describe the users

Those who are working with lots of types with pagination.

Designs

The feature can be implemented by defining paginated_field like this:

# app/graphql/types/base_object.rb

module Types
  class BaseObject < GraphQL::Schema::Object
    module HasPaginatedField
      def paginated_field(name, type, **kwargs, &block)
        field name, type, **kwargs do
          argument :page, GraphQL::Schema::Member::Int, required: true
          argument :per, GraphQL::Schema::Member::Int, required: false
          instance_eval &block if block_given? # Enable to define additional arguments
        end
      end
    end

    edge_type_class(Types::BaseEdge)
    connection_type_class(Types::BaseConnection)
    field_class Types::BaseField

    extend HasPaginatedField
  end
end

So paginated_field can be used in object type definitions like this:

  field :projects, Types::ProjectType.collection_type do
    argument :where, Types::ProjectWhereInput, required: false
    argument :order, String, required: false
  end
  def projects(page: nil, per: nil)
    Project.page(page).per(per)
  end
@acro5piano
Copy link
Author

acro5piano commented Jul 2, 2022

This implementation is much simpler to use, but less explicit.

# app/graphql/types/base_field.rb
module Types
  class BaseField < GraphQL::Schema::Field
    argument_class Types::BaseArgument

    def initialize(**kwargs, &block)
      super
    
      type = kwargs[:type]
      if type.respond_to?(:graphql_name) && type.graphql_name.end_with?('Collection')
        extension(Types::KaminariExtension)
      end
    end
  end
end

# app/graphql/types/kaminari_extension.rb
module Types
  class KaminariExtension < GraphQL::Schema::FieldExtension
    def apply
      field.argument :page, Integer, required: true, description: 'current page number'
      field.argument :per, Integer, required: true, description: 'current page hoge', prepare: ->(value, _ctx) {
        if value > 100
          raise GraphQL::ExecutionError, "Per page value must be less than 100"
        end
        value
      }
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant