最初に
こんにちは!初めまして!!
11日目のカレンダーを担当させていただく佐々木です。
さて、今回は私自身バックエンドを学んだら、その後どうしよう?と考えたところ
フロントエンドもできればかっこよくね??みたいな安直な考えで最初勉強し始めたのですが、
つまずく点が個人的にとても多く、とても苦労したので少しでも参考になればと思います。
ぜひ、Railsを活用して見たいという人に見ていただきたいです。
使うものについてさらっと説明
Ruby on Rails
言わずと知れたスピーディーでweb開発ができる優れもの
https://guides.rubyonrails.org/
React
モダンなフロントエンドのフレームワークの一つです。
hooksめちゃ楽しいです!!
https://ja.reactjs.org/
####GraphQL
RESTapiの代わりになるものという認識です。(間違っていましたら申し訳ありません。)
なんかすごい直感的にかけるイメージ強いです。
https://graphql.org/
ApolloClient
ReactとRailsをつなぐものです。
https://www.apollographql.com/docs/react/api/core/ApolloClient/
完成のファイル
実装
バックエンド編
railsアプリの雛形の作成
早速ターミナルに打ち込んで雛形を作成しましょう。
※今回はAPIモードを使用します
$ rails new demo --api
モデルの作成
早速cd demo
を入力してdemoディレクトリに移動しましょー!
移動できたところで
$ rails g model User name:string age:integer
$ rails g model Book title:string body:text user:references
$ rails db:migrate RAILS_ENV=development
としてUserとBookモデルを作成&反映させていきましょう。
※ referencesについてはこちらが参考になります。
リレーションの定義
モデルの作成ができましたら、Bookモデルの方はreferencesによって自動でリレーションできているので、Userモデルの方のみ設定していきましょう。
class User < ApplicationRecord
# 以下を記述
has_many :books
end
各種gemのインストール
それぞれgemをインストールしていきます。
graphql → GraphQLの開発に必須
graphiql-rails → railsのdevelopment環境でGraphQLの動作確認をできるようにする
faker → ランダムなダミーデータの自動作成
group :development do
gem 'listen', '~> 3.2'
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
# 追加
gem 'graphiql-rails'
gem 'faker'
end
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
# 追加
gem 'graphql'
と記述できたら
$ bundle install
しておきましょう!
GraphQLのインストール
佐伯ほど追加したgraphqlを利用するために
$ rails g graphql:install
とすることでapp
ファイルの直下にgraphql関連のものが追加され
Rails.application.routes.draw do
# 以下の部分が自動で追加されている
post "/graphql", to: "graphql#execute"
end
となります。
また、、以下のコマンドをコマンドをターミナル上で扱うことができるようになります。
Graphql:
graphql:enum
graphql:install
graphql:interface
graphql:loader
graphql:mutation
graphql:object
graphql:scalar
graphql:union
ダミーデータの作成
先ほどインストールしたfakerを利用して
10.times do
user = User.create!(name: Faker::Name.name, age: rand(1..100))
10.times do
user.books.create!(title: Faker::Lorem::sentence(word_count: 5),
body: Faker::Lorem::paragraph(sentence_count: 4))
end
end
として
$ rails db:seed
$ rails c # コンソール画面へ
irb(main):001:0> User.all
10個のUser情報の表示
irb(main):002:0> Book.all
10個のBook情報の表示
irb(main):003:0> exit
と確認することができれば正しくデータが入っているかわかります!
GraphQLのオブジェクトの作成
最初にターミナルにてgraphqlのオブジェクトを作成していきます。
$ rails g graphql:object user
$ rails g graphql:object book
と記述することでapp/graphql/types
直下にオブジェクト名_type.rbが
作成されると思います。
タイプファイルの確認と追加
ここでの型定義はmigrate
ファイルに少し近い記述方法となります。
確認と追加を行いましょう」。
module Types
class UserType < Types::BaseObject
field :id, ID, null: false
field :name, String, null: true
field :age, Integer, null: true
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
# ここから記述
field :books, [Types::BookType], null: false
field :books_object_count, Integer, null: false
# ユーザーに紐づけられたBookオブジェクトの数を数える
def books_object_count
object.books.count
end
end
end
module Types
class BookType < Types::BaseObject
field :id, ID, null: false
field :title, String, null: true
field :body, String, null: true
field :user_id, Integer, null: false
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
end
end
Queryの定義
簡単にQueryの説明をしておくとデータを取得するものという認識で大丈夫だと思います。
※補足としてここの部分の詳細は一つのデータのみを取得するので配列で括らなくで大丈夫です。
module Types
class QueryType < Types::BaseObject
# 全てのデータの取得
field :users, [Types::UserType], null: false
def users
User.all
end
# 引数の番号のデータを取得
field :user, Types::UserType, null: false do
argument :id, ID, required: true
end
def user(id:)
User.find(id)
end
end
end
railsでGraphqlを確認できるようにする
ここまで、できたら実際に確認してみましょう。
実際に``とアクセスしてGraphQLの画面を開けるように
Rails.application.routes.draw do
# ここの部分を記述
if Rails.env.development?
mount GraphiQL::Rails::Engine, at: '/graphiql', graphql_path: "graphql#execute"
end
# 以下の部分が自動で追加されている
post "/graphql", to: "graphql#execute"
end
と記述し
require_relative 'boot'
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_mailbox/engine"
require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
require "sprockets/railtie" # ここの部分のコメントアウトを取る
require "rails/test_unit/railtie"
さらに
app
フォルダの直下にassets/config/manifest.js
を作成し
//= link graphiql/rails/application.css
//= link graphiql/rails/application.js
とすることでdevelopment環境でのみアクセスが可能となります。
データを確認する
ここまでできたら実際にデータを確認してみましょう!
全てのデータ
ここでのデータは
Userは10人(IDは全部で10)
1人のUserに紐づけられている本は10冊なので合計で100冊(IDは全部で100)
となります。
指定されたデータ
フロントエンド編
フロント部分の雛形を作成
では、reactの雛形を作成していきましょう。
今回はcreate-react-app
を使用してお手軽reactアプリケーションを作成します。
$ yarn global add create-react-app #create-react-appコマンドをグローバルで使用できるようにする
$ create-react-app front-demo #雛形を作成
CORSの設定
CORSとはCRUDリクエストをサーバーがフィルター
するものという認識です!
参考サイトとしてこちらをご参照ください
デフォルトでコメント状態となっているのでコメントアウトしてあげましょう!
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors' #コメントアウト
としてbundle install
しましょう!
続いて
# Be sure to restart your server when you modify this file.
# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
# Read more: https://github.com/cyu/rack-cors
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
としましょう。
画面に表示させる
以上のようなものをそれぞれインストールのほどお願いします。
そしてデフォルトで作成されているApp.js
ファイルを
import React from 'react';
import ApolloClient from 'apollo-boost'
import { ApolloProvider } from "@apollo/react-hooks"
import Demo from "./Demo";
const client = new ApolloClient({
uri: 'http://localhost:3000/graphql'
})
const App = () => {
return (
<ApolloProvider client={client} >
<div className="App">
<Demo/>
</div>
</ApolloProvider>
);
}
export default App;
としていき、srcファイル内にDemo.js
というファイルを作成していただき
import React from 'react';
import {useQuery} from '@apollo/react-hooks';
import gql from 'graphql-tag';
const GET_USERS = gql`
{
users{
id
name
age
books{
id
title
body
}
}
}
`;
const Demo = () => {
const {loading, error, data} = useQuery(GET_USERS);
const style = {
color: "red"
};
if (loading) return 'ロード中....';
if (error) return `Error ${error.message}`;
return (
<React.Fragment>
{data.users.map(user => (
<div key={user.id}>
<h1>{user.name}</h1>
<h2>{user.age}</h2>
{user.books.map(book => (
<div key={book.id}>
<h1>{book.title}</h1>
<h2>{book.body}</h2>
</div>
))};
<h1 style={style}>ここまでが{user.id}回目!</h1>
</div>
))}
</React.Fragment>
)
};
export default Demo;
としましょう!
画面で確認する
と表示されれば完璧です!
文字の部分はFakerの文字になるのでランダムです。
以上が実装の一例となります!
ここからさらにGET_USERやユーザーの作成などの拡張ができると思うのでお手隙の際にぜひ試してみてください
記事を見てくださりありがとございました!!!