Basic architecture
This section describes the basic architecture of the SOULs serverless Ruby GraphQL API framework.
CRUD file structure in SOULs API
SOULs uses GraphQL Ruby.
Reference Gem: graphql-ruby
In this souls guide, we will explain the API in the red frame in the figure below.
As you progress, you'll end up writing a lot of code for a lot of CRUD.
CRUD is an acronym for Create, Read, Update, and Delete, which are the four basic functions required of software that handles persistent data. ..
There are two CRUD removals mentioned above in the SOULs framework.
The first is logical deletion. It only sets the delete flag, it does not actually delete it. The SOULs framework defines the is_deleted
flag on all tables by default.
The second is physical deletion. Deletes data from the database with the SQL DELETE syntax.
In operating the application, deletion by user's operation occurs frequently.
Create a logical deletion area in advance when sending a deletion transmission from the user client to prevent unintentional data loss.
Below is the layout of the files related to CRUD when the User
motion | GraphQL | file name |
---|---|---|
Read (singular) | Query | apps / api / app / graphql / queries / user.rb |
Read (multiple) | Query | apps / api / app / graphql / queries / users.rb |
Read (condition) | Query | apps / api / app / graphql / resolvers / user_search.rb |
register | Mutation | apps / api / app / graphql / mutations / base / create_user.rb |
update | Mutation | apps / api / app / graphql / mutations / base / update_user.rb |
Logical deletion | Mutation | apps / api / app / graphql / mutations / base / delete_user.rb |
Physical deletion | Mutation | apps / api / app / graphql / mutations / base / destroy_delete_user.rb |
Data registration, update, logical deletion, and physical deletion are defined in mutation/base
Once you have determined the database schema and souls g scaffold
command, it will automatically generate the following files needed to implement GraphQL:
role | File type | File Path |
---|---|---|
GraphQL API | mutation | apps/api/app/graphql/mutations/base/creat_user.rb |
GraphQL API | mutation | apps/api/app/graphql/mutations/base/update_user.rb |
GraphQL API | mutation | apps/api/app/graphql/mutations/base/delete_user.rb |
GraphQL API | mutation | apps/api/app/graphql/mutations/base/destroy_delete_user.rb |
GraphQL API | query | apps/api/app/graphql/queries/user.rb |
GraphQL API | type | apps/api/app/graphql/types/user_type.rb |
GraphQL API | resolver | apps/api/app/graphql/resolvers/user_search.rb |
GraphQL API | connection | apps/api/app/graphql/types/connections/user_connection.rb |
GraphQL API | edge | apps/api/app/graphql/types/edges/user_edge.rb |
RSpec | rspec_mutation | apps/api/spec/mutations/base/user_spec.rb |
RSpec | rspec_query | apps/api/app/spec/queries/user_spec.rb |
RSpec | rspec_factory | apps/api/spec/factories/users.rb |
RSpec | rspec_resolver | apps/api/app/spec/resolvers/user_search_spec.rb |
RBS | mutation rbs | sig/api/apps/api/app/graphql/mutations/base/create_user.rbs |
RBS | mutation rbs | sig/api/apps/api/app/graphql/mutations/base/update_user.rbs |
RBS | mutation rbs | sig/api/apps/api/app/graphql/mutations/base/delete_user.rbs |
RBS | mutation rbs | sig/api/apps/api/app/graphql/mutations/base/destroy_delete_user.rbs |
RBS | query rbs | sig/api/apps/api/app/graphql/queries/users.rbs |
RBS | type rbs | sig/api/apps/api/app/graphql/types/base/user_type.rbs |
RBS | resolver rbs | sig/api/apps/api/app/graphql/resolvers/user_search.rbs |
RBS | connection rbs | sig/api/apps/api/app/graphql/types/connections/user_spec.rbs |
RBS | edge rbs | sig/api/apps/api/app/graphql/types/edges/user_spec.rbs |
Also, from Ruby 3.0, a mechanism called RBS that provides type definition information to the code was introduced.
The SOULs framework for automatically generated files
A type definition template is also automatically generated with a .rbs
extension.
The rbs
files for each service are located under the sig
directory.
Steepfile
is reading the sig
directory.
In the SOULs framework, according to the file created by the souls
command,
The .rbs
and _spec.rb
files are automatically generated.
If you are new to RBS and Steep, we recommend that you read the links below first.
-[RBS] (https://github.com/ruby/rbs) -[Steep] (https://github.com/soutaro/steep)
SOULs API directory structure
The directory structure of SOULs API is as follows.
souls-app/apps/api
directory
souls-app
├── apps
│ ├── api
│ ├── app
│ │ ├── models
│ │ ├── utils
│ │ ├── graphql
│ │ ├── mutations
│ │ ├── queries
│ │ ├── resolvers
│ │ ├── types
│ │ │ ├── base
│ │ │ ├── connections
│ │ │ ├── edges
│ │ │
│ │ ├── s_o_u_ls_api_schema.rb
│ ├── config
│ │ ├── database.yml
│ │ ├── souls.rb
│ │
│ ├── constants
│ ├── db
│ ├── github
│ ├── log
│ ├── spec
│ │ ├── factory
│ │ ├── models
│ │ ├── mutations
│ │ ├── queries
│ │ ├── resolvers
│ │ ├── factory
│ │
│ ├── tmp
│ ├── app.rb
│ ├── Dockerfile
│ ├── Gemfile
│ ├── Gemfile.lock
│ ├── Procfile
There are 4 folders and 1 file in souls-app/apps/api/app/graphql/
mutations
, queries
, resolvers
, types
, and s_o_u_ls_api_schema.rb
These files are working with GraphQL.
Database settings
ORM uses ActiveRecord, so if you've used Rails before, you can continue to use it as usual.
Start Docker container
The SOULs framework uses PostgreSQL, a Docker container, for the development and test environments by default.
Start PostgreSQL container
$ souls docker psql
MySQL users can also use it by modifying config/database.yml
and Gemfile
MySQL container launch
$ souls docker mysql
Model and Migration
Database files are defined in the souls-app/apps/api/models
and souls-app/apps/api/db
souls-app
├── apps
│ ├── api
│ ├── app
│ ├── models
│ │ ├── article_category.rb
│ │ ├── article.rb
│ │ ├── user.rb
│ │
│ ├── db
│ ├── migrate
│ │ ├── 20200006095538_create_users.rb
│ │ ├── 20200712180236_create_article_categories.rb
│ │ ├── 20200714215521_create_articles.rb
│ │
│ ├── schema.rb
│ ├── seeds.rb
Let's take a look at the Migration file that creates the user table.
class CreateUsers < ActiveRecord::Migration[6.1]
def change
create_table :users do |t|
t.string :uid, null: false, unique: true
t.string :username, null: false, default: ""
t.string :screen_name, null: false, default: ""
t.string :last_name, null: false, default: ""
t.string :first_name, null: false, default: ""
t.string :last_name_kanji, null: false, default: ""
t.string :first_name_kanji, null: false, default: ""
t.string :last_name_kana, null: false, default: ""
t.string :first_name_kana, null: false, default: ""
t.string :email, null: false, unique: true
t.string :tel, null: false, default: ""
t.string :icon_url, null: false, default: ""
t.string :birthday, null: false, default: ""
t.string :gender, null: false, default: ""
t.string :lang, null: false, default: "ja"
t.string :category, null: false, default: "user"
t.integer :roles_mask, null: false, default: 1
t.boolean :is_deleted, null: false, default: false
t.timestamps
end
add_index :users, :uid
add_index :users, :screen_name
add_index :users, :email, unique: true
add_index :users, :username
add_index :users, :is_deleted
end
end
Define the type in the Migration file and run Migration.
Run Migration
In the SOULs framework, you can operate the database with the following commands.
Create database
$ souls db create
Run Migration
$ souls db migrate
Create seed data
$ souls db seed
Reset Database
$ souls db migrate_reset
Reset Database and Create seed data
$ souls db reset
When executing in a production environment, specify the --e=production
Database operations in a production environment
Creating a database
$ souls db create --e=production
Run Migration
$ souls db migrate --e=production
Create seed data
$ souls db seed --e=production
Note that these commands allow you to interact directly with the production environment.
Start local server
Start local server
$ souls s
Go to localhost: 4000
If you see a screen like the one below, you're successful!
Launch console
The SOULs framework allows you to use irb in the same environment as your app with the souls c
$ souls c
irb(main):001:0>
Production environment
$ souls c --e=production
irb(main):001:0>
Deploy
Before deploying, let's test again to make sure the app is working properly.
$ souls test
Make sure that all examples are green and have 0 failures. Now, if the test fails, it will also fail during deployment, so make sure the test is clear.
Now let's rename and deploy the github
directory in the mother directory.
From here on, if the deployment is successful, Google Cloud credits will start to be used.
$ cd ...
$ mv github .github
$ git add .
$ git commit -m 'first deploy'
$ git push origin main
Check the delivery status by pressing the Actions tab on the GitHub page.
If build is displayed in green, the deployment is complete.
Let's access the Google Cloud Run endpoint.
The deployment is completed successfully.