如何在Docker中使用Rails7 API模式结合MySQL来使用GraphQL

文章的内容 de

开始学习GraphQL时,首先想明白为什么要使用GraphQL。
另外,由于学习过程中遇到了很多我以前从未听说过的词汇,所以我想通过这篇文章来记录笔记。
在这篇文章中,我打算从使用Docker进行环境配置开始,一直到记录user的index、show和create。

GraphQL 是什么?

很快,我发现参考资料非常易懂。介绍了一些使用GraphQL的著名服务,非常有趣。
GraphQL是用于API查询的语言,与REST API不同的是,在REST API中,服务器决定返回的数据结构等,而实际上,在客户端使用数据时可以自由获取数据。
由于如今的智能手机和SPA会处理复杂的数据,GraphQL受到了广泛关注。

优点和缺点

优点

    • フロント側でレスポンスの形式を指定できる

必要なデータのみ取得でき、オーバーフェッチ、アンダーフェッチがなくなる
Swagger等の仕様書が必要なくなる

型があるため堅牢
一度に複数のリソースを取得できる

RESTでいう post/1,post/2のようなリソースを一気に取得できる

缺点

    • 学習コストがかかる

 

    キャッシュが REST よりも複雑になる。N+1問題等に気をつける必要あり。

词汇

    • クエリ言語:Graphqlサーバへの問い合わせ内容を記載した言語

 

    • スキーマ言語: Graphqlサーバでのデータの型を記載した言語

 

    • リゾルバ: 問い合わせを実行するメソッド

 

    • Query: SQLでいうSELECTにあたるもの。データを取得する際に使用

 

    • Mutation: SQLでいうINSERT, UPDATE,DELETE。データを作成、変更削除する際に使用

 

    • field: クラスメソッド。データをDBからもってくる単位

 

    Argument: 検索やデータの呼び出しに使う引数。Queryに渡す引数を指定。

实施

环境构建

1. 准备各种文件

创建以下文件

FROM ruby:3.1.2


RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
EXPOSE 3306

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
version: '3'
services:
  db:
    platform: linux/x86_64  #M1対応
    image: mysql:5.7
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
      MYSQL_USER: root
      MYSQL_PASSWORD: root
    ports:
      - '3306:3306'
    volumes:
      - ./tmp/db:/var/lib/mysql

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - '3000:3000'
    depends_on:
      - db
source 'https://rubygems.org'
gem 'rails', '~>7.0.3'
Gemfile.lock 是空的。
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

2.创建一个新的Rails应用

% docker-compose run --rm web rails new . --force --database=mysql --api

3. 形象构建 ɡtǔ)

% docker-compose build

4. 数据库配置文件database.yml的设置。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db

创建数据库并进行迁移。

% docker-compose run --rm web rails db:create
Creating rails_backend_web_run ... done
Created database 'app_development'
Created database 'app_test'

% docker-compose run --rm web rails db:migration

6. 启动容器

% docker-compose up -d

如果能够在 http://localhost:3000/ 上访问并显示Rails页面,那就没问题。

你还要其他的东西吗?

使用graphql-ruby创建API
使用Rails + GraphQL创建API

准备

GraphQL的安装

gem 'graphql'    #追加
% bundle install
% rails generate graphql:install   #様々なファイルが作成されます

请确认上述命令是否已经记录。

Rails.application.routes.draw do
  post "/graphql", to: "graphql#execute" # rails generate graphql:installで記述されているか確認
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  # root "articles#index"
end

确认行动

安装Altair GraphQL客户端,然后按照下面的请求发送方式发送请求,如果显示Hello World!,则表示成功。

スクリーンショット 2023-01-05 9.16.30.png

模型的构建 de

% rails g model user

class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string      :name
      t.string      :email

      t.timestamps
    end
  end
end

% rails db:migrate

创建型文件

% rails g graphql:object User
   create  app/graphql/types/user_type.rb

执行上述命令后,将会生成以下文件,以与先前创建的模型相匹配。

# frozen_string_literal: true

module Types
  class UserType < Types::BaseObject
    field :id, ID, null: false
    field :name, String
    field :email, String
    field :created_at, GraphQL::Types::ISO8601DateTime, null: false
    field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
  end
end

创建查询

查询:相当于SQL中的SELECT。用于获取数据时使用。

在graphql/type/query_type.rb中写入以下内容。

