ruby on rails admin/frontend 常用架构
rails 有一个 admin/frontned 2个大模块,admin 只要提供api即可(我会用其它技术开发 admin 后台); frontend 会使用 erb 生成 html
你描述的 Rails 项目结构非常清晰:一个 Rails 应用,包含两个大模块:
- admin:仅提供 API 接口,供外部管理后台(可能用 Vue、React、Next.js 等)调用。
- frontend:使用 ERB 模板渲染 HTML 页面,面向普通用户。
下面我为你详细说明如何在 Rails 中实现这种架构设计,并给出最佳实践建议。
✅ 一、整体架构设计
app/
├── controllers/
│ ├── api/ # API 控制器(admin 使用)
│ │ └── v1/
│ │ ├── users_controller.rb
│ │ └── ...
│ ├── frontend/ # 前台控制器(ERB 渲染)
│ │ ├── pages_controller.rb
│ │ └── ...
│ └── application_controller.rb
├── views/
│ ├── frontend/ # ERB 模板
│ │ ├── pages/
│ │ │ └── home.html.erb
│ │ └── layouts/
│ │ └── application.html.erb
│ └── api/ # 无视图(API 不需要)
└── helpers/
└── frontend/ # 前台辅助方法
config/routes.rb # 路由分离
✅ 二、路由设计(关键)
在 config/routes.rb
中分离两个模块:
Rails.application.routes.draw do
# 前台:HTML 页面,使用 ERB
scope module: 'frontend' do
root 'pages#home'
get '/about', to: 'pages#about'
# 其它页面...
end
# 后台 API:JSON 接口,版本化
namespace :api do
namespace :v1 do
resources :users, only: [:index, :show, :create, :update, :destroy]
post '/login', to: 'sessions#create'
# 其它 API...
end
end
end
访问示例:
- 前台页面:
GET /
→frontend/pages#home
- API 接口:
GET /api/v1/users
→api/v1/users#index
✅ 三、控制器分离
1. 前台控制器(ERB 渲染)
# app/controllers/frontend/pages_controller.rb
class Frontend::PagesController < ApplicationController
def home
@title = "首页"
end
def about
@title = "关于我们"
end
end
2. API 控制器(仅返回 JSON)
# app/controllers/api/v1/users_controller.rb
module Api
module V1
class UsersController < ApplicationController
before_action :authenticate_admin!, except: [:index] # 可选鉴权
def index
users = User.all
render json: { data: users }, status: :ok
end
def show
user = User.find(params[:id])
render json: { data: user }
end
def create
user = User.new(user_params)
if user.save
render json: { data: user, message: "创建成功" }, status: :created
else
render json: { errors: user.errors }, status: :unprocessable_entity
end
end
# ... update, destroy
private
def user_params
params.require(:user).permit(:name, :email)
end
end
end
end
✅ 四、基础控制器设计
1. Application Controller(通用)
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
# 可添加通用 helper_method、current_user 等
end
2. API 基类控制器(可选)
# app/controllers/api/v1/base_controller.rb
module Api
module V1
class BaseController < ApplicationController
skip_before_action :verify_authenticity_token # API 不需要 CSRF
respond_to :json
rescue_from ActiveRecord::RecordNotFound do |e|
render json: { error: '记录未找到' }, status: :not_found
end
private
def authenticate_admin!
# 示例:使用 Token 鉴权
# header: Authorization: Bearer xxx
token = request.headers['Authorization']&.split(' ')&.last
unless token && AdminToken.valid?(token)
render json: { error: '未授权' }, status: :unauthorized
end
end
end
end
end
然后让所有 API 控制器继承它:
class Api::V1::UsersController < Api::V1::BaseController
# ...
end
✅ 五、视图(仅 frontend 使用 ERB)
<!-- app/views/frontend/pages/home.html.erb -->
<% content_for :title, @title %>
<h1>欢迎来到首页</h1>
<p>这是使用 ERB 渲染的页面。</p>
布局文件:
<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
<title><%= yield :title %></title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', 'data-turbo-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
✅ 六、静态资源与前端分离建议
- frontend:继续使用 Rails 的 Asset Pipeline(Sprockets)或导入 Webpacker / Importmap。
- admin:完全外部开发(如用 React/Vue),部署为独立站点,通过 CORS 调用 Rails 的
/api/v1/*
接口。
配置 CORS(重要!)
使用 rack-cors
gem:
# Gemfile
gem 'rack-cors'
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'http://admin.example.com' # 你的 admin 域名
resource '/api/v1/*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options],
credentials: true
end
end
✅ 七、可选:命名空间优化
你也可以使用更清晰的命名空间:
Frontend::PagesController
Api::V1::UsersController
并通过 scope
和 namespace
控制路由。
✅ 八、总结:最佳实践
| 项目 | 建议 |
|------|------|
| API 设计 | 版本化(/api/v1/...
) |
| 认证 | 使用 JWT / Token / Devise Token Auth |
| 前台 | ERB + Rails 内置视图 |
| 后台 | 外部 SPA,调用 API |
| 鉴权 | before_action :authenticate_admin!
|
| 错误处理 | rescue_from
统一返回 JSON |
| CORS | 配置 rack-cors
允许 admin 域名 |
| 日志 | API 请求建议记录日志 |
✅ 九、后续扩展建议
- 使用
ActiveModel::Serializer
或Jbuilder
格式化 JSON 输出。 - 使用
Devise
管理后台用户(可配合devise_token_auth
)。 - 前台用户登录也可走 API(如果未来要做 SPA)。
如果你希望我生成一个完整的示例项目结构或代码模板,也可以告诉我,我可以帮你生成脚手架代码。