Generate Dart client code with Rails + apipie

background

This is a continuation of this article.

Display API definition in Swagger UI using Docker \ + Rails6 \ + apipie -Qiita

When I sent the above definition file to a member who develops apps with Dart/Flutter, I was told that "Dart client code cannot be automatically generated".

This time, we will rewrite the apipie settings with the goal of automatically generating Dart client code.

environment

Ruby: 2.7.1
Rails: 6.0.3

What is Flutter/Dart?

A rough summary of Flutter looks like this.

React Native etc. make it easier for people with web experience to get their hands on the app, but Dart seems to make it easier for people with no web experience to get their hands on it.

Also, Dart is an altJS similar to TypeScript. It's basically a language for Flutter, and if you use it as altJS, it seems better to use TypeScript.

cf. What is Flutter? Understand the merits and features of using \ (1/4 ): CodeZine

Adjustment of apipie

Now the mounting surface. I received the following error from the app manager.

E/flutter (17797): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: ApiException 500: Exception during deserialization. (Inner exception: ApiException 500: Could not find a suitable class for deserialization)
E/flutter (17797): 
E/flutter (17797): #0      ApiClient._deserialize (package:openapi/api_client.dart:57:5)
E/flutter (17797): #1      ApiClient._deserialize.<anonymous closure> (package:openapi/api_client.dart:50:43)
E/flutter (17797): #2      MappedIterator.moveNext (dart:_internal/iterable.dart:392:20)
E/flutter (17797): #3      MapBase._fillMapWithIterables (dart:collection/maps.dart:83:39)
E/flutter (17797): #4      new LinkedHashMap.fromIterables (dart:collection/linked_hash_map.dart:127:13)
E/flutter (17797): #5      ApiClient._deserialize (package:openapi/api_client.dart:49:26)
E/flutter (17797): #6      ApiClient.deserialize (package:openapi/api_client.dart:67:12)
E/flutter (17797): #7      UsersApi.postApiV1UsersToken (package:openapi/api/users_api.dart:77:49)

I was inexperienced with Dart, and even if I saw the error, it was a mess, so I asked the person in charge of the application to play with the definition file and make it work.

As a result, we found that the following three are the main causes.

Specify basePath

If api_base_url is blank, a warning will be issued, so add it.

apipie.rb


-  config.api_base_url            = ""
+  config.api_base_url            = "/api"

"additionalProperties": specified as false

additionalProperties seems to be an option to specify" whether to accept properties other than those specified in properties ".

If it is true, properties that are not described in properties are accepted, but if it is false, it seems to be useless.

cf. What is the OpenAPI additional_property option?

It seems that the reason why the error occurred when generating the client code was because it was false.

In apipie, the initial value is false, so let's set it to true.

apipie.rb


+ config.swagger_allow_additional_properties_in_response = true

cf. Swagger-Specific Configuration Parameters

In addition, it seems that an error will occur even if you try to generate it while including all the properties that respond (status, message, etc. that are intentionally returned). (This is unsolved ...)

There is no title in the response

If there is no title in the API definition (swagger.json), the class name seems to be InlineResponse200.

swagger.json


            "schema": {
               "type": "object",
+              "title": "Token",
               "properties": {

Looking at the apipie reference, I couldn't find a description to add title to that part ...

However, there is an implementation similar to Response Description and I tried it and it worked!

api/v1/users_controller.rb



+  def_param_group :user_login_token do
+    property :status, Integer, desc: "status code"
+    property :message, String
+    property :detail, String, desc: "user token"
+  end

 api :POST, "/v1/users/token", "get access token"
  description "Authenticate login and return token"
  formats ["json"]
  param :email, String, desc: "mail address", required: true
  param :password, String, desc: "password", required: true
-  returns code: 200, desc: "return user token"
+  returns :user_login_token, desc: "return user token"
  error code: 401, desc: "Unauthorized."

With the above modifications, you can now generate Dart client code.

Digression: Create Dart client code from your browser

  1. Paste the API definition file into Swagger Editor
  2. Select dart from Generate Client in the header

You can generate client code in this way. If you check the operation like this time, you can do it enough.

Recommended Posts

Generate Dart client code with Rails + apipie
[Grover] Generate PDF with Rails [2020 version]
[Rails] Organize your code neatly with gem active_decorator
Generate Java client code for Salesforce SOAP API
[Ruby] Generate a concatenated QR code with rqrcode (Knowledge)
How to manually generate a JWT with Rails Knock
Write beautiful code with indentation in mind (rails, html)
[Ruby] Generate a concatenated QR code with rqrcode (Practice)
[Rails] Put together the same code with controller actions
Lombok with VS Code
Rails deploy with Docker
[Rails 6] RuntimeError with $ rails s
Handle devise with Rails
[Rails] Learning with Rails tutorial
[Rails] Test with RSpec
[Rails] Development with MySQL
Supports multilingualization with Rails!
Generate JavaScript with Thymeleaf
Double polymorphic with Rails
exited with code 1 error resolution with docker-compose up in rails environment