文章目录
1.controller 是什么?
- Action Controller 是 MVC 中的 C(控制器)。
- 路由器决定使用哪个控制器处理请求后,控制器负责解析请求,生成相应的输出。
- 所有的controller都继承自actionController::base
2. 控制器命名约定
- Rails 控制器的命名约定是,最后一个单词使用复数形式,如: SiteAdminsController,而不是 SiteAdminController 或 SitesAdminsController。但也有例外,如:ApplicationController
- 遵守这一约定便可享用默认的路由生成器(例如 resources 等),无需再指定 :path 或 :controller 选项,而且 URL 和路径的辅助方法也能保持一致性。
- 控制器的命名约定与模型不同,模型的名字习惯使用单数形式。
3.参数
在rails中,get与post请求参数均是通过params获取。
3.1 数组:
GET /clients?ids[]=1&ids[]=2&ids[]=3
此时,params[:ids] 的值是 [“1”, “2”, “3”]
3.2 散列
在方括号内指定键名,可借助form_for
<input type="text" name="client[name]" value="Acme" />
<input type="text" name="client[phone]" value="12345" />
params[:client] 的值是 { “name” => “Acme”, “phone” => “12345”}
3.3 JSON
{ "company": { "name": "acme", "address": "123 Carrot Street" } }
3.4 路由参数
get '/clients/:status' => 'clients#index', foo: 'bar'
params 散列始终有 :controller 和 :action 两个键,params[:foo] 的值会被设为 “bar”,params[:action],其值为 “index”,以及 params[:controller],其值为 “clients”
3.5 健壮参数
Action Controller 的参数禁止在 Avtive Model 中批量赋值,除非参数在白名单中。以防不小心允许用户更新模型中敏感的属性。
params.permit(:id)
若 params 中有 :id 键,且 :id 是标量值,就可以通过白名单检查;否则 :id 会被过滤掉。因此,不能传入数组、散列或其他对象。
若想允许传入整个参数散列,可以使用 permit! 方法:
params.require(:log_entry).permit!
4.会话
应用中的每个用户都有一个会话(session),用于存储少量数据,在多次请求中永久存储。会话只能在控制器和视图中使用,可以通过以下几种存储机制实现:
- ActionDispatch::Session::CookieStore:所有数据都存储在客户端cookie中(默认也是推荐使用的存储方式)
- ActionDispatch::Session::CacheStore:数据存储在 Rails 缓存里,会话中不存储重要的数据,或者不需要持久存储(例如存储闪现消息)
- ActionDispatch::Session::ActiveRecordStore:使用 Active Record 把数据存储在数据库中(需要使用 activerecord-session_store gem)
- ActionDispatch::Session::MemCacheStore:数据存储在 Memcached集群中(这是以前的实现方式,现在应该改用 CacheStore)
签署会话数据时,还可以传入 :domain 键,指定可使用此 cookie 的域名:
Rails.application.config.session_store :cookie_store, key: '_your_app_session', domain: ".example.com"
4.1 访问会话 session
- 会话中的数据以键值对的形式存储
session[:current_user_id]
- 删除会话中数据,把键的值设为 nil
session[:current_user_id] = nil
4.2 闪现消息flash
- 闪现消息是会话的一个特殊部分,其中存储的数据只能在下次请求时使用,因此可用于传递错误消息等
flash[:notice] = "You have successfully logged out."
- 重定向也可以设置闪现消息。可以指定 :notice、:alert 或者常规的 :flash:
redirect_to root_url, notice: "You have successfully logged out."
redirect_to root_url, alert: "You're stuck here!"
redirect_to root_url, flash: { referral_code: 1234 }
- flash.keep
闪现消息保留到其他请求 - flash.now
默认情况下,闪现消息中的内容只在下一次请求中可用,但有时希望在同一个请求中使用,针对这种情况,可以使用 flash.now
5.cookies
- 应用可以在客户端存储少量数据(称为 cookie,通过cookies访问
- 删除会话中的数据是把键的值设为 nil,但若想删除 cookie 中的值,要使用 cookies.delete(:key) 方法。
cookies.delete(:current_user_id)
6.渲染 XML 和 JSON 数据
def index
@users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render xml: @users}
format.json { render json: @users}
end
end
我们使用的是 render xml: @users 而不是 render xml: @users.to_xml。如果不是字符串对象,Rails 会自动调用 to_xml 方法。
7. 过滤器
- 过滤器(filter)是一种方法,在控制器动作运行之前、之后,或者前后运行。
- 过滤器会继承,如果在 ApplicationController 中定义了过滤器,那么应用的每个控制器都可使用。
before_action :require_login
如果想跳过某个动作,可以使用 skip_before_action:
skip_before_action :require_login, only: [:new, :create]
:only 选项的意思是只跳过这些动作。此外,还有个 :except 选项,用法类似。定义过滤器时也可使用这些选项,指定只在选中的动作上运行。
8.HTTP 身份验证
- HTTP 基本身份验证 http_basic_authenticate_with
http_basic_authenticate_with name: "humbaba", password: "5baa61e4"
添加 http_basic_authenticate_with 方法后,可以创建具有命名空间的控制器,继承自 AdminsController,http_basic_authenticate_with 方法会在这些控制器的所有动作运行之前执行,启用 HTTP 基本身份验证。(???创建控制器)
- HTTP 摘要身份验证 authenticate_or_request_with_http_digest
authenticate_or_request_with_http_digest do |username| USERS[username]
authenticate_or_request_with_http_digest 方法的块只接受一个参数,用户名,返回值是密码。如果 authenticate_or_request_with_http_digest 返回 false 或 nil,表明身份验证失败。
9.数据流和文件下载
10.日志过滤
- 参数过滤
可以在应用的配置文件(initializers/filter_parameter_logging.rb)中设置 config.filter_parameters 选项。过滤掉的参数在日志中显示为 [FILTERED]。
config.filter_parameters << :password
注:password不需要手动加,构建项目时自动就会生成。
- 重定向过滤
有时需要从日志文件中过滤掉一些重定向的敏感数据,此时可以设置 config.filter_redirect 选项:
config.filter_redirect << 's3.amazonaws.com'
11.异常处理
捕获错误后如果想做更详尽的处理,可以使用 rescue_from。rescue_from 可以处理整个控制器及其子类中的某种(或多种)异常。
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
rescue_from User::NotAuthorized, with: :user_not_authorized
private
def record_not_found
render plain: "404 Not Found", status: 404
end
# 如果用户没有授权,抛出异常
def check_authorization
raise User::NotAuthorized unless current_user.admin?
end
end
12.强制使用 HTTPS 协议
基于安全考虑,可能希望某个控制器只能通过 HTTPS 协议访问。为了达到这一目的,可以在控制器中使用 force_ssl 方法:
class DinnerController
force_ssl only: :cheeseburger
# 或者
force_ssl except: :cheeseburger
end