Rails 视图层经常被外行粗暴地理解成“后端拼 HTML”。
其实它更像一套有层次的大厅装修系统:
Layout = 整栋大厅的统一外立面
View = 某个窗口当前页面
Partial = 可复用的小构件
Helper = 展示辅助工具最外层 layout:
<!DOCTYPE html>
<html>
<head>
<title>城市脚手架工务署</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
<body>
<header>
<h1>城市脚手架工务署</h1>
<nav>
<%= link_to "许可单列表", permits_path %>
<%= link_to "新建许可单", new_permit_path %>
</nav>
</header>
<main>
<% if notice %>
<p><%= notice %></p>
<% end %>
<%= yield %>
</main>
</body>
</html>列表页:
<h2>施工许可单</h2>
<div id="permits">
<%= render @permits %>
</div>局部构件 _permit.html.erb:
<article id="<%= dom_id permit %>">
<h3><%= link_to permit.title, permit %></h3>
<p>城区:<%= permit.district %></p>
<p>状态:<%= permit.status %></p>
</article>表单:
<%= form_with model: @permit do |form| %>
<% if @permit.errors.any? %>
<div>
<h3>资料不完整:</h3>
<ul>
<% @permit.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= form.label :title, "工程标题" %>
<%= form.text_field :title %>
</div>
<div>
<%= form.label :district, "城区" %>
<%= form.text_field :district %>
</div>
<div>
<%= form.label :status, "状态" %>
<%= form.select :status, %w[draft submitted approved rejected] %>
</div>
<div>
<%= form.label :starts_on, "开工日期" %>
<%= form.date_field :starts_on %>
</div>
<%= form.submit %>
<% end %>这里最值得建立的心智是:
layout管整栋楼view管当前窗口partial管可复用构件form_with不是单纯字符串拼接,它帮你处理 model 绑定、字段命名、CSRF、提交路径
Rails 的视图层不追求“前端框架感”,它追求的是:
服务器端页面输出的结构化、复用性和约定一致性。