Rails辅助方法 #
一、辅助方法概述 #
1.1 什么是辅助方法 #
辅助方法(Helper)是Rails提供的视图辅助方法,用于简化视图代码,保持视图简洁。
1.2 辅助方法位置 #
text
app/helpers/
├── application_helper.rb # 全局辅助方法
├── articles_helper.rb # 文章相关辅助方法
└── users_helper.rb # 用户相关辅助方法
二、内置辅助方法 #
2.1 链接辅助方法 #
erb
<!-- 基本链接 -->
<%= link_to '首页', root_path %>
<!-- 带HTML属性 -->
<%= link_to '文章', articles_path, class: 'btn', id: 'articles-link' %>
<!-- 带数据属性 -->
<%= link_to '删除', article_path(@article),
data: {
turbo_method: :delete,
turbo_confirm: '确定删除?'
} %>
<!-- 块链接 -->
<%= link_to article_path(@article) do %>
<strong><%= @article.title %></strong>
<% end %>
<!-- 邮件链接 -->
<%= mail_to 'info@example.com', '联系我们' %>
<!-- 电话链接 -->
<%= phone_to '1234567890', '拨打电话' %>
<!-- SMS链接 -->
<%= sms_to '1234567890', '发送短信' %>
2.2 URL辅助方法 #
erb
<!-- 路径助手 -->
<%= root_path %> <!-- / -->
<%= articles_path %> <!-- /articles -->
<%= article_path(@article) %> <!-- /articles/1 -->
<%= new_article_path %> <!-- /articles/new -->
<%= edit_article_path(@article) %> <!-- /articles/1/edit -->
<!-- URL助手 -->
<%= root_url %> <!-- http://example.com/ -->
<%= articles_url %> <!-- http://example.com/articles -->
<!-- 带参数 -->
<%= articles_path(page: 2) %> <!-- /articles?page=2 -->
<%= article_path(@article, format: :json) %> <!-- /articles/1.json -->
2.3 资源辅助方法 #
erb
<!-- 样式表 -->
<%= stylesheet_link_tag 'application' %>
<%= stylesheet_link_tag 'print', media: 'print' %>
<!-- JavaScript -->
<%= javascript_importmap_tags %>
<%= javascript_include_tag 'application' %>
<!-- 图片 -->
<%= image_tag 'logo.png', alt: 'Logo' %>
<%= image_tag 'icon.png', size: '16x16' %>
<%= image_tag 'photo.jpg', class: 'img-fluid' %>
<!-- 视频和音频 -->
<%= video_tag 'intro.mp4', controls: true %>
<%= audio_tag 'music.mp3', controls: true %>
<!-- favicon -->
<%= favicon_link_tag 'favicon.ico' %>
2.4 文本辅助方法 #
erb
<!-- 截断文本 -->
<%= truncate(@article.body, length: 100) %>
<%= truncate(@article.body, length: 100, omission: '...') %>
<!-- 高亮文本 -->
<%= highlight(@article.body, 'Rails') %>
<%= highlight(@article.body, ['Rails', 'Ruby']) %>
<!-- 简单格式化 -->
<%= simple_format(@article.body) %>
<%= simple_format(@article.body, class: 'paragraph') %>
<!-- 自动链接 -->
<%= auto_link(@article.body) %>
<%= auto_link(@article.body, html: { target: '_blank' }) %>
<!-- 复数化 -->
<%= pluralize(@articles.count, 'article') %> <!-- 5 articles -->
<%= pluralize(1, 'person') %> <!-- 1 person -->
<!-- 单词截断 -->
<%= word_wrap(@article.body, line_width: 80) %>
<!-- 首字母大写 -->
<%= titleize('hello world') %> <!-- Hello World -->
2.5 数字辅助方法 #
erb
<!-- 格式化数字 -->
<%= number_with_delimiter(1234567) %> <!-- 1,234,567 -->
<%= number_with_precision(3.14159, precision: 2) %> <!-- 3.14 -->
<!-- 货币格式 -->
<%= number_to_currency(123.45) %> <!-- $123.45 -->
<%= number_to_currency(123.45, unit: '¥') %> <!-- ¥123.45 -->
<%= number_to_currency(123.45, format: '%n %u') %> <!-- 123.45 ¥ -->
<!-- 百分比格式 -->
<%= number_to_percentage(0.5, precision: 0) %> <!-- 50% -->
<%= number_to_percentage(0.523, precision: 2) %> <!-- 52.30% -->
<!-- 电话格式 -->
<%= number_to_phone(1234567890) %> <!-- 123-456-7890 -->
<!-- 文件大小 -->
<%= number_to_human_size(1234567) %> <!-- 1.18 MB -->
<!-- 人类可读数字 -->
<%= number_to_human(1234567) %> <!-- 1.23 Million -->
2.6 日期时间辅助方法 #
erb
<!-- 格式化日期 -->
<%= l Date.today, format: :long %> <!-- 2024年3月28日 -->
<%= l Time.now, format: :short %> <!-- 28日 15:30 -->
<!-- 距离时间 -->
<%= distance_of_time_in_words(Time.now, Time.now + 1.day) %> <!-- about 1 day -->
<%= distance_of_time_in_words(Time.now, Time.now + 1.hour) %> <!-- about 1 hour -->
<!-- 时间选择 -->
<%= time_ago_in_words(@article.created_at) %> <!-- 2 hours ago -->
<!-- 时间标签 -->
<%= time_tag Date.today %> <!-- <time datetime="2024-03-28">2024-03-28</time> -->
<%= time_tag Date.today, format: :long %> <!-- <time datetime="2024-03-28">2024年3月28日</time> -->
2.7 数组辅助方法 #
erb
<!-- 循环 -->
<% ['one', 'two', 'three'].each_with_index do |item, index| %>
<%= cycle('odd', 'even', name: 'row_class') %> <!-- odd, even, odd -->
<% end %>
<!-- 安全连接 -->
<%= safe_join(['项目1', '项目2', '项目3'], ', ') %> <!-- 项目1, 项目2, 项目3 -->
<!-- 截取数组 -->
<%= @articles.first(5) %>
2.8 标签辅助方法 #
erb
<!-- 内容标签 -->
<%= content_tag :div, class: 'container' do %>
<p>内容</p>
<% end %>
<!-- 标签 -->
<%= tag.div class: 'container' do %>
<p>内容</p>
<% end %>
<!-- 自闭合标签 -->
<%= tag.br %>
<%= tag.hr %>
<%= tag.img src: 'logo.png' %>
2.9 缓存辅助方法 #
erb
<!-- 缓存片段 -->
<% cache @article do %>
<%= render @article %>
<% end %>
<!-- 缓存集合 -->
<%= render partial: 'article', collection: @articles, cached: true %>
<!-- 缓存过期 -->
<% cache [@article, current_user] do %>
<%= render @article %>
<% end %>
2.10 调试辅助方法 #
erb
<!-- 调试输出 -->
<%= debug(@article) %>
<%= debug(params) %>
<!-- 美化输出 -->
<%= simple_format(@article.to_yaml) %>
<!-- 控制台 -->
<%= console %>
三、自定义辅助方法 #
3.1 创建辅助方法 #
ruby
# app/helpers/application_helper.rb
module ApplicationHelper
def page_title(title)
title.present? ? "#{title} | MyApp" : 'MyApp'
end
def format_date(date)
date.strftime('%Y年%m月%d日') if date
end
def markdown(text)
renderer = Redcarpet::Render::HTML.new
markdown = Redcarpet::Markdown.new(renderer)
markdown.render(text).html_safe
end
def author_link(article)
link_to article.author.name, user_path(article.author)
end
end
3.2 使用辅助方法 #
erb
<!-- app/views/layouts/application.html.erb -->
<title><%= page_title(yield(:title)) %></title>
<!-- app/views/articles/show.html.erb -->
<h1><%= @article.title %></h1>
<p><%= format_date(@article.created_at) %></p>
<div class="content">
<%= markdown(@article.body) %>
</div>
<p>作者:<%= author_link(@article) %></p>
3.3 控制器辅助方法 #
ruby
# app/helpers/articles_helper.rb
module ArticlesHelper
def article_status_badge(article)
case article.status
when 'published'
content_tag :span, '已发布', class: 'badge bg-success'
when 'draft'
content_tag :span, '草稿', class: 'badge bg-secondary'
when 'archived'
content_tag :span, '已归档', class: 'badge bg-dark'
end
end
def article_card(article)
content_tag :div, class: 'card' do
concat(content_tag(:div, class: 'card-header') do
article.title
end)
concat(content_tag(:div, class: 'card-body') do
truncate(article.body, length: 100)
end)
end
end
end
3.4 表单辅助方法 #
ruby
# app/helpers/form_helper.rb
module FormHelper
def error_messages_for(object)
return '' if object.errors.empty?
content_tag :div, class: 'alert alert-danger' do
concat(content_tag(:h4, '请修正以下错误:'))
concat(content_tag(:ul) do
object.errors.full_messages.each do |message|
concat(content_tag(:li, message))
end
end)
end
end
def form_group(form, attribute, options = {})
content_tag :div, class: 'form-group' do
concat(form.label(attribute, class: 'form-label'))
concat(form.text_field(attribute, class: 'form-control'))
if options[:help]
concat(content_tag(:small, options[:help], class: 'form-text'))
end
end
end
end
四、辅助方法最佳实践 #
4.1 命名规范 #
ruby
# 推荐:动词开头
def format_date(date)
end
def render_article(article)
end
def display_status(status)
end
# 不推荐:名词开头
def date_format(date)
end
def article_renderer(article)
end
4.2 保持简洁 #
ruby
# 不推荐:复杂逻辑
def article_list(articles)
html = ''
articles.each do |article|
html += '<div class="article">'
html += "<h2>#{article.title}</h2>"
html += "<p>#{article.body}</p>"
html += '</div>'
end
html.html_safe
end
# 推荐:使用辅助方法
def article_list(articles)
render partial: 'articles/article', collection: articles
end
4.3 避免业务逻辑 #
ruby
# 不推荐:辅助方法中包含业务逻辑
def article_price(article)
if article.on_sale?
article.price * 0.9
else
article.price
end
end
# 推荐:业务逻辑放在模型中
# app/models/article.rb
class Article < ApplicationRecord
def final_price
on_sale? ? price * 0.9 : price
end
end
# app/helpers/articles_helper.rb
def article_price(article)
number_to_currency(article.final_price)
end
五、总结 #
5.1 核心要点 #
| 要点 | 说明 |
|---|---|
| 内置辅助方法 | Rails提供的辅助方法 |
| 自定义辅助方法 | 在helpers目录创建 |
| 命名规范 | 动词开头 |
| 保持简洁 | 使用render等 |
| 避免业务逻辑 | 放在模型中 |
5.2 下一步 #
现在你已经掌握了辅助方法,接下来让我们学习 数据库配置,深入了解Rails的数据库系统!
最后更新:2026-03-28