フロントエンドから今更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
モデル周りの has_one
, has_many
, belongs_to
などはここを見れば分かる
migration周りの外部キー制約はここを参考
RSpecを用いたModelのテスト
アサーション一覧は特に脳内indexを作っておいた方がいい。
Jestのテストで初期でも、「何ができるか」を知るまではテストに予想以上の時間を使っていた。
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
GraphQL RubyとApolloとApollo ClientとGraphQL Code Generator
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
以下が作成されないために発生している。
今回はエラー内容に従って app/assets/config/manifest.js
のディレクトリとファイルを作成して、Example通りの内容を書き込んでもう一度rails g graphql:install
を実行すると正常に動作した。
正直jsの構文的にただのコメントなので、この記述の意味が全くわからない。
ただファイルの存在が必要だったっぽいので、Sprockets
のバグなんだと思う。たぶん。
example
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
追記: graphql系ファイルの吐き出し先の指定に使うのかも知れない。
QueryやTypesの命名を変えるとエラーになってしまう問題の理解ができなかった。
メモ
動いたコード
# 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
module Queries
class Posts < Queries::BaseQuery
type [ObjectTypes::Post], null: false
def resolve
::Post.all.order(:id)
end
end
end
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
書きたかったコード
# 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
module Queries
class PostsQuery < Queries::BaseQuery
type [Types::PostType], null: false
def resolve
::Post.all.order(:id)
end
end
end
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に置き換える
こんな感じに設定ファイルを書いたら実行できる。
もちろん必要なpluginsのinstallは別途必要。
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が重複エラーを出していた。
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;