📚アバター作成
■ おつきあいノート
▽サービス概要
誕生日や贈り物、最後にあった日を振り返れるノート
※具体的内容は別途書く!
▽目的
webアプリ開発のポートフォリオにする
▽作成のルール
・細部にこだわること
・完成までにかけれる時間は2か月
・設計、pjt管理、フロント・バックエンド・DB・インフラ技術について習得すること
・ドキュメントを残すこと
使用技術(予定)
設計
- インフラ構成図
- 画面遷移図
- ER図
PJT管理
- Git Hub
- notion
フロントエンド
- React.js
- Ajax ★
選定理由
最も標準的と感じたから
バックエンド
- Ruby on Rails ★
選定理由
あまたのフレームワークから、募集数が多いこと、比較的扱いが安易なこと、web開発に向いていることを条件に
DB
- MySQL
インフラ
- Heroku ★
- AWS ★
- Docker ★
- 認証系
選定理由
ドキュメントが多いこと、流行りの構成であること
サービス概要
誕生日や贈り物、最後にあった日を振り返れるノート
- Info
- Story
- Tips
Info
- 人ごとに、基本情報やエピソードを記録できる機能
- 名前や記録した情報から特定の個人を検索できる機能
- 五十音順や出会った日、関係性によって並び替える機能
Story
- カレンダー上からエピソードを確認できる機能
Tips
- InfoやStoryで登録した情報を抽出して、会話のネタになりそうな記事やYouTubeをリコメンドする機能
- InfoやStoryで登録した情報を抽出して、おすすめのプレゼントをリコメンドする機能
ワイヤーフレームとして
機能の同士の関連と画面遷移についてしっかり考えたらもう少し追記が必要そうね。。
あと記入項目を具体的に10個増やしてみるのとか、登録画面の図も追加したほうがよいね。
上記のようなレイアウトとかを考えたり、Railsの導入動画を見ている間に圧倒言う間に時間が過ぎていた。
改めて考えてみると、個人情報を書くのがめちゃめちゃ怖いので、とりあえず
人ごとに、基本情報を記録できる機能 に絞って実装してみようと考えている。
イメージとしては、トモダチコレクションみたいな
顔パーツ選択式メモアプリ を作ることだ。
輪郭、目、鼻、口、チーク、眉のパーツを準備して、それぞれのパーツを選択し、位置を調整し、ニックネームとともに保存できるようにしようと思っている。
ざっと考えたER図
- Personに人の情報
- FacePartに各パーツの写真URL
- FacePartSetに人と顔パーツの対応
- FacePartPositionに顔パーツの位置情報
を格納しようと思っている。・
+--------------+ +---------------+ +--------------+ +------------------+
| Person | | FacePart | | FacePartSet | | FacePartPosition |
+--------------+ +---------------+ +--------------+ +------------------+
| id | | id | | id | | id |
| name | | name | | person_id | | face_part_set_id |
+--------------+ | part_type_id | | contour_id | | face_part_id |
+---------------+ | eyes_id | | x_position |
| nose_id | | y_position |
| mouth_id | +------------------+
| cheeks_id |
| eyebrows_id |
+--------------+
初めの一歩
1. Ruby+Devkit 3.3.0-1 (x64) をインストール
ruby -v
ruby 3.3.0
2.Railsインストール
gem install rails -v 7.0.0
3.プロジェクトフォルダ作成
rails new friends --database=postgresql
Git
ローカルのGitリポジトリとGitHubリポジトリを紐付け
git remote add origin <GitHubリポジトリのURL>
変更をステージングする
git add .
変更をコミットする
git commit -m "Commit message"
GitHubにpushする
git push -u origin main
-
rails プロジェクトの作成
rails new friends_ --api --database=postgresql
-
gemファイルが見つからないエラー発生
An error occurred while installing pg (1.5.6), and Bundler cannot continue.
In Gemfile:
pg
run bundle binstubs bundler
Could not find gem 'pg (~> 1.1)' in locally installed gems.
- gemをインストール
gem install pg
- PostgreSQL クライアント ライブラリが見つかりません。エラー
Unable to find PostgreSQL client library.
Please install libpq or postgresql client package like so:
ridk exec sh -c "pacman -S ${MINGW_PACKAGE_PREFIX}-postgresql"
- おまじない
MSYS2/MinGW環境の pacman を使用してPostgreSQLのクライアントライブラリをインストールするため
ridk exec sh -c "pacman -S ${MINGW_PACKAGE_PREFIX}-postgresql"
- 再度gemをインストール
gem install pg
DB作成
Postgreのデータベースを作成するの忘れて沼田↓参考
テーブル作成
person_idとface_part_set_idに外部キー制約を持たせてDBテーブルを作成した。
rails g model FacePart name:string part_type:string url:string
DB
rails db:migrate
Rails console
rails console
-
FacePartモデルのレコードを全て取得する場合:
FacePart.all
-
FacePartモデルの最初のレコードを取得する場合
FacePart.first
-
FacePartモデルの特定の条件を満たすレコードを取得する場合(例えば、nameが"eyes"のレコードを取得する場合):
FacePart.find_by(name: "eyes")
-
データベース内のテーブル一覧を取得
ActiveRecord::Base.connection.tables
-
FacePartテーブルのスキーマ情報を取得する場合
ActiveRecord::Base.connection.columns(:face_parts).map(&:name)
-
FacePartモデルのカラムを確認する場合
FacePart.columns.map(&:name)
-
FacePartモデルのカラムを確認する場合
FacePart.column_names
テーブルの作り替えをおこなった
だいぶシンプルに
以下4つのAPIを作成していく。
・初期画面表示
①パーツ選択画面 全パーツのURL渡すAPI
②アバター画面 デフォルトのデータ渡すAPI
・登録処理
③name,パーツデータの登録 受け取り型API
・個別画面表示
④特定nameのパーツデータ渡すAPI
①パーツ選択画面 全パーツのURL渡すAPI
Railsの復習兼ねて 丁寧に
- Controllerの作成
rails g controller Parts
class PartsController < ApplicationController
# 全パーツのデータを渡す(/parts)
def index
@parts = Part.all
render json: @parts.as_json(only: [:id, :part_type, :url])
end
end
- ルーティングの設定
config/routes.rbに以下を追加
get 'parts', to: 'parts#index'
②アバター画面 デフォルトのデータ渡すAPI
- Part テーブルにデフォルトデータかを判別するフラグを追加
- migrationファイル作成
rails generate migration AddDefaultFlagToParts default_flag:boolean
class AddDefaultFlagToParts < ActiveRecord::Migration[6.0]
def change
add_column :parts, :default_flag, :boolean, default: false
end
end
rails db:migrate
!作成済みのレコードにもdefaultフラグfalseが追加されていた
- 各パーツ1レコードずつ、defalutフラグをtrueに変更した
# rails console
Part.find(1).update(default_flag: true)
- Controller追記
class PartsController < ApplicationController
# 全パーツのデータを渡す(/parts)
・・・
# デフォルトのパーツのデータを渡す(/default_parts)
def default_index
@parts = Part.where(default_flag: true)
render json: @parts.as_json(only: [:id, :part_type, :url])
end
end
- routing設定
get 'default_parts', to: 'parts#default_index'
③名前,パーツデータの登録 受け取り型API
初めに、、わかっていない部分
- トランジション
- ルーティングのところ
コントローラの作成
- ポイントは、module APIやV1でAPIのバージョン管理をしていること
- 同時に2つのテーブルに登録をかけるので、トランザクションを利用していること
- create! のほうを使っていること
# app\controllers\api\v1\registration_controller.rb
module Api
module V1
class RegistrationController < ApplicationController
def register_user_with_part_set
ActiveRecord::Base.transaction do
user = User.create!(user_params)
part_set = user.part_sets.create!(part_set_params)
render json: {user: user,part_set: part_set}, status: :created
end
rescue ActiveRecord::RecordInvalid => e
render json: {error: e.message}, status: :unprocessably_entity
end
private
def user_params
params.require(:user).permit(:name)
end
def part_set_params
params.require(:part_set).permit(:part_id, :x_position, :y_position)
end
end
end
end
ルーティングの設定
- ポイントはよくわからないnamespaceを使っていること
# config\routes.rb
namespace :api do
namespace :v1 do
post 'register_user_with_part_set', to: 'registration#register_user_with_part_set'
end
end
テスト
以下のファイルを実行した
RubyのHTTPクライアントライブラリを使用してAPIを呼び出す方法があります。以下は、Rubyの標準ライブラリであるNet::HTTPを使用する例です。
# test_api.rb
require 'net/http'
require 'json'
uri = URI('http://localhost:3000/api/v1/register_user_with_part_set')
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = {
user: {
name: 'John Doe'
},
part_set: {
part_id: 1,
x_position: 10,
y_position: 20
}
}.to_json
response = http.request(request)
puts response.code
puts response.body
ruby test\test_api.rb
特定nameのパーツデータ渡すAPI
- コントローラの作成
class PartSetsController < ApplicationController
# 特定のnameのPartSetのデータをすべて渡すAPI
def index
user = User.find_by(name: params[:name])
if user
part_sets = user.part_sets
render json: part_sets.as_json(only: [:part_id, :x_position, :y_position])
else
render json: {error: "User not found"}, status: :not_found
end
end
end
- ルーティングの設定
get 'users/:name/part_sets', to: 'part_sets#index'
- テスト
http://localhost/users/John/part_sets でjson取得
Next.js
Nest.jsとは
プロジェクトの作成
- Node.jsのインストール
- Next.jsのインストール
npm install next react react-dom
- Next.jsプロジェクトの作成
npx create-next-app プロジェクト名
- プロジェクトの実行
cd プロジェクト名
npm run dev
画面遷移
画面については3画面用意する。
- 一覧画面 (index.js)
アバターの名前とプレビュー図の一覧を表示する - 編集画面 (edit/[id].js)
プレビュー画面とパーツ選択画面、保存ボタンを表示する - 個別閲覧画面 (view/[id].js)
プレビュー画面と編集ボタン、png出力ボタンを表示する
編集画面
http://localhost:3000/edit/[id]
例)http://localhost:3000/edit/1
利用ライブラリについて
- useRouter Next.js フレームワークで提供されているフックの一つです。Next.js は、Reactベースのサーバーサイドレンダリングやルーティング機能を提供するフレームワーク
- useState 関数コンポーネント内で状態を管理するために使用される。
- AvatarEditor ユーザーのプロフィール写真などのアバターを編集するためのReactコンポーネント
useRouter よくある使い方
ルートのパス名を取得する
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
const currentPath = router.pathname;
return <p>Current path: {currentPath}</p>;
}
クエリパラメータを取得する
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
const query = router.query;
return <p>Query parameter: {query.param}</p>;
}
ページ遷移をおこなう
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
function handleClick() {
router.push('/another-page');
}
return <button onClick={handleClick}>Go to another page</button>;
}
動的なルートパラメータを取得する
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
const { id } = router.query; //router.query オブジェクトから id プロパティの値を取り出し、それを id という変数に代入
return <p>Dynamic parameter: {id}</p>;
}
useState よくある使い方
単一状態の管理
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // 初期値0のcount状態を宣言
return (
<div>
<p>Count: {count}</p> {/* countの値を表示 */}
<button onClick={() => setCount(count + 1)}>Increment</button> {/* ボタンがクリックされた時にcountを1増やす */}
</div>
);
}
複数の状態の管理
import React, { useState } from 'react';
function Form() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
return (
<form>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
</form>
);
}
状態の更新
const [count, setCount] = useState(0); // count状態を宣言
// count状態を更新する
setCount(count + 1);
前の状態を利用して更新
const [count, setCount] = useState(0); // count状態を宣言
// 前の状態を利用してcountを更新する
setCount(prevCount => prevCount + 1);
状態の初期化
const [count, setCount] = useState(() => {
const initialCount = someExpensiveComputation(); // 何らかの計算結果を取得
return initialCount;
});
- コンポーネントが初めてレンダリングされる際にのみ実行される ※APIから値取得する際に重宝
- 結果が初期状態として設定される
AvatarEditor
ユーザーのプロフィール写真などのアバターを編集するためのReactコンポーネント
ユーザーが画像をアップロードし、必要に応じてサイズを調整したり、切り抜いたりするためのツール
主な機能
- ユーザーが画像をアップロードする機能
- 画像をリサイズ・回転する機能
- 画像を切り抜く機能
- 切り抜いた画像をプレビューする機能
- 編集された画像をサーバーに送信して保存する機能