🙆♀️
【frourio】Railsとfrourioの比較(Scaffoldingとcreate-frourio-app)
まとめと感想
全体的にRailsはcontroller~modelの責務が大きかったのに対して、
frourioの方が細かく分離されている印象。
リクエストpath
Rails
routes.rbに記載
config/routes.rb
Rails.application.routes.draw do
resources :users
# get '/users', to: 'users#index'
# get '/users/new', to: 'users#new'
# post '/users', to: 'users#create'
# get '/users/:id', to: 'users#show'
# get '/users/:id/edit', to: 'users#edit'
# patch '/users/id', to: 'users#update'
# delete '/users/:id', to: 'users#destroy'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
frourio
ファイルpathとindex.tsで表現
ファイルpath
server
└──api
└──tasks
├── $relay.ts
├── _taskId@number
│ ├── $relay.ts
│ ├── controller.ts
│ └── index.ts
├── controller.ts
└── index.ts
server/api/tasks/index.ts
import type { Task } from '$prisma/client'
export type Methods = {
get: {
query?: {
limit?: number
message?: string
}
resBody: Task[]
}
post: {
reqBody: Pick<Task, 'label'>
resBody: Task
}
}
処理の振り分け
Rails
controllerで行う
app/controllers/users_controller.rb
class UsersController < ApplicationController
before_action :set_user, only: %i[ show edit update destroy ]
# GET /users or /users.json
def index
@users = User.all
end
# GET /users/1 or /users/1.json
def show
end
# GET /users/new
def new
@user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users or /users.json
def create
@user = User.new(user_params)
respond_to do |format|
if @user.save
format.html { redirect_to user_url(@user), notice: "User was successfully created." }
format.json { render :show, status: :created, location: @user }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1 or /users/1.json
def update
respond_to do |format|
if @user.update(user_params)
format.html { redirect_to user_url(@user), notice: "User was successfully updated." }
format.json { render :show, status: :ok, location: @user }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1 or /users/1.json
def destroy
@user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: "User was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Only allow a list of trusted parameters through.
def user_params
params.require(:user).permit(:name, :age)
end
end
frourio
controllerで行う
server/api/tasks/controller.ts
import { defineController } from './$relay'
import { getTasks, createTask } from '$/service/tasks'
const print = (text: string) => console.log(text)
export default defineController({ getTasks, print }, ({ getTasks, print }) => ({
get: async ({ query }) => {
if (query?.message) print(query.message)
return { status: 200, body: await getTasks(query?.limit) }
},
post: async ({ body }) => ({
status: 201,
body: await createTask(body.label)
})
}))
DB接続周り
Rails
app/models/user.rb
class User < ApplicationRecord
end
frourio
処理を実行する純粋な関数だけserviceに残して、DB操作は別ディレクトリに分けても良い。
server/service/tasks.ts
import { depend } from 'velona'
import { PrismaClient } from '@prisma/client'
import type { Task, Prisma } from '$prisma/client'
const prisma = new PrismaClient()
export const getTasks = depend(
{ prisma: prisma as { task: { findMany(): Promise<Task[]> } } },
async ({ prisma }, limit?: number) =>
(await prisma.task.findMany()).slice(0, limit)
)
export const createTask = (label: Task['label']) =>
prisma.task.create({ data: { label } })
export const updateTask = (
id: Task['id'],
partialTask: Prisma.TaskUpdateInput
) => prisma.task.update({ where: { id }, data: partialTask })
export const deleteTask = (id: Task['id']) =>
prisma.task.delete({ where: { id } })
Discussion