【山竹记账后端】1.搭建后端项目
从无到有创建
Rails API
大纲链接 §
toc
1. 初始化目录 [⇧](#1. 初始化目录 ⇧ "#catalogue")
前提:已经创建好
oh-my-env的容器环境,打开容器项目
- 已预装
ruby@3.0.0p0或者rvm use 3.1.2 - 已预装
gem@3.2.3 - 已预装
bundle@2.5.23 - 已预装
rvm@1.29.12
还需要配置安装的:
gem和bundle的源未配置国内镜像rails未安装postgresql未安装
命令行步骤
- 在
VSCode中启动oh-my-env的容器环境 - 无需重新
build
zsh
# 更换gem国内源
gem sources --add https://mirrors.tuna.tsinghua.edu.cn/rubygems/ --remove https://gems.ruby-china.com/
# 更换bundle国内源
bundle config set --global mirror.https://rubygems.org https://mirrors.tuna.tsinghua.edu.cn/rubygems
# 安装rails,版本尽量和我的一致,会有日志,等待时间较长
gem install rails -v 7.2.3.2
# 在 docker 镜像的 linux 中安装 postgresql 驱动;
# 已在 `Dockerfile` 内置命令 `RUN pacman -S postgresql-lib`,可省略
pacman -S postgresql-libs
# 创建rails项目;只是用 api 模式;数据库 使用 postgresql;跳过自带测试(之后使用第三方测试);
cd ~/repos
rails new --api --database=postgresql --skip-test mangosteen-1
# 使用 VSCode 打开在容器中项目
code mangosteen-1 # code ~/repos/mangosteen-1
# 新建一个zsh终端后,启动rails服务;需要关闭server 请按Ctrl+C
bundle exec rails server
- 如果报错
gem:14: command not found: gem,需要切一下版本rvm use 3或者rvm use 3.1.2 - 安装rails,版本尽量和我的一致
rails -v 7.2.3.2,更新到稳定版 rails new --api --database=postgresql --skip-test mangosteen-1参数解释rails new创建框架新项目--api只是用 api 模式--database=postgresql指定使用 PostgreSQL 数据库--skip-test跳过自带测试(之后使用第三方测试)mangosteen-1创建的项目目录名称
rails new创建项目还需要安装另外的依赖,需要等待时间较长- 提示运行
bundle binstubs bundler前,需要先进入项目目录cd mangosteen-1 - 进入后可以看到已经创建了一堆项目文件,已经
git init,但还没有提交
- 提示运行
rails api模式下的目录

- 使用
code .在当前目录中打开容器项目,由于全局环境和项目环境会有不一致,需要保证在项目中运行 - 启动rails服务
bundle exec rails server或者bundle exe rails server- 可以简写为
bundle exec rails s - 也可以简写为
bin/rails s - 不推荐
rails s,因为全局环境和项目环境软件版本可能不一致- 项目中的
rails版本在Gemfile中指定gem "rails", "~> 7.2.3", ">= 7.2.3.2"
- 项目中的
- 可以简写为
- 启动后可以看到终端
=> Booting PumaMin threads:5最小进程数Max threads:5最大进程数Environment:development默认环境为开发环境Listening on http://127.0.0.1:3000默认监听端口 3000,自动转发到主机系统中
- 直接访问
http://127.0.0.1:3000会看到报错ActiveRecord::ConnectionNotEstablished- 这是因为数据库没有启动,需要先启动数据库,定位报错信息
PGSQL.5432,需要执行docker命令来启动数据库
- 这是因为数据库没有启动,需要先启动数据库,定位报错信息
国内源 [⇧](#国内源 ⇧ "#catalogue")
- 清华镜像
https://mirrors.tuna.tsinghua.edu.cn/rubygems/ - 南阳镜像
https://mirror.nyist.edu.cn/rubygems/
zsh
# 移除已失效的 Ruby China 源和官方源
gem sources --remove https://gems.ruby-china.com/
gem sources --remove https://rubygems.org/
# 添加全新可用的国内源
# 中国科学技术大学 (USTC) 源
gem sources -a https://mirrors.ustc.edu.cn/rubygems/
# 清华大学 (TUNA) 源
gem sources -a https://mirrors.tuna.tsinghua.edu.cn/rubygems/
# 官方源
gem sources -a https://rubygems.org/rubygems/
# 验证当前源
gem sources -l
2. 启动数据库镜像 [⇧](#2. 启动数据库镜像 ⇧ "#catalogue")
zsh
docker run -d --name db-for-mangosteen -e POSTGRES_USER=mangosteen -e POSTGRES_PASSWORD=123456 -e POSTGRES_DB=mangosteen_dev -e PGDATA=/var/lib/postgresql/data/pgdata -v mangosteen-data:/var/lib/postgresql/data -p 5432:5432 --network=network1 postgres:14
- 命令不可折行,会有bug,以下为参数说明
docker run -d启动一个新容器,-d后台保持运行--name db-for-mangosteen命名该容器的名称e POSTGRES_USER=mangosteen环境变量:用户名e POSTGRES_PASSWORD=123456环境变量:密码e POSTGRES_DB=mangosteen_dev环境变量:数据库名称- 以区分测试环境
mangosteen_test和生产环境mangosteen_production的数据库
- 以区分测试环境
e PGDATA=/var/lib/postgresql/data/pgdata环境变量:PostgreSQL 数据目录,官方指定v mangosteen-data:/var/lib/postgresql/data挂载数据卷,将主机上的数据挂载到容器中- 自动创建并持久化数据卷,容器重启后数据不会丢失
-p 5432:5432指定端口映射,将容器的5432端口映射到主机的5432端口,可选,使用VSCode时可不用--network=network1指定网络,可以通过db-for-mangosteen这个名称来访问网络- 前提是之前已在在命令行运行
docker network create network1创建网络
- 前提是之前已在在命令行运行
postgres:14镜像名称与版本号
- 这行命令需要在
windows(docker的外部)系统中运行 - 命令运行后会返回一串哈希,说明数据库已经启动
- 此时在
docker desktop中可以看到数据库容器正在运行 - 可以通过
docker ps查看数据库容器是否启动
3. 配置项目开发数据库,并运行命令连接 [⇧](#3. 配置项目开发数据库,并运行命令连接 ⇧ "#catalogue")
修改 config/database.yml 配置开发数据库 [⇧](#修改 config/database.yml 配置开发数据库 ⇧ "#catalogue")
yaml
development:
# noinspection YAMLUnresolvedAlias
<<: *default
database: mangosteen_dev
username: mangosteen
password: 123456
host: db-for-mangosteen
- 数据库名称
database: mangosteen_dev - 用户名
username: mangosteen - 密码
password: 123456 - 主机名
host: db-for-mangosteen,理论上应填写一个ip或域名,这里填写的是容器名称- 这是之前运行容器的参数
docker run -d --name db-for-mangosteen ...
- 这是之前运行容器的参数
运行 sever [⇧](#运行 sever ⇧ "#catalogue")
- 此时需要按
Ctrl+C先断开之前的服务,重新启动bin/rails s
看到以下界面说明已经成功启动服务

对于一个熟练的
ruby程序员来说,主要步骤就三步
- 创建目录
- 启动数据库
- 配置数据库,刷新
记得及时提交代码
4. rails 项目的选择 [⇧](#4. rails 项目的选择 ⇧ "#catalogue")
- 创建时使用
api模式 - 数据库 使用
postgresql - 跳过自带测试(之后使用第三方测试)
rails的理念:约定大于配置,即直接给到最佳实践
5. 实现一个后台功能 [⇧](#5. 实现一个后台功能 ⇧ "#catalogue")
简单实现一个后台功能,看看完整过程时怎样的
设计数据库 [⇧](#设计数据库 ⇧ "#catalogue")
山竹记账需要哪些数据?
设计数据库的两种思路 [⇧](#设计数据库的两种思路 ⇧ "#catalogue")
- 自上而下:现想大概,再添加细节
- 大概有哪些表,有那些数据字段
- 自下而上:用到什么加什么,会出现打脸的情况
- 两种思路可以混合,我们先采用 自下而上
rsils提供的设计数据库工具 [⇧](#rsils提供的设计数据库工具 ⇧ "#catalogue")
- 建模工具:
bin/rails g model user email:string name:stringg代表generate会自动生成 模型类 和 迁移文件- 模型类:
app/models/user.rb文件 - 迁移文件:
db/migrate/YYYYMMDD_create_users.rb文件YYYYMMDD为当前日期,用于区分不同的迁移文件- 需要自行填充
change方法的逻辑
- 数据库操作工具:
ActiveRecord::Migration- 同步到数据库:
bin/rails db:migrate - 反悔命令:
bin/rails db:rollback step=1step=1表示回滚最近一次迁移
- 同步到数据库:
rsils创建新建数据库代码 [⇧](#rsils创建新建数据库代码 ⇧ "#catalogue")
在进行数据库相关操作前,确保当前代码都已提交
ruby
bin/rails g model user email:string name:string
# invoke active_record
# create db/migrate/20260906082930_create_users.rb
# create app/models/user.rb
查看
app/models/user.rb
ruby
class User < ApplicationRecord
end
查看
db/migrate/20260906082930_create_users.rb
ruby
class CreateUsers < ActiveRecord::Migration[7.2]
def change
create_table :users do |t|
t.string :email, limit: 100
t.string :name
t.timestamps
end
end
end
- 声明类
class CreateUsers < ActiveRecord::Migration[7.2]Migration[7.2]表示使用 rails 7.2 版本的迁移类
def change代表对数据库做的变动create_table :users do |t|接受两个参数- 第一个参数
:users创建一个名为users的表 - 第二个参数为一个函数
do |t| ... end,用于定义表的字段t.string :email添加一个字符串类型的email字段t.string :name添加一个字符串类型的name字段t.timestamps会自动添加created_at和updated_at字段,用于记录创建时间和更新时间
- 类似于
js代码createTable('users', (api) => {api.string('email', {limit: 100})})
参考
- 搜索 rails create_table example
- 查找关键字
create_tablelimit
- 查找关键字
目前并没有直接变更数据库,只是把将要变更的写到代码中,需要运行
bin/rails db:migrate才会变更数据库。
rsils第一次迁移数据库 [⇧](#rsils第一次迁移数据库 ⇧ "#catalogue")
运行
bin/rails db:migrate后,数据库会自动创建users表
ruby
bin/rails db:migrate
# == 20260906082930 CreateUsers: migrating ======================================
# -- create_table(:users)
# -> 0.0393s
# == 20260906082930 CreateUsers: migrated (0.0394s) =============================
rsils反悔迁移数据库 [⇧](#rsils反悔迁移数据库 ⇧ "#catalogue")
运行
bin/rails db:rollback可以回滚最近一次迁移 运行bin/rails db:rollback step=1可以回滚指定步数的迁移
ruby
bin/rails db:rollback
# == 20260906082930 CreateUsers: reverting ======================================
# -- drop_table(:users)
# -> 0.0076s
# == 20260906082930 CreateUsers: reverted (0.0138s) =============================
- 智能自动识别之前
create_table的反操作为drop_table删除 - 其他后端框架做不到自识别
create_table的反操作为drop_table
这样就可以随时对数据库进行操作,增删字段、迁移数据库、反悔操作
6. 创建路由 [⇧](#6. 创建路由 ⇧ "#catalogue")
手动添加路由(原始) [⇧](#手动添加路由(原始) ⇧ "#catalogue")
config/routes.rb
ruby
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
post '/users', to: 'users#create'
get '/users/:id', to: 'users#show'
end
- 相当于
js中类似代码,post('/users', {to: 'users#create'}) ruby但更简洁,少了括号的杂音post '/users', to: 'users#create'to: 'users#create'表示将 POST 请求路由到UsersController的create方法to: 'users#show'表示将 GET 请求路由到UsersController的show方法
目前还未实现
create和show这两个方法,继续实现前别忘记提交代码
7.创建 Controller [⇧](#7.创建 Controller ⇧ "#catalogue")
实现
create和show这两个方法
- 脚手架
bin/rails g controller users create show - 输出
JSON视图render json: user
zsh
bin/rails g controller users create show
# create app/controllers/users_controller.rb
# route get "users/create"
# get "users/show"
- 注意
users不要写错成user,复数形式很重要- 确保文件名为
app/controllers/users_controller.rb - 确保的该文件中的类名为
UsersController - 如果错误发起请求时会报错
ActionController::RoutingError (uninitialized constant UsersController Did you mean?UserController):
- 确保文件名为
- 自动创建了
app/controllers/users_controller.rb文件 - 运行命令后,在
config/routes.rb中自动添加了路由get "users/create"和get "users/show"- 不够精确,可删除,使用手动添加的
app/controllers/users_controller.rb
ruby
class UsersController < ApplicationController
def create
p "你访问了 create"
end
def show
p "你访问了 show"
end
end
- 添加打印日志,验证当用户访问这两个接口时,确实走了这两个方法的逻辑
- 先确保服务已经启动
bin/rails s - 另外打开一个终端,拆分到右侧,使用
curl命令访问api接口,成功运行,可以在puma控制台看到输出- 搜索 google curl post educative
curl -X POST http://127.0.0.1:3000/userscurl -X GET http://127.0.0.1:3000/users/1
- 正确发起请求后,查看控制台打印
config/routes.rb
ruby
Rails.application.routes.draw do
# get "user/create"
# get "user/show"
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
post '/users', to: 'users#create'
get '/users/:id', to: 'users#show'
end
调试填充功能逻辑
app/controllers/users_controller.rb
ruby
class UsersController < ApplicationController
def create
user = User.new email: 'frank@x.com', name: 'frank'
if user.save
p 'save 成功了'
else
p 'save 失败了'
end
end
def show
p "你访问了 show"
end
end
- 使用
User.new创建一个对象 - 使用
user.save保存对象,if user.save返回一个布尔值,根据结果打印日志
安装
VSCode插件查看数据库,验证是否成功创建表
PostgreSQL- 点击
+连接 - 输入
hostname为db-formangosteen - 输入用户名
mangosteen - 输入密码
123456 - 输入端口
5432 - 点选
Standart Conection - 点选 数据库
mangosteen_dev
- 点击
- 查看数据库中该表的字段

渲染信息 [⇧](#渲染信息 ⇧ "#catalogue")
app/controllers/users_controller.rb
ruby
class UsersController < ApplicationController
def create
user = User.new email: "frank@x.com", name: "frank"
if user.save
render json: user
else
render json: user.errors
end
end
def show
end
end
- 直接使用
render json: user渲染用户信息- 这句代码相当于
js中render({json: user.errors})
- 这句代码相当于
- 使用
curl -X POST http://127.0.0.1:3000/users添加一个用户,查看后台打印信息
添加字段验证 [⇧](#添加字段验证 ⇧ "#catalogue")
app/models/user.rb
ruby
class User < ApplicationRecord
validates :email, presence: true
end
- 搜索 google rails validations
- 添加验证
email字段为必须validates :email, presence: true
app/controllers/users_controller.rb尝试修改 不写
ruby
def create
user = User.new name: "frank"
if user.save
render json: user
else
render json: user.errors
end
end
- 请求
curl -X POST http://127.0.0.1:3000/users - 返回报错
{"email":["can't be blank"]}#
实现 show 方法 [⇧](#实现 show 方法 ⇧ "#catalogue")
app/controllers/users_controller.rb
ruby
class UsersController < ApplicationController
def create
# ...
end
def show
p "--------------------"
p params[:id]
p "--------------------"
user = User.find params[:id]
render json: user
end
end
- 请求
curl -X GET http://127.0.0.1:3000/users/1查看后台打印 - 打印找不到的情况,请求
curl -X GET http://127.0.0.1:3000/users/1000 - 由于
User.find可能返回异常报错,自动返回404并且逻辑不再往下处理,截胡代码逻辑- 解决方法:使用
find_by_id方法,返回 nil 时,返回 404 错误 find_by_id是Ruby的 元编程 方法- 并未在
app/models/user.rb中主动定义该方法,自动读取数据库字段生成 - 意味着还有
find_by_name、find_by_email等方法 - 建议开发中少使用
find,直接终端当前方法,返回 404 - 当需要对错误做另外处理时,使用
find_by_xxx
- 解决方法:使用
- 使用
curl -v http://127.0.0.1:3000/users/1- 查看响应头
< HTTP/1.1 404 Not Found
- 查看响应头
最终
app/controllers/users_controller.rb
ruby
class UsersController < ApplicationController
def create
# ...
end
def show
user = User.find_by_id params[:id]
if user
render json: user
else
head 404
end
end
end
Router + MVC [⇧](#Router + MVC ⇧ "#catalogue")
- 目前实现了
- 路由
config/routes.rb - Model
app/models/user.rb - 控制器
app/controllers/users_controller.rb - 视图(
api模式没有视图,只是返回json)
- 路由
- 理解这些 rails 就入门了
8. 总结和实战操作 [⇧](#8. 总结和实战操作 ⇧ "#catalogue")
创建一个后台的工作流,启动数据库服务,启动服务
bin/rails s
- 创建
Model的命令:bin/rails g model user email:string name:string- 生成
app/models/user.rb添加验证逻辑 - 生成
db/migrate/xxxx_create_users_table.rb- 在
CreateUsers#change方法中添加自定义字段
- 在
- 生成
- 迁移数据库的命令:
bin/rails db:migrate - 反悔命令:
bin/rails db:rollback step=1 - 通过插件或自带数据库功能,可以查看数据库中的表
- 手动在
config/routes.rb中创建路由post '/users', to: 'users#create'get '/users/:id', to: 'users#show'
- 创建
Controller运行命令bin/rails g controller users create show- 生成
app/controllers/users_controller.rb, 补充操作逻辑- 暂时使用
curl命令访问接口,查看后台打印 - 通过插件或自带数据库功能,可以查看数据库中的数据
- 暂时使用
- 在路由文件中自动添加了两个方法,但不够精确,目前不用,手动删除
get 'user/create'get 'user/show'
- 生成
命令
zsh
# Model
bin/rails g model user email:string name:string
# Data Migration
bin/rails db:migrate
# Data Rollback
bin/rails db:rollback step=1
# Controller & Route
bin/rails g controller users create show
创建一个github仓库,实现如下功能
post /users可以创建用户(属性随意)get /users/:id可以展示用户(属性随意)
9.使用 JetBrains 的 Dev Container 远程开发 V.S. VSCode 的 Dev Container [⇧](#9.使用 JetBrains 的 Dev Container 远程开发 V.S. VSCode 的 Dev Container ⇧ "#catalogue")
总结使用 VSCode 的 Dev Container 远程开发 [⇧](#总结使用 VSCode 的 Dev Container 远程开发 ⇧ "#catalogue")
以
win11的WSL2环境,并安装 Docker Desktop 客户端为例
- 本地下载
oh-my-env项目,使用VSCode打开,在容器中打开,构建镜像 - 成功启动开发容器,新建终端zsh,打开
repos中的项目目录- 确认开启
docker容器数据库镜像服务(重新构建数据库镜像后,需要执行迁移数据库命令) - 仅首次构建或
rebuild,从oh-my-env2目录拷贝初始配置- 替换覆盖
/root项目目录中的配置
- 替换覆盖
- 项目目录打开成功,检查环境依赖配置版本,启动项目服务
- 端口自动转发
127.0.0.1:3000成功访问初始页面
- 确认开启
设置并备份环境配置,持久化默认开发配置
- 仅首次构建或
rebuild,从oh-my-env2目录拷贝初始配置- 替换覆盖
/root项目目录中的配置
- 替换覆盖
- 备份脚本,将主要配置拷贝到 本地目录
oh-my-env中
使用 JetBrains 的 Dev Container 远程开发 [⇧](#使用 JetBrains 的 Dev Container 远程开发 ⇧ "#catalogue")
以
win11的WSL2环境,并安装 Docker Desktop 客户端为例
- 本地下载
oh-my-env项目,使用RubyMine打开- 可以选择消息提示浮动框,在容器中重新打开,构建镜像
- 或者点击菜单中的 文件 -> 远程开发 ->
Dev Container - 或者在服务面板中点击
Dev Container对应的容器启动
- 成功启动开发容器,新建终端zsh, 打开
repos中的项目目录- 确认开启
docker容器数据库镜像服务(重新构建数据库镜像后,需要执行迁移数据库命令)- 创建数据库镜像时,需要添加
-p 5432:5432指定端口映射 - 将容器的5432端口映射到主机的5432端口
- 创建数据库镜像时,需要添加
- 仅首次构建或
rebuild,从oh-my-env2目录拷贝初始配置- 替换覆盖
/root项目目录中的配置
- 替换覆盖
- 项目目录打开成功,检查环境依赖配置版本,启动项目服务
- 点击弹出框,确认端口转发
127.0.0.1:3000成功访问初始页面
- 确认开启

消息提示浮动框,在容器中重新打开,构建镜像

远程开发

确认端口转发

10. 连接查看数据库 [⇧](#10. 连接查看数据库 ⇧ "#catalogue")
每次重启后忘记开数据库 [⇧](#每次重启后忘记开数据库 ⇧ "#catalogue")
会看到启动页面报错

运行启动命令
bash
docker start db-for-mangosteen
# 成功运行会返回id
# db-for-mangosteen
- 再次刷新页面即可
将创建数据库命令和启动命令写到
README.md中,添加运行脚本
create_database_container.shstart_database_container.sh
数据库容器已经持久化到
mangosteen-data数据卷中
使用插件或者 DataGrip 或者 DBeaver 数据库 IDE
- 待更新
11. 需要运行的命令参考 [⇧](#11. 需要运行的命令参考 ⇧ "#catalogue")
需要运行的命令参考
zsh
# 更换gem国内源
gem sources --add https://mirrors.tuna.tsinghua.edu.cn/rubygems/ --remove https://gems.ruby-china.com/
# 更换bundle国内源
bundle config set --global mirror.https://rubygems.org https://mirrors.tuna.tsinghua.edu.cn/rubygems
# 安装rails,版本尽量和我的一致,会有日志,等待时间较长
gem install rails -v 7.2.3.2
# 创建rails项目;只是用 api 模式;数据库 使用 postgresql;跳过自带测试(之后使用第三方测试);
cd ~/repos
rails new --api --database=postgresql --skip-test mangosteen-1
# 使用 VSCode 打开在容器中项目
code mangosteen-1 # code ~/repos/mangosteen-1
# 启动数据库容器
docker run -d --name db-for-mangosteen -e POSTGRES_USER=mangosteen -e POSTGRES_PASSWORD=123456 -e POSTGRES_DB=mangosteen_dev -e PGDATA=/var/lib/postgresql/data/pgdata -v mangosteen-data:/var/lib/postgresql/data -p 5432:5432 --network=network1 postgres:14
# 新建一个zsh终端后,启动rails服务;需要关闭server 请按Ctrl+C
bundle exec rails server
# 创建数据库模型类 Model
bin/rails g model user email:string name:string
# 迁移数据库 Migration
bin/rails db:migrate
# 反悔迁移数据库 Rollback
bin/rails db:rollback step=1
# Controller & Route
bin/rails g controller users create show
·未完待续·
参考文章
- 如何快速正确的安装 Ruby, Rails 运行环境------来自ruby-china社区
- ruby-lang 官方
- Ruby Version Manager (RVM)
- ruby on rails
- rails github
- Install Ruby on Rails Guide
- 安装开发依赖 ruby-china
源代码镜像服务
- Ruby 源代码镜像服务
- Ruby China Gems 镜像服务停服公告
- 清华大学开源软件镜像站
- 中国科学技术大学 USTC 提供 cache.ruby-lang.org 镜像!
- Ruby镜像源切换:解决淘宝源失效与SSL问题
- RubyMetric/chsrc
- 告别换源抓狂!chsrc 全平台一键换源工具(python,go,nodejs,ruby)
数据迁移
相关文章
- 怎么安装特定版本的 rails reddit
- 安装Ruby和安装Rails
- rbenv - the Ruby version manager
- rbenv github
- rbenv-cn
- 【转】Ruby on Rails,服务端如何响应页面提交的请求
- Ruby 浅谈 Rails 8.0.0 特性
- 【2026年最新版】Windows 11 + WSL2 + Ubuntuで Rails 8 を構築する完全ガイド【Ruby4対応】
- 作者: Joel
- 文章链接:
- 版权声明
- 非自由转载-非商用-非衍生-保持署名