module Types
  class QueryType < Types::BaseObject
    # Add `node(id: ID!) and `nodes(ids: [ID!]!)`
    include GraphQL::Types::Relay::HasNodeField
    include GraphQL::Types::Relay::HasNodesField

    # Add root-level fields here.
    # They will be entry points for queries on your schema.
    field :users, resolver: Resolvers::QueryTypes::UsersResolver # 追加
    # fieeld: クラスメソッド。データをDBからもってくる単位
    # 追加した記述でリゾルバ(問い合わせを実行するメソッド)を実行
  end
end

请将以下内容在中文中以本地方式翻译,只需一种选择:将以下内容写入 app/graphql/resolvers/query_types/users_resolver.rb 文件。

module Resolvers::QueryTypes
  class UsersResolver < GraphQL::Schema::Resolver
    type [Types::UserType], null: false
    def resolve
      User.all
    end
  end
end

只要结果像图片那样就可以了(请各自创建用户记录)。

スクリーンショット 2023-01-05 10.04.54.png

使用Argument来获取指定用户的数据。

参数:用于搜索和调用数据的参数。指定要传递给查询的参数。

在graphql/type/query_type.rb文件中添加一个字段。

module Types
  class QueryType < Types::BaseObject
    include GraphQL::Types::Relay::HasNodeField
    include GraphQL::Types::Relay::HasNodesField

    # Add root-level fields here.
    # They will be entry points for queries on your schema.
    field :users, resolver: Resolvers::QueryTypes::UsersResolver 
    field :user, resolver: Resolvers::QueryTypes::UserResolver # 追加
    # fieeld: クラスメソッド。データをDBからもってくる単位
    # 追加した記述でリゾルバ(問い合わせを実行するメソッド)を実行
  end
end

创建 app/graphql/resolvers/query_types/users_resolver.rb 文件,并按照以下方式描述。

module Resolvers::QueryTypes
  class UserResolver < GraphQL::Schema::Resolver
    type Types::UserType, null: false
    argument :id, ID, required: false # 引数。
# 型はapp/graphql/resolvers/query_types/users_resolver.rbを参照

    def resolve(id:)
      User.find(id)
    end
  end
end

获取根据以下查询指定的用户ID的用户信息。

query {
  user(id: 1) {
    id
    name
    email
    createdAt #ここに記載したカラムのデータが返ってくる
  }
}
スクリーンショット 2023-01-05 15.00.25.png

另外,如果您想通过名字进行搜索,请进行以下修改。

module Resolvers::QueryTypes
  class UserResolver < GraphQL::Schema::Resolver
    type Types::UserType, null: false
    argument :name, String, required: false # 引数。name
# 型はapp/graphql/resolvers/query_types/users_resolver.rbを参照

    def resolve(name:)
      User.find_by(name: name)
    end  
  end
end

query {
  user(name: "test2") {
    id
    name
    email
    createdAt
  }
}

结果

スクリーンショット 2023-01-05 15.06.40.png

生成变异

变异:在SQL中对应INSERT、UPDATE、DELETE操作。用于创建、修改和删除数据。
首先,我们将实现用户创建。

执行以下命令。

% rails g graphql:mutation CreateUser

将会创建下列文件。

module Types
  class MutationType < Types::BaseObject
    field :create_user, mutation: Mutations::CreateUser
  end
end

将自动生成的 app/graphql/mutations/create_user.rb 文件修改如下:

module Mutations
  class CreateUser < BaseMutation
    graphql_name 'CreateUser'
    field :user, Types::UserType, null: true

    argument :name, String, required: true # 引数
    argument :email, String, required: true # 引数

    def resolve(**args) # **argsに引数がす
      user = User.create!(args)
      {
        user: user
      }
    end
  end
end

执行以下的变异

mutation {
  createUser(
    input:{
      name: "user"
      email: "user@email.com"
    }
  ){
    user {
      id
      name 
      email
    }
  }
}

args的内容如下

[1] pry(#<Mutations::CreateUser>)> args
=> {:name=>"user", :email=>"user@email.com"}

结果 (jié guǒ)

スクリーンショット 2023-01-05 15.41.53.png

结束

我简要总结了从环境搭建到基本功能实现的方法。
我也希望今后能学习graphql-rails的设计。

广告
将在 10 秒后关闭
bannerAds