Rails第一个应用 #
一、创建项目 #
1.1 生成项目 #
bash
# 创建新的Rails项目
rails new blog
# 进入项目目录
cd blog
# 创建数据库
rails db:create
1.2 项目结构概览 #
text
blog/
├── app/
│ ├── controllers/ # 控制器
│ │ └── application_controller.rb
│ ├── models/ # 模型
│ │ └── application_record.rb
│ ├── views/ # 视图
│ │ └── layouts/
│ │ └── application.html.erb
│ ├── helpers/ # 辅助方法
│ ├── javascript/ # JavaScript
│ └── assets/ # 静态资源
├── config/
│ ├── routes.rb # 路由配置
│ ├── database.yml # 数据库配置
│ └── environments/ # 环境配置
├── db/
│ ├── migrate/ # 迁移文件
│ ├── schema.rb # 数据库结构
│ └── seeds.rb # 种子数据
├── public/ # 公共文件
├── Gemfile # Gem依赖
└── Gemfile.lock # 锁定版本
二、Hello World #
2.1 创建控制器 #
bash
# 生成控制器
rails generate controller Welcome index
# 输出:
# create app/controllers/welcome_controller.rb
# route get 'welcome/index'
# invoke erb
# create app/views/welcome
# create app/views/welcome/index.html.erb
# invoke test_unit
# create test/controllers/welcome_controller_test.rb
# invoke helper
# create app/helpers/welcome_helper.rb
2.2 控制器代码 #
ruby
# app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
def index
end
end
2.3 视图代码 #
erb
<!-- app/views/welcome/index.html.erb -->
<h1>Welcome to Rails</h1>
<p>Hello, World!</p>
<p>现在是:<%= Time.now.strftime('%Y-%m-%d %H:%M:%S') %></p>
2.4 设置根路由 #
ruby
# config/routes.rb
Rails.application.routes.draw do
root 'welcome#index'
# 也可以这样写
# get 'welcome/index'
# root to: 'welcome#index'
end
2.5 启动应用 #
bash
# 启动服务器
rails server
# 访问 http://localhost:3000
三、使用脚手架 #
3.1 什么是脚手架 #
脚手架(Scaffold)是Rails的代码生成器,可以快速创建完整的CRUD(创建、读取、更新、删除)功能。
3.2 创建Article脚手架 #
bash
# 生成Article脚手架
rails generate scaffold Article title:string body:text
# 输出:
# invoke active_record
# create db/migrate/20240328000001_create_articles.rb
# create app/models/article.rb
# invoke test_unit
# create test/models/article_test.rb
# invoke resource_route
# route resources :articles
# invoke scaffold_controller
# create app/controllers/articles_controller.rb
# invoke erb
# create app/views/articles
# create app/views/articles/index.html.erb
# create app/views/articles/edit.html.erb
# create app/views/articles/show.html.erb
# create app/views/articles/new.html.erb
# create app/views/articles/_article.html.erb
# invoke test_unit
# create test/controllers/articles_controller_test.rb
# invoke helper
# create app/helpers/articles_helper.rb
3.3 运行迁移 #
bash
# 执行数据库迁移
rails db:migrate
# 输出:
# == 20240328000001 CreateArticles: migrating ===================================
# -- create_table(:articles)
# -> 0.0018s
# == 20240328000001 CreateArticles: migrated (0.0019s) ==========================
3.4 生成的文件 #
迁移文件:
ruby
# db/migrate/20240328000001_create_articles.rb
class CreateArticles < ActiveRecord::Migration[7.1]
def change
create_table :articles do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
模型文件:
ruby
# app/models/article.rb
class Article < ApplicationRecord
end
控制器文件:
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
before_action :set_article, only: %i[ show edit update destroy ]
def index
@articles = Article.all
end
def show
end
def new
@article = Article.new
end
def edit
end
def create
@article = Article.new(article_params)
respond_to do |format|
if @article.save
format.html { redirect_to article_url(@article), notice: "Article was successfully created." }
format.json { render :show, status: :created, location: @article }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @article.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @article.update(article_params)
format.html { redirect_to article_url(@article), notice: "Article was successfully updated." }
format.json { render :show, status: :ok, location: @article }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @article.errors, status: :unprocessable_entity }
end
end
end
def destroy
@article.destroy!
respond_to do |format|
format.html { redirect_to articles_url, notice: "Article was successfully destroyed." }
format.json { head :no_content }
end
end
private
def set_article
@article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(:title, :body)
end
end
路由配置:
ruby
# config/routes.rb
Rails.application.routes.draw do
resources :articles
root 'welcome#index'
end
3.5 视图文件 #
列表页面:
erb
<!-- app/views/articles/index.html.erb -->
<p style="color: green"><%= notice %></p>
<h1>Articles</h1>
<div id="articles">
<% @articles.each do |article| %>
<%= render article %>
<p>
<%= link_to "Show this article", article %>
</p>
<% end %>
</div>
<%= link_to "New article", new_article_path %>
详情页面:
erb
<!-- app/views/articles/show.html.erb -->
<p style="color: green"><%= notice %></p>
<%= render @article %>
<div>
<%= link_to "Edit this article", edit_article_path(@article) %> |
<%= link_to "Back to articles", articles_path %>
<%= button_to "Destroy this article", @article, method: :delete %>
</div>
表单页面:
erb
<!-- app/views/articles/_form.html.erb -->
<%= form_with(model: article) do |form| %>
<% if article.errors.any? %>
<div style="color: red">
<h2><%= pluralize(article.errors.count, "error") %> prohibited this article from being saved:</h2>
<ul>
<% article.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= form.label :title, style: "display: block" %>
<%= form.text_field :title %>
</div>
<div>
<%= form.label :body, style: "display: block" %>
<%= form.text_area :body %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
四、添加数据验证 #
4.1 模型验证 #
ruby
# app/models/article.rb
class Article < ApplicationRecord
validates :title, presence: true,
length: { minimum: 5, maximum: 100 }
validates :body, presence: true,
length: { minimum: 10 }
end
4.2 测试验证 #
bash
# 启动Rails控制台
rails console
# 创建无效的文章
article = Article.new(title: "Hi", body: "Too short")
article.valid?
# => false
article.errors.full_messages
# => ["Title is too short (minimum is 5 characters)", "Body is too short (minimum is 10 characters)"]
# 创建有效的文章
article = Article.new(title: "My First Article", body: "This is the body of my first article.")
article.valid?
# => true
article.save
# => true
五、添加评论功能 #
5.1 生成Comment模型 #
bash
# 生成Comment模型
rails generate model Comment commenter:string body:text article:references
# 执行迁移
rails db:migrate
5.2 建立关联关系 #
ruby
# app/models/article.rb
class Article < ApplicationRecord
has_many :comments, dependent: :destroy
validates :title, presence: true,
length: { minimum: 5, maximum: 100 }
validates :body, presence: true,
length: { minimum: 10 }
end
# app/models/comment.rb
class Comment < ApplicationRecord
belongs_to :article
validates :commenter, presence: true
validates :body, presence: true
end
5.3 添加评论路由 #
ruby
# config/routes.rb
Rails.application.routes.draw do
resources :articles do
resources :comments
end
root 'welcome#index'
end
5.4 生成评论控制器 #
bash
rails generate controller Comments
5.5 评论控制器 #
ruby
# app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
@article = Article.find(params[:article_id])
@comment = @article.comments.create(comment_params)
redirect_to article_path(@article)
end
def destroy
@article = Article.find(params[:article_id])
@comment = @article.comments.find(params[:id])
@comment.destroy
redirect_to article_path(@article), status: :see_other
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
5.6 在文章页面显示评论 #
erb
<!-- app/views/articles/show.html.erb -->
<p style="color: green"><%= notice %></p>
<%= render @article %>
<h2>Comments</h2>
<div id="comments">
<% @article.comments.each do |comment| %>
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>
<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<p>
<%= link_to "Destroy Comment", [@article, comment],
data: {
turbo_method: :delete,
turbo_confirm: "Are you sure?"
} %>
</p>
<% end %>
</div>
<h2>Add a comment:</h2>
<%= form_with(model: [@article, @article.comments.build]) do |form| %>
<p>
<%= form.label :commenter %><br>
<%= form.text_field :commenter %>
</p>
<p>
<%= form.label :body %><br>
<%= form.text_area :body %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
<div>
<%= link_to "Edit this article", edit_article_path(@article) %> |
<%= link_to "Back to articles", articles_path %>
<%= button_to "Destroy this article", @article, method: :delete %>
</div>
六、添加样式 #
6.1 使用CSS #
css
/* app/assets/stylesheets/application.css */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
h1, h2, h3 {
color: #333;
}
.article {
background: white;
padding: 20px;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.comment {
background: #f9f9f9;
padding: 15px;
margin: 10px 0;
border-left: 3px solid #007bff;
}
form {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
input[type="text"],
textarea {
width: 100%;
padding: 10px;
margin: 5px 0;
border: 1px solid #ddd;
border-radius: 4px;
}
input[type="submit"] {
background: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
input[type="submit"]:hover {
background: #0056b3;
}
a {
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.notice {
background: #d4edda;
color: #155724;
padding: 10px;
border-radius: 4px;
margin-bottom: 20px;
}
.alert {
background: #f8d7da;
color: #721c24;
padding: 10px;
border-radius: 4px;
margin-bottom: 20px;
}
七、常用Rails命令 #
7.1 生成器命令 #
| 命令 | 说明 |
|---|---|
rails generate model |
生成模型 |
rails generate controller |
生成控制器 |
rails generate scaffold |
生成脚手架 |
rails generate migration |
生成迁移 |
rails generate resource |
生成资源 |
7.2 数据库命令 #
| 命令 | 说明 |
|---|---|
rails db:create |
创建数据库 |
rails db:drop |
删除数据库 |
rails db:migrate |
执行迁移 |
rails db:rollback |
回滚迁移 |
rails db:seed |
填充数据 |
rails db:reset |
重置数据库 |
7.3 服务器命令 #
| 命令 | 说明 |
|---|---|
rails server |
启动服务器 |
rails console |
启动控制台 |
rails runner |
执行Ruby代码 |
rails routes |
查看路由 |
rails stats |
查看统计信息 |
7.4 撤销生成 #
bash
# 撤销脚手架
rails destroy scaffold Article
# 撤销控制器
rails destroy controller Welcome
# 撤销模型
rails destroy model Comment
# 回滚迁移
rails db:rollback
八、项目测试 #
8.1 启动服务器 #
bash
rails server
8.2 访问页面 #
| URL | 说明 |
|---|---|
| http://localhost:3000 | 首页 |
| http://localhost:3000/articles | 文章列表 |
| http://localhost:3000/articles/new | 新建文章 |
| http://localhost:3000/articles/1 | 查看文章 |
| http://localhost:3000/articles/1/edit | 编辑文章 |
8.3 测试CRUD操作 #
- 访问文章列表页面
- 点击"New article"创建新文章
- 填写标题和内容,点击提交
- 查看文章详情
- 添加评论
- 编辑文章
- 删除文章
九、调试技巧 #
9.1 使用Rails控制台 #
bash
# 启动控制台
rails console
# 查询数据
Article.all
Article.first
Article.find_by(title: "My First Article")
# 创建数据
Article.create(title: "Test", body: "Test body")
# 更新数据
article = Article.first
article.update(title: "New Title")
# 删除数据
article.destroy
9.2 使用debug方法 #
erb
<!-- 在视图中调试 -->
<%= debug(params) %>
<%= debug(@article) %>
9.3 使用byebug #
ruby
# 在控制器中设置断点
def show
@article = Article.find(params[:id])
byebug # 程序会在这里暂停
end
9.4 查看日志 #
bash
# 查看开发日志
tail -f log/development.log
# 查看SQL查询
# 在日志中可以看到所有执行的SQL语句
十、总结 #
10.1 核心要点 #
| 要点 | 说明 |
|---|---|
| 创建项目 | rails new app_name |
| 生成脚手架 | rails generate scaffold Model field:type |
| 数据库迁移 | rails db:migrate |
| 启动服务器 | rails server |
| 路由配置 | config/routes.rb |
| 模型验证 | validates 方法 |
10.2 下一步 #
现在你已经创建了第一个Rails应用,接下来让我们学习 项目结构,深入了解Rails项目的组织方式!
最后更新:2026-03-28