docs/components/controller.md in graphql_rails-0.8.0 vs docs/components/controller.md in graphql_rails-1.0.0

- old
+ new

@@ -153,26 +153,10 @@ action(:update_password) .permit_input(:input, type: 'User!', subtype: :change_password) end ``` -### *can_return_nil* - -By default it is expected that each controller action returns model or array of models. `nil` is not allowed. You can change that by adding `can_return_nil` like this: - -```ruby -class UsersController < GraphqlRails::Controller - action(:show).permit(:email).can_return_nil - - def show - user = User.find_by(email: params[:email]) - return nil if user.blank? - user - end -end -``` - ### *paginated* You can mark collection action as `paginated`. In this case controller will return relay connection type and it will be possible to return only partial results. No need to do anything on controller side (you should always return full list of items) ```ruby @@ -199,13 +183,33 @@ User.all # it will render 10 users even you have more end end ``` +### *model* + +If you want to define model dynamically, you can use combination of `model` and `returns_list` or `returns_single`. This is especially handy when model is used with `action_default`: + +```ruby +class OrdersController < GraphqlRails::Controller + model('Order') + action(:show).returns_single # returns `Order!` + action(:index).returns_list # returns `[Order!]!` + + def show + Order.first + end + + def index + Order.all + end +end +``` + ### *returns* -By default return type is determined by controller name. When you want to return some custom object, you can specify that with `returns` method: +You must specify what each action will return. This is done with `returns` method: ```ruby class UsersController < GraphqlRails::Controller action(:last_order).permit(:id).returns('Order!') # Order is your model class name @@ -213,10 +217,36 @@ user = User.find(params[:id]).orders.last end end ``` +### *returns_list* + +When you have defined `model` dynamically, you can use `returns_list` to indicate that action must return list without specifying model type for each action. By default list and inner types are required but you can change that with `required_list: false` and `required_inner: false` + +```ruby +class OrdersController < GraphqlRails::Controller + model('Order') + + action(:index).returns_list(required_list: false, required_inner: false) # returns `[Order]` + action(:search).permit(:filter).returns_list # returns `[Order!]!` +end +``` + +### *returns_single* + +When you have defined `model` dynamically, you can use `returns_single` to indicate that action must return single item without specifying model type for each action. By default return type is required, but you can change that by providing `required: false` flag: + +```ruby +class OrdersController < GraphqlRails::Controller + model('Order') + + action(:show).returns_single(required: false) # returns `Order` + action(:update).permit(title: :string!).returns_single # returns `Order!` +end +``` + ### *describe* If you want to improve graphql documentation, you can add description for each action. To do so, use `describe` method: ```ruby @@ -260,10 +290,43 @@ User.create(params) end end ``` +## *model* + +`model` is just a shorter version of `action_default.model`. See `action.model` and `action_default` for more information: + +```ruby +class OrdersController < GraphqlRails::Controller + model('Order') + action(:show).returns_single # returns `Order!` + action(:index).returns_list # returns `[Order!]!` + + def show + Order.first + end + + def index + Order.all + end +end +``` + +## *action_default* + +Sometimes you want to have some shared attributes for all your actions. In order to make this possible you need to use `action_default`. It acts identical to `action` and is "inherited" by all actions defined after `action_default` part: + +```ruby +class UsersController < GraphqlRails::Controller + action_default.permit(token: :string!) + + action(:update).returns('User!') # action(:update) has `permit(token: :string!) + action(:create).returns('User') # action(:create) has `permit(token: :string!) +end +``` + ## *before_action* You can add `before_action` to run some filters before calling your controller action. Here is an example: ```ruby @@ -374,5 +437,99 @@ ``` ## decorating objects See ['Decorating controller responses']('components/decorator') for various options how you can decorate paginated responses + +## Rendering errors + +### Rendering strings as errors + +The simples way to render error is to provide list of error messages, like this: + +```ruby +class UsersController < GraphqlRails::Controller + action(:update).permit(:id, input: 'UserInput!').returns('User!') + + def update + user = User.find(params[:id]) + + if user.update(params[:input]) + user + else + render(errors: ['Something went wrong']) + end + end +end +``` + +### Rendering validation errors + +GraphqlRails controller has `#render` method which you can use to render errors: + +```ruby +class UsersController < GraphqlRails::Controller + action(:update).permit(:id, input: 'UserInput!').returns('User!') + + def update + user = User.find(params[:id]) + + if user.update(params[:input]) + user + else + render(errors: user.errors) + end + end +end +``` + +### Rendering errors with custom data + +When you want to return errors with custom data, you can provide hash like this: + +```ruby +class UsersController < GraphqlRails::Controller + action(:update).permit(:id, input: 'UserInput!').returns('User!') + + def update + user = User.find(params[:id]) + + if user.update(params[:input]) + user + else + render( + errors: [ + { message: 'Something went wrong', code: 500, type: 'fatal' }, + { message: 'Something went wrong', custom_param: true, ... }, + ] + ) + end + end +end +``` + +### Raising custom error classes + +If you want to have customized error classes you need to create errors which inherits from `GraphqlRails::ExecutionError` + +```ruby +class MyCustomError < GraphqlRails::ExecutionError + def to_h + # this part will be rendered in graphl + { something_custom: 'yes' } + end +end + +class UsersController < GraphqlRails::Controller + action(:update).permit(:id, input: 'UserInput!').returns('User!') + + def update + user = User.find(params[:id]) + + if user.update(params[:input]) + user + else + raise MyCustomError, 'ups!' + end + end +end +```