Rails
大约 8 分钟
Rails
- Rails 是用 Ruby 编程语言编写的 Web 应用程序开发框架。
入门
gem install rails
rails --version
sqlite3 --version
rails new hello-rails
- 启动
bin/rails server
- 一键生成:
bin/rails generate controller HelloRails index
- HelloRails 自动转下划线风格分割 hello_rails
- 控制器:hello_rails_controller.rb
- 路由:hello_rails/index
- 视图:app/views/hello_rails/index.html.erb
- 配置主页 / ,设置路由
vi config/routes.rb
- 使用 # 符号
hello_rails/index
>'hello_rails#index'
# config/routes.rb
Rails.application.routes.draw do
get 'hello_rails/index'
root 'hello_rails#index'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
说明
bin/rails generate controller HelloRails index
create app/controllers/hello_rails_controller.rb
route get 'hello_rails/index'
invoke erb
create app/views/hello_rails
create app/views/hello_rails/index.html.erb
invoke test_unit
create test/controllers/hello_rails_controller_test.rb
invoke helper
create app/helpers/hello_rails_helper.rb
invoke test_unit
- 目录介绍
bundler
- 安装依赖
- 依据 Gemfile 文件 自动安装依赖
bundle install
- Gemfile 示例
source 指定源
gem 安装的包及版本
source 'https://rubygems.org'
gem 'nokogiri'
入门实践
- 举例 对用户管理,用户CURD
- 创建控制器
- 创建动作
- 创建视图
- 参数处理
- 创建模型:生成迁移文件
- 运行迁移:生成表
- 保存数据
- 显示数据
- 视图链接
- 表单验证
- 错误回显
- 视图布局,局部代码,代码复用,如相同form表单
- 删除数据
- 模型关联
- 级连操作
- 安全,如安全认证
资源 resources
- Rails 提供了 resources 方法,用于声明标准的 REST 资源。
- 如声明 用户 的资源
resources :users
config/routes.rb
Rails.application.routes.draw do
get 'welcome/index'
resources :users
root 'welcome#index'
end
资源路由
- Rails 能够推导出 如资源 users 的路由
- 执行命令
bin/rails routes
路由 Routes
- 命令: 列出所有路由
bin/rails routes
- 也会列出 声明资源的路由 推导出资源路由 见 资源路由
控制器 Controller
控制器实际上只是一个继承自 ApplicationController 的类。
自动创建控制器
命令:
bin/rails generate controller Users
app/controllers/users_controller.rb
class UsersController < ApplicationController
end
动作 Action
- 在控制器中手动定义动作,只需要定义一个新方法。
- 如定义创建用户页面
class UsersController < ApplicationController
def new
end
end
参数处理
- 如创建表单,定义创建action ,获取参数
- render 方法接受了一个简单的散列(hash)作为参数
- :plain 键的值是 params[:user].inspect。
- params 方法是代表表单提交的参数(或字段)的对象。
- params 方法返回 ActionController::Parameters 对象,这个对象允许使用字符串或符号访问散列的键。
def create
render plain: params[:user].inspect
end
- 查看该动作的响应信息
#<ActionController::Parameters {"username"=>"11", "password"=>"11", "user_desc"=>"11"} permitted: false>
- render plain: params[:user][:username].inspect
render plain: params[:user][:username].inspect
保存数据
- 在创建action中保存数据
- Rails 模型可以用相应的属性初始化,它们会自动映射到对应的数据库字段。
@user = User.new(params[:user])
@article.save
负责把模型保存到数据库。最后把页面重定向- User.new 中 User 为模型
- Rails 模型可以用相应的属性初始化,它们会自动映射到对应的数据库字段。
def create
@user = User.new(params[:user])
@user.save
redirect_to @user
end
健壮参数
Rails 提供了多种安全特性来帮助我们编写安全的应用,健壮参数就是一种安全特性。
如进行上述保存数据,操作会报错
ActiveModel::ForbiddenAttributesError in UsersController#create
- 要求我们明确地告诉 Rails 哪些参数允许在控制器动作中使用。
- 避免有人对服务器发起了一个精心设计的请求,看起来就像提交了一篇新文章,但同时包含了能够破坏应用完整性的额外字段和值,会怎么样?这些恶意数据会批量赋值给模型,然后和正常数据一起进入数据库,这样就有可能破坏我们的应用或者造成更大损失。
@user = User.new(params.require([:user]).permit(:username, :nickname, :password, :user_desc))
- 所以我们只能为控制器参数设置白名单,以避免错误地批量赋值。
- 我们想在 create 动作中合法使用 需要的 参数,为此需要使用 require 和 permit 方法。
方法抽象
- 如上述 健壮参数只获取我们需要的字段,将该步骤抽象为一个方法 user_params
- private: 禁止从外部调用此方法
def create
@user = User.new(user_params)
@user.save
redirect_to @user
end
private
def user_params
params.require(:user).permit(:username, :nickname, :password, :user_desc)
end
数据展示
@user
@对象 :表示 返回一个对象@user = User.new
返回一个空对象通过 bin/rails routes 可以看到,users资源 的展示动作为show 见资源路由
- 控制器创建 show, 视图 创建 users/show.html.erb
查询数据 ID 为 1 的
/users/1
def show
@user = User.find(params[:id])
end
- 展示所有用户
- /users ,查看对应动作 bin/rails routes:index
- 视图 index.html.erb
def index
@users = User.all
end
render vs redirect_to
- 注意在 create 动作中,当 save 返回 false 时,我们用 render 代替了 redirect_to。
- render 方法是为了把 @article 对象回传给 new 模板。这里渲染操作是在提交表单的这个请求中完成的,
- redirect_to 会告诉浏览器发起另一个请求。
- 见数据验证部分应用
视图模版 view template
当在路由中声明了 users 资源,创建了控制器并定义了 new 动作
- 此时路由会指向 new 的一个视图模版
- 报错信息:UsersController#new is missing a template for request formats: text/html
- app/controllers/users_controller.rb should have a corresponding view template in a file named app/views/users/new.html.erb.
app/views/users/new.html.erb
- 第一个扩展名是模板格式 html
- 第二个扩展名是模板处理器
- erb 是最常用的 HTML 模板处理器
- builder 是 XML 模板处理器
- coffee 模板处理器用 CoffeeScript 创建 JavaScript 模板
表单构造器
- 参考 form_for 的文档。
- 在模板中创建表单,可以使用表单构建器。
- Rails 中最常用的表单构建器是 form_for 辅助方法。
- 用户表单
- 需要为表单传递一个标识对象作为参数
- 第一个参数为对象
- :user 表单用于处理哪个对象
- f 表示 FormBuilder 对象
- f 对象上调用 submit 方法来为表单创建提交按钮
- 默认表单提交的地址为 /users/new ,但这个路由是进入到new页面的
- 第二个参数,url: users_path
- 告诉 Rails 把表单指向和 users 前缀相关联的 URI 模式
- 此时提交表单路由会指向create 见资源路由
- 控制器定义 动作 create ,否则报错:
AbstractController::ActionNotFound (The action 'create' could not be found for UsersController):
- 告诉 Rails 把表单指向和 users 前缀相关联的 URI 模式
- 第一个参数为对象
- 需要为表单传递一个标识对象作为参数
<%= form_for :user, url: users_path do |f| %>
<p>
<%= f.label :用户名 %><br>
<%= f.text_field :username %>
</p>
<p>
<%= f.label :用户密码 %><br>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :用户描述 %><br>
<%= f.text_area :user_desc %>
</p>
<p>
<%= f.submit :创建用户%>
</p>
<% end %>
添加链接
- link_to: Rails 内置的视图辅助方法之一,用于创建基于链接文本和地址的超链接。
<%= link_to '查看用户列表', controller: 'users' %>
<%= link_to '创建用户', new_user_path %>
链接到当前控制器的动作时不需要指定 :controller 选项,因为 Rails 默认使用当前控制器。
错误回显
- 如创建用户时,用户名长度验证,没有通过
- 状态返回 422 Unprocessable Content
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render :new, status: :unprocessable_entity
end
end
- 视图错误字段回显
- pluralize
- Rails 提供的辅助方法
- 接受一个数字和一个字符串作为参数。如果数字比 1 大,字符串会被自动转换为复数形式。
- 发现 <%= pluralize(@user.errors.count, "error") %> ,创建异常。
- 发现 2 errors ,创建异常。
- 发现 1 error ,创建异常。
- 中文 会加s: 发现 2 错误s ,创建异常。
- pluralize
<%= form_for :user, url: users_path do |f| %>
<% if @user.errors.any? %>
<div id="error_explanation">
<h2>
发现 <%= pluralize(@user.errors.count, "error") %> ,创建异常。
</h2>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :登录用户名 %><br>
<%= f.text_field :username %>
<% @user.errors.full_messages_for(:username).each do |message| %>
<div><%= message %></div>
<% end %>
</p>
Rails 布局和视图渲染
- 如编辑和新建用户页面,都使用一致的表单
- 抽取form重复代码
- 创建 app/views/users/_form.html.erb
- 其他页面引用
<%= render 'form' %>
对象(资源)模型
- 创建如 用户 对象 模型
bin/rails generate model User username:string nickname:string password:string user_desc:text
- active_record
- Active Record 很智能,能自动把数据表的字段名映射到模型属性上,因此无需在 Rails 模型中声明属性,让 Active Record 自动完成即可。
invoke active_record
create db/migrate/20231210064012_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
迁移 Active Record
- 迁移是用于简化创建和修改数据库表操作的 Ruby 类;
- Rails 使用 rake 命令运行迁移,并且在迁移作用于数据库之后还可以撤销迁移操作。
- 迁移的文件名包含了时间戳,以确保迁移按照创建时间顺序运行。
- db/migrate/YYYYMMDDHHMMSS_create_users.rb
- bin/rails generate model 命令会在 db/migrate 文件夹中生成数据库迁移文件。
- db/migrate/20231210064012_create_users.rb
class CreateUsers < ActiveRecord::Migration[7.1]
def change
create_table :users do |t|
t.string :username
t.string :nickname
t.string :password
t.text :user_desc
t.timestamps
end
end
end
- 生成迁移文件后,执行 bin/rails db:migrate
- 生成用户表
- 默认情况下我们是在开发环境中工作
- 命令应用于 config/database.yml 文件中 development 部分定义的的数据库。
- 也可显示指定环境
bin/rails db:migrate RAILS_ENV=production
- 也可显示指定环境
bin/rails db:migrate
== 20231210064012 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0044s
== 20231210064012 CreateUsers: migrated (0.0045s) =============================
数据验证
- 模型文件简单到只有两行代码
class User < ApplicationRecord
end
- User 继承自 ApplicationRecord 类
- ApplicationRecord 继承自 ActiveRecord::Base 类
- Base 类为 Rails 模型提供了大量功能
- 基本的数据库 CRUD 操作(创建、读取、更新、删除)、数据验证,以及对复杂搜索的支持和关联多个模型的能力。
- 对用户名进行验证
- User,用户名必填,至少5位
class User < ApplicationRecord
validates :username, presence: true, length: {minimum: 5}
end
- 判断处理
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render 'new'
end
end
对象操作
- 创建空对象
User.new
- 根据参数提交对象
User.new(user_params)
- 保存对象
@user.save
- 保存对象
- 查找对象
@user = Article.find(params[:id])
- 删除对象 *
@user.destroy
- 删除对象 *
- 查找所有对象
User.all
模型关联
- 生成日志模型关联用户
- bin/rails generate model Log log_key:string log_content:text user:references
- 表示日志输入用户
- belongs_to
- 自动生成关联表
bin/rails db:migrate
,参考 迁移 Active Record - 可以在User中加 关联关系 has_many
- 级连删除:
dependent: :destroy
- 级连删除:
安全
基本身份验证
http_basic_authenticate_with
UsersController
- 动作认证,除了index 和 show
http_basic_authenticate_with name: "root", password: "123456", except: [:index, :show]
参考官方文档Active Record 数据验证