Rails响应格式 #
一、响应格式概述 #
1.1 支持的格式 #
Rails支持多种响应格式:
| 格式 | 说明 | Content-Type |
|---|---|---|
| HTML | 网页 | text/html |
| JSON | API数据 | application/json |
| XML | XML数据 | application/xml |
| JS | JavaScript | application/javascript |
| CSV | 表格数据 | text/csv |
| PDF文档 | application/pdf |
1.2 格式协商 #
Rails通过以下方式确定响应格式:
- URL后缀:
/articles.json - Accept头:
Accept: application/json - 参数:
?format=json
二、respond_to #
2.1 基本用法 #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
respond_to do |format|
format.html
format.json { render json: @article }
format.xml { render xml: @article }
end
end
end
2.2 格式选项 #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
respond_to do |format|
format.html { render :show }
format.json { render json: @article, status: :ok }
format.xml { render xml: @article, root: 'article' }
format.js { render js: "alert('Hello')" }
format.text { render plain: @article.body }
end
end
end
2.3 默认格式 #
ruby
# config/routes.rb
Rails.application.routes.draw do
resources :articles, defaults: { format: :json }
end
# 或在控制器中
class ArticlesController < ApplicationController
def index
@articles = Article.all
respond_to do |format|
format.any { render json: @articles }
end
end
end
三、JSON响应 #
3.1 基本JSON渲染 #
ruby
# app/controllers/api/v1/articles_controller.rb
module Api
module V1
class ArticlesController < ApplicationController
def index
@articles = Article.all
render json: @articles
end
def show
@article = Article.find(params[:id])
render json: @article
end
def create
@article = Article.new(article_params)
if @article.save
render json: @article, status: :created
else
render json: { errors: @article.errors }, status: :unprocessable_entity
end
end
end
end
end
3.2 自定义JSON #
ruby
# app/controllers/api/v1/articles_controller.rb
module Api
module V1
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
render json: {
id: @article.id,
title: @article.title,
body: @article.body,
author: {
id: @article.author.id,
name: @article.author.name
},
created_at: @article.created_at.iso8601
}
end
end
end
end
3.3 使用Jbuilder #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
respond_to do |format|
format.json
end
end
end
# app/views/articles/show.json.jbuilder
json.id @article.id
json.title @article.title
json.body @article.body
json.author do
json.id @article.author.id
json.name @article.author.name
end
json.created_at @article.created_at.iso8601
3.4 JSON选项 #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def index
@articles = Article.all
render json: @articles,
only: [:id, :title, :created_at],
methods: [:summary],
include: {
author: { only: [:id, :name] }
}
end
end
四、XML响应 #
4.1 基本XML渲染 #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
render xml: @article
end
end
4.2 自定义XML #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
render xml: @article.to_xml(
only: [:id, :title, :body],
include: {
author: { only: [:id, :name] }
}
)
end
end
五、JavaScript响应 #
5.1 JS模板 #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def create
@article = Article.new(article_params)
respond_to do |format|
if @article.save
format.html { redirect_to @article }
format.js # 渲染 create.js.erb
else
format.html { render :new }
format.js # 渲染 create.js.erb
end
end
end
end
# app/views/articles/create.js.erb
$('#articles').append('<%= j render @article %>');
$('#article_form').trigger('reset');
5.2 内联JavaScript #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def update
@article = Article.find(params[:id])
@article.update(article_params)
render js: "alert('Article updated!')"
end
end
六、CSV响应 #
6.1 基本CSV渲染 #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def index
@articles = Article.all
respond_to do |format|
format.html
format.csv do
send_data generate_csv(@articles),
filename: "articles-#{Date.today}.csv",
type: 'text/csv'
end
end
end
private
def generate_csv(articles)
CSV.generate(headers: true) do |csv|
csv << ['ID', 'Title', 'Author', 'Created At']
articles.each do |article|
csv << [article.id, article.title, article.author.name, article.created_at]
end
end
end
end
6.2 CSV模板 #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def index
@articles = Article.all
respond_to do |format|
format.csv { render csv: @articles }
end
end
end
# app/views/articles/index.csv.erb
<%= CSV.generate_line(['ID', 'Title', 'Author', 'Created At']) %>
<% @articles.each do |article| %>
<%= CSV.generate_line([article.id, article.title, article.author.name, article.created_at]) %>
<% end %>
七、PDF响应 #
7.1 使用Prawn #
ruby
# Gemfile
gem 'prawn'
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
respond_to do |format|
format.html
format.pdf do
pdf = Prawn::Document.new
pdf.text @article.title, size: 24, style: :bold
pdf.text @article.body
send_data pdf.render,
filename: "#{@article.title}.pdf",
type: 'application/pdf'
end
end
end
end
7.2 使用Wicked PDF #
ruby
# Gemfile
gem 'wicked_pdf'
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
respond_to do |format|
format.html
format.pdf do
render pdf: @article.title,
template: 'articles/show',
layout: 'pdf'
end
end
end
end
八、文件下载 #
8.1 send_data #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def download
content = generate_content
send_data content,
filename: 'articles.txt',
type: 'text/plain',
disposition: 'attachment'
end
end
8.2 send_file #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def download
file_path = Rails.root.join('public', 'files', 'document.pdf')
send_file file_path,
filename: 'document.pdf',
type: 'application/pdf',
disposition: 'attachment'
end
end
8.3 Active Storage下载 #
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def download_attachment
@article = Article.find(params[:id])
redirect_to @article.attachment.url,
disposition: 'attachment'
end
end
九、API响应模式 #
9.1 统一响应格式 #
ruby
# app/controllers/api/v1/base_controller.rb
module Api
module V1
class BaseController < ApplicationController
private
def render_success(data = nil, message: 'Success')
render json: {
success: true,
message: message,
data: data
}
end
def render_error(message, status: :bad_request, errors: nil)
render json: {
success: false,
message: message,
errors: errors
}, status: status
end
end
end
end
# app/controllers/api/v1/articles_controller.rb
module Api
module V1
class ArticlesController < BaseController
def create
@article = Article.new(article_params)
if @article.save
render_success(@article, message: 'Article created')
else
render_error('Validation failed', errors: @article.errors)
end
end
end
end
end
9.2 分页响应 #
ruby
# app/controllers/api/v1/articles_controller.rb
module Api
module V1
class ArticlesController < BaseController
def index
@articles = Article.page(params[:page]).per(params[:per_page] || 20)
render json: {
articles: @articles,
pagination: {
current_page: @articles.current_page,
total_pages: @articles.total_pages,
total_count: @articles.total_count,
per_page: @articles.limit_value
}
}
end
end
end
end
十、内容协商 #
10.1 自定义MIME类型 #
ruby
# config/initializers/mime_types.rb
Mime::Type.register 'application/vnd.api+json', :api_json
Mime::Type.register 'application/vnd.myapp.v1+json', :v1_json
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
respond_to do |format|
format.json { render json: @article }
format.api_json { render json: @article, adapter: :json_api }
end
end
end
10.2 API版本控制 #
ruby
# app/controllers/api/v1/articles_controller.rb
module Api
module V1
class ArticlesController < ApplicationController
def index
@articles = Article.all
render json: @articles
end
end
end
end
# app/controllers/api/v2/articles_controller.rb
module Api
module V2
class ArticlesController < ApplicationController
def index
@articles = Article.includes(:author).all
render json: @articles, include: :author
end
end
end
end
十一、总结 #
11.1 核心要点 #
| 要点 | 说明 |
|---|---|
| respond_to | 多格式响应 |
| JSON渲染 | API开发常用 |
| 文件下载 | send_data/send_file |
| 格式协商 | Accept头和URL后缀 |
| 统一响应 | API最佳实践 |
11.2 下一步 #
现在你已经掌握了响应格式,接下来让我们学习 ERB模板,深入了解Rails的视图系统!
最后更新:2026-03-28