Open14

フロントエンドから今更Rails入門メモ

堀川登喜矢堀川登喜矢

環境構築

環境構築周りはここを参考にdocker上で行った。
フロントはとりあえずNext.jsを使う予定なので、BFF前提でapi modeで環境構築

構成

  • Ruby on Rails - API Mode
  • GraphQL Ruby
  • Apollo
  • Apollo Client
  • GraphQL Codegen
  • Next.js
  • React.js
  • TypeScript
  • ChakraUI

https://qiita.com/Yusuke_Hoirta/items/3a50d066af3bafbb8641
https://railsguides.jp/api_app.html

堀川登喜矢堀川登喜矢

PHPとLaravelでバックエンド書いていた頃にVirtial box系使っていた時と比べて異様に楽な気がする。。。docker周りの知識も補填していかないとな…。

堀川登喜矢堀川登喜矢

本当のフレームワーク初学者の頃と比べると、「やりたいこと」を調べれば何とか実現できるから、「何ができるのか」の脳内インデックス貼り作業って感じだな。

堀川登喜矢堀川登喜矢

RSpecを用いたModelのテスト

アサーション一覧は特に脳内indexを作っておいた方がいい。
Jestのテストで初期でも、「何ができるか」を知るまではテストに予想以上の時間を使っていた。
https://railsguides.jp/testing.html

堀川登喜矢堀川登喜矢

database.ymlで定義したtest用のdatabaseがあるか確認する。

ex: docker containerの中に入って($ docker-compose exec {container} bash
railsのテストを実行

$ rails test test/models/user_test.rb:4

無ければymlファイルでtest用のdatabase部分の定義を修正して、DBを作成してテスト用の環境変数をオプションに付けてマイグレーションを行う。

$ rails db:create
$ bundle exec rails db:migrate RAILS_ENV=test
堀川登喜矢堀川登喜矢

seedにデータ投入

db/seeds.rbに下記のように書くだけ

User.create!(
  [
    { id: 1, name: '平清盛' },
    { id: 2, name: '源頼朝' },
    { id: 3, name: '木曽義仲' },
    { id: 4, name: '後鳥羽上皇' },
  ]
)

データ投入

$ rails db:seed

データ確認

$ rails db
MySQL [db]> SELECT * FROM {table_name}

dbリセット

$ rails db:migrate:reset
堀川登喜矢堀川登喜矢
堀川登喜矢堀川登喜矢

rails g graphql:installでこの様なエラーが出る。

Expected to find a manifest file in `app/assets/config/manifest.js` (Sprockets::Railtie::ManifestNeededError)
But did not, please create this file and use it to link any assets that need
to be rendered by your app:

Example:
  //= link_tree ../images
  //= link_directory ../javascripts .js
  //= link_directory ../stylesheets .css
and restart your server

原因はSprocketsのgemのv4.0.0以降あたりで起こるエラー
また、api modeでrails newすると、app/assets以下が作成されないために発生している。

https://abillyz.com/watanabe/studies/400

今回はエラー内容に従って app/assets/config/manifest.js のディレクトリとファイルを作成して、Example通りの内容を書き込んでもう一度rails g graphql:installを実行すると正常に動作した。

正直jsの構文的にただのコメントなので、この記述の意味が全くわからない。
ただファイルの存在が必要だったっぽいので、Sprocketsのバグなんだと思う。たぶん。

example

app/assets/config/manifest.js
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css

追記: graphql系ファイルの吐き出し先の指定に使うのかも知れない。

堀川登喜矢堀川登喜矢

QueryやTypesの命名を変えるとエラーになってしまう問題の理解ができなかった。

メモ

動いたコード
app/graphql/types/post.rb
# frozen_string_literal: true

class ObjectTypes::Post < Types::BaseObject
  field :id, ID, null: false
  field :title, String
  field :created_at, GraphQL::Types::ISO8601DateTime, null: false
  field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
end
app/graphql/queries/posts.rb
module Queries
  class Posts < Queries::BaseQuery

    type [ObjectTypes::Post], null: false

    def resolve
      ::Post.all.order(:id)
    end
  end
end
app/graphql/types/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

    field :posts, resolver: Queries::Posts
  end
end
書きたかったコード
app/graphql/types/post.rb
# frozen_string_literal: true

module Types
  class PostType < Types::BaseObject
    field :id, ID, null: false
    field :title, String
    field :created_at, GraphQL::Types::ISO8601DateTime, null: false
    field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
  end
end
app/graphql/queries/posts.rb
module Queries
  class PostsQuery < Queries::BaseQuery

    type [Types::PostType], null: false

    def resolve
      ::Post.all.order(:id)
    end
  end
end
app/graphql/types/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

    field :posts, resolver: Queries::PostsQuery
  end
end
堀川登喜矢堀川登喜矢

QueryやTypesの命名を変えるとエラーになってしまう問題の理解ができなかった。

上記の問題は、Railsのクラス名がファイル名に依存していることを失念していたためでした。
あははは〜

堀川登喜矢堀川登喜矢

GraphQL Codegenにて生成した自動hookに置き換える

https://zenn.dev/lilac/books/37bdf5d90b5f9b/viewer/fe48d3

こんな感じに設定ファイルを書いたら実行できる。
もちろん必要なpluginsのinstallは別途必要。

codegen.ts
import type { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: "http://localhost:3000/graphql",
  documents: ["graphql/queries/**/*.graphql"],
  generates: {
    "./graphql/generated/api.ts": {
      plugins: [
        "typescript",
        "typescript-operations",
        "typescript-react-apollo",
      ],
    },
  },
};
export default config;
堀川登喜矢堀川登喜矢

GraphQL Codegenで生成したファイルで重複の型などが発生する(Deplicated type error with graphql codegen and apollo client)

失敗談としては、下記の様にディレクトリを指定してcodegenした時に生成されたファイルで、パット見いい感じに自動生成された型やhooksが重複エラーを出していた。

codegen.ts
import type { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: "http://localhost:3000/graphql",
  documents: ["graphql/queries/**/*.graphql"],
  generates: {
    // ディレクトリ指定だと謎のデフォファイルを沢山生成してくれるけど、重複とかでるのでやめた
    "./graphql/generated": {
      preset: "client",
      plugins: [
        "typescript",
        "typescript-operations",
        "typescript-react-apollo",
      ],
    },
  },
};
export default config;