控制器内部对请求的操作
一Action方法
1调用方式
控制器处理请求时会找到与之名字匹配的action.
调用method_missing(),如果找不到action
调用模版,如果找不到action和method_missing()
调用错误报告Unknown Action如果上述都不符合
2禁止调用
将action声明为protected或private,也可以不改变私有性声明为hidden_action :XXX
3控制器环境
action_name 当前处理的action名称
cookies与请求相关的cookie,相应时对象设置的值将保存到客户机上
headers一个类似于hash的对象,代表HTTP头信息,这些信息用于应答
params一个类似于hash的对象,存放着请求参数
request进入控制器的请求对象,包含属性:
domain 返回请求地址中域名部分的最后两段
remote_ip一字符串形式返回客户端IP,若有代理则包含多个IP地址
env返回客户浏览器设置的环境变量值如:request.env[‘XXX’]
method返回客户端所使用的请求方法:delete,put,get,post….
delete?,get?,head?,post?,put?返回是否为该方法:true or false
xml_http_request?和xhr?,请求来自AJAX则返回true 与method值无关
response代表HTTP应答的对象,在处理时rails填充这个对象
session一个类似与hash的对象,代表当前的session数据
4应答
模版的渲染(render:)
Rails内建支持3中模版:.rhtml格式内嵌ruby代码的HTML代码;构造器XML内容的方式;rjs,用于生成JavaScript
通过定义ActionController::Base.template_root=dir_path改变视图根路径,默认的视图根路径为:app/views
render(:text=>string)将指定字符串发送给客户端
render(:inline=>string,:type=>”rhtml”/”rxml”/”rjs”,:locals=>hash)把string内容作为指定的type模版进行渲染,:locals提供局部模版中的变量
render(:action=>action_name,:locals=>hash)渲染控制器中指定的action对应的模版
render(:file=>path,:use_full_path=>true/false,:locals=>hash)渲染指定路径的模版, 若设置:use_full_path=>true,则变为相对路径的方式寻找
render(:template=>name) template必须同事包含控制器名和action名
render(:partial=>name) 渲染一个局部模版
render(:js=>”alert(‘xxx’)”) 将返回text/javascript格式
render(:nothing=>true) 什么都不返回---返回一片空白给浏览器
render(:xml=>stuff) 以xml格式渲染,stuff将被强制转换为xml格式
render(:json=>stuff) 以json格式渲染,stuff将被强制转换为json格式
render(:update) do |page| …end以rjs模版渲染 从略
文件下载(send_data,send_file)
send_data(data, options)发送一个二进制数据流给客户端
send_file(path, options)发送一个文件内容给客户端
重定向(redirect_to)
Redirect_to(:action, options)options可以提供params的值
Redirect_to(:back)返回前一个action
5 cookie和session
cookie
cookie的创建:cookie的值必须是字符串
Cookies[:name]={:value=>值,:domain=>”http://www.xxx.com”,:path=>”/store”,: expires =>””,:secure=>”secure”/”空串” }
domain属性用来设置所定义的Cookie变量的域,设置不同变量的域可以防止不同网站之间的Cookie相互冲突
path属性用来设置所定义的Cookie变量的文件路径,请求为此路径时cookie才有效
expires属性来设置它的生命期限。
secure属性为secure或为空,WEB服务器之间就通过HTTPS或者其它安全协议传递数据
session
与cookie不同session是保存在服务器端的。建立会话后应用会为session分配一个session_id,他将保存在cookie中以便用户对session的访问以及修改
Session中可以保存任意可以被序列化的对象。存储ActiveRecord对象需在控制器中加入声明——model : session的键,在声明的控制器引用session便可为模型对象进行序列化和反序列化的操作
1)Session自定义属性:可在config/environment中设置config.action_controller.session.option的hash
:session_domain 用于保存session_id的cookie作用域,默认为当前应用域名
:session_id如果不设置此项,新建session会自动得到一个32字长的id
:session_key用于保存session id的cookie名称
:session_path有效的路径范围。默认值是/,既整个域名内有效
:session_secure如果设为true,则只有当用http://开头的地址访问时session生效
2)Session的存储
在config/environment中设置config.active_record.session_store的值来指定存储机制,这个值由CGI::Session模块中定义,除PStore与默认的cookiestore,其他存储策略直接符号引用
session_store=CGI::Session:PStore方式
数据保存到PStore格式的文件中,2.x后被遗弃的方式
session_store=:active_record_store
数据保存到数据库,通过rake db:sessions:create建立session表迁移任务。2.x后开启此模式若同时需要csrf保护,需要设置csrf密钥
session_store=:drb_store
数据保存到非web应用之外的服务器(而通过服务器这些数据又可以存储到不同的物理位置,google采用了这种水平伸缩的吞吐)
其他存储方式是不推荐作为B/S架构的存储方式。
3)session的过期
人工session过期可以使用reset_session(),是一种主动清除的策略;如果采用非cookiestore可以服务器删除过期session的策略
Flash
Flash有session类似的功能,区别在于flash所记忆的内容只能提供给跳转后的下一个action,所以我经常把flash又叫做小session
Flash的两个方法:
flash.now[:key]=value此flash将能通过跳转传到下个action
成功跳转后在跳转后的action定义:flash.keep[:key]=value将保持传递性,将再传递到下一个action,从而实现了2次跳转仍然保持原数据。
6过滤器与校验
1)前置、后置、环绕过滤
before_filter: 前置
after_filter: 后置
around_filter: 环绕
注:一个controller中有多个前置、后置过滤器时,加入一个前置或后置过滤都将会添加到所有以添加的过滤器后,既先执行其他过滤后在执行 新加入的前置或后置过滤。若希望新加入的先被执行则前置:prepend_before_filter,后置:prepend_after_filter
环绕过滤与上述不同,当controller中有多个环绕过滤时,新加入的环绕则嵌套在其他环绕过滤中,就如同大家见过的嵌套循环的结构一样
2)过滤形式
过滤方法:定义一个过滤方法通过xxx_filter: method引用,注:环绕过滤内部要用yield引入要执行的action
过滤模块: xxx_filter do |some_params|
some_params为控制器参数
end
注:环绕过滤还要传入另一个参数,该参数的call方法将执行过滤的action
过滤类:定义一个类,并创建类方法filter(some_params),过滤声明为xxx_filter 类,
当过滤器被调用,则类的filter方法被调用,并传入控制器参数。注:环绕过滤需要在filter类方法中定义yield
3)过滤的有效范围
xxx_filter:some_method,:only=>[:one_action,:two_action]指定需要过滤的action
xxx_filter:some_method,:except=>[:one_action,:two_action]指定不需要过滤的action
4)rails提供的内置过滤校验
例:
verify :only=> :some_action #需要过滤验证的内容
:session=>:some_key #判断会话中有some_key的键值
:add_flash=>{:note=>”some_noties”} #上个条件不成立flash添加此信息
:redirect=>:some_action #条件不成立跳转的action
有效范围 :only=> :some_action 需要过滤的action
:except=> :some_action 不需要过滤的action
检查条件 :flash=>:key #flash中是否包含指定的键
:method=>:symbol #请求方法(get、post、put等)
:params=>:key #请求参数中包含指定的键
:session=>:key #session中是否包含指定的键
:xhr=>true or false #请求是否来自AJAX
动作 :add_flash=>hash #将指定的hash放入flash
:add_headers=>hash #应答头信息放入hash的内容
:redirect_to=>url_for,params #根据条件跳转
:render=>params #根据条件渲染模版
7缓存处理
三种缓存机制:
页面缓存:将整个渲染后的页面放入缓存,后续调用直接调用缓存
Action缓存:需经过filter后将action放入缓存,后续访问通过过滤后若有此
缓存,则直接调用缓存
片段缓存:后面介绍
1)缓存钩子(控制器中)
caches_page :some_action #设定某个action的页面缓存
caches_action :some_action #设定某个action的action缓存
注:缓存只要在生产模式被开启,手动设置为在environement.rb中设置
config.action_controller.perform_caching=true,这里特别要注意,不是所有内容都能缓存,对于可变性很大的内容最好不要缓存,这个需要根据开发经验而定
2)手工清除缓存
缓存的内容被更新后,对于用户缓存的内容没有任何意义,并且没用的缓存会占用大量的资源。
expire_page :some_action #清除指定action的页面缓存
expire_action :some_action #清除指定action的页面缓存
3)缓存清扫器
人工清理缓存对于大型项目势必要漏清,这里引入清理器,清扫器应该放在model下
class SomeModelSweeper < ActionController::Caching::Sweeper
observe Article #设置要监视的模型
#表中添加新数据后执行页面缓存清理
def after_create(article)
expire_public_page
end
#表中数据被更新后执行action缓存清理
def after_update(article)
expire_article_page(article.id)
end
#表中数据被删除一条或多条时同事执行页面、action缓存清理
def after_destroy(article)
expire_public_page
expire_article_page(article.id)
end
private
def expire_public_page
expire_page(:controller => "content" , :action => 'public_content' )
end
def expire_article_page(article_id)
expire_action(:controller => "content" ,
:action => "premium_content" ,
:id => article_id)
end
end
控制器中的清理器钩子(在控制器中)
cache_sweeper :article_sweeper, #开启Article清理器
:onlye=>:some_action #监视的控制器
:except=>:some_action #忽略的控制器
注:若要对可变性较大内容进行缓存需要引入时间缓存失效策略:通过操作系统编写定时删除缓存的进程来控制
8CSRF安全策略
Rails2.x后引入了防止跨域访问攻击的pluging,具体操作如下
在控制器中定义protect_from_forgery钩子,在模版中使用form_for等标签时,服务器会在生成form_for等标签时 建立一个密钥(token),服务器会监视request回来的所有post以及AJAX行为,如果request没有token或者与服务器计算出的不 一致,将返回错误信息。
cookiestore的session存储机制下,token是根据CGI::Session.generate_unique_id生成的随即数并进行编码得到的,所以不需要为protect_from_forgery设置secret的键值
:active_record_store是根据session_id、protect_from_forgery的secret的值以及digest(默认是SHA1)计算得来,所以要为这种session机制设置secret值。
一Action方法
1调用方式
控制器处理请求时会找到与之名字匹配的action.
调用method_missing(),如果找不到action
调用模版,如果找不到action和method_missing()
调用错误报告Unknown Action如果上述都不符合
2禁止调用
将action声明为protected或private,也可以不改变私有性声明为hidden_action :XXX
3控制器环境
action_name 当前处理的action名称
cookies与请求相关的cookie,相应时对象设置的值将保存到客户机上
headers一个类似于hash的对象,代表HTTP头信息,这些信息用于应答
params一个类似于hash的对象,存放着请求参数
request进入控制器的请求对象,包含属性:
domain 返回请求地址中域名部分的最后两段
remote_ip一字符串形式返回客户端IP,若有代理则包含多个IP地址
env返回客户浏览器设置的环境变量值如:request.env[‘XXX’]
method返回客户端所使用的请求方法:delete,put,get,post….
delete?,get?,head?,post?,put?返回是否为该方法:true or false
xml_http_request?和xhr?,请求来自AJAX则返回true 与method值无关
response代表HTTP应答的对象,在处理时rails填充这个对象
session一个类似与hash的对象,代表当前的session数据
4应答
模版的渲染(render:)
Rails内建支持3中模版:.rhtml格式内嵌ruby代码的HTML代码;构造器XML内容的方式;rjs,用于生成JavaScript
通过定义ActionController::Base.template_root=dir_path改变视图根路径,默认的视图根路径为:app/views
render(:text=>string)将指定字符串发送给客户端
render(:inline=>string,:type=>”rhtml”/”rxml”/”rjs”,:locals=>hash)把string内容作为指定的type模版进行渲染,:locals提供局部模版中的变量
render(:action=>action_name,:locals=>hash)渲染控制器中指定的action对应的模版
render(:file=>path,:use_full_path=>true/false,:locals=>hash)渲染指定路径的模版, 若设置:use_full_path=>true,则变为相对路径的方式寻找
render(:template=>name) template必须同事包含控制器名和action名
render(:partial=>name) 渲染一个局部模版
render(:js=>”alert(‘xxx’)”) 将返回text/javascript格式
render(:nothing=>true) 什么都不返回---返回一片空白给浏览器
render(:xml=>stuff) 以xml格式渲染,stuff将被强制转换为xml格式
render(:json=>stuff) 以json格式渲染,stuff将被强制转换为json格式
render(:update) do |page| …end以rjs模版渲染 从略
文件下载(send_data,send_file)
send_data(data, options)发送一个二进制数据流给客户端
send_file(path, options)发送一个文件内容给客户端
重定向(redirect_to)
Redirect_to(:action, options)options可以提供params的值
Redirect_to(:back)返回前一个action
5 cookie和session
cookie
cookie的创建:cookie的值必须是字符串
Cookies[:name]={:value=>值,:domain=>”http://www.xxx.com”,:path=>”/store”,: expires =>””,:secure=>”secure”/”空串” }
domain属性用来设置所定义的Cookie变量的域,设置不同变量的域可以防止不同网站之间的Cookie相互冲突
path属性用来设置所定义的Cookie变量的文件路径,请求为此路径时cookie才有效
expires属性来设置它的生命期限。
secure属性为secure或为空,WEB服务器之间就通过HTTPS或者其它安全协议传递数据
session
与cookie不同session是保存在服务器端的。建立会话后应用会为session分配一个session_id,他将保存在cookie中以便用户对session的访问以及修改
Session中可以保存任意可以被序列化的对象。存储ActiveRecord对象需在控制器中加入声明——model : session的键,在声明的控制器引用session便可为模型对象进行序列化和反序列化的操作
1)Session自定义属性:可在config/environment中设置config.action_controller.session.option的hash
:session_domain 用于保存session_id的cookie作用域,默认为当前应用域名
:session_id如果不设置此项,新建session会自动得到一个32字长的id
:session_key用于保存session id的cookie名称
:session_path有效的路径范围。默认值是/,既整个域名内有效
:session_secure如果设为true,则只有当用http://开头的地址访问时session生效
2)Session的存储
在config/environment中设置config.active_record.session_store的值来指定存储机制,这个值由CGI::Session模块中定义,除PStore与默认的cookiestore,其他存储策略直接符号引用
session_store=CGI::Session:PStore方式
数据保存到PStore格式的文件中,2.x后被遗弃的方式
session_store=:active_record_store
数据保存到数据库,通过rake db:sessions:create建立session表迁移任务。2.x后开启此模式若同时需要csrf保护,需要设置csrf密钥
session_store=:drb_store
数据保存到非web应用之外的服务器(而通过服务器这些数据又可以存储到不同的物理位置,google采用了这种水平伸缩的吞吐)
其他存储方式是不推荐作为B/S架构的存储方式。
3)session的过期
人工session过期可以使用reset_session(),是一种主动清除的策略;如果采用非cookiestore可以服务器删除过期session的策略
Flash
Flash有session类似的功能,区别在于flash所记忆的内容只能提供给跳转后的下一个action,所以我经常把flash又叫做小session
Flash的两个方法:
flash.now[:key]=value此flash将能通过跳转传到下个action
成功跳转后在跳转后的action定义:flash.keep[:key]=value将保持传递性,将再传递到下一个action,从而实现了2次跳转仍然保持原数据。
6过滤器与校验
1)前置、后置、环绕过滤
before_filter: 前置
after_filter: 后置
around_filter: 环绕
注:一个controller中有多个前置、后置过滤器时,加入一个前置或后置过滤都将会添加到所有以添加的过滤器后,既先执行其他过滤后在执行 新加入的前置或后置过滤。若希望新加入的先被执行则前置:prepend_before_filter,后置:prepend_after_filter
环绕过滤与上述不同,当controller中有多个环绕过滤时,新加入的环绕则嵌套在其他环绕过滤中,就如同大家见过的嵌套循环的结构一样
2)过滤形式
过滤方法:定义一个过滤方法通过xxx_filter: method引用,注:环绕过滤内部要用yield引入要执行的action
过滤模块: xxx_filter do |some_params|
some_params为控制器参数
end
注:环绕过滤还要传入另一个参数,该参数的call方法将执行过滤的action
过滤类:定义一个类,并创建类方法filter(some_params),过滤声明为xxx_filter 类,
当过滤器被调用,则类的filter方法被调用,并传入控制器参数。注:环绕过滤需要在filter类方法中定义yield
3)过滤的有效范围
xxx_filter:some_method,:only=>[:one_action,:two_action]指定需要过滤的action
xxx_filter:some_method,:except=>[:one_action,:two_action]指定不需要过滤的action
4)rails提供的内置过滤校验
例:
verify :only=> :some_action #需要过滤验证的内容
:session=>:some_key #判断会话中有some_key的键值
:add_flash=>{:note=>”some_noties”} #上个条件不成立flash添加此信息
:redirect=>:some_action #条件不成立跳转的action
有效范围 :only=> :some_action 需要过滤的action
:except=> :some_action 不需要过滤的action
检查条件 :flash=>:key #flash中是否包含指定的键
:method=>:symbol #请求方法(get、post、put等)
:params=>:key #请求参数中包含指定的键
:session=>:key #session中是否包含指定的键
:xhr=>true or false #请求是否来自AJAX
动作 :add_flash=>hash #将指定的hash放入flash
:add_headers=>hash #应答头信息放入hash的内容
:redirect_to=>url_for,params #根据条件跳转
:render=>params #根据条件渲染模版
7缓存处理
三种缓存机制:
页面缓存:将整个渲染后的页面放入缓存,后续调用直接调用缓存
Action缓存:需经过filter后将action放入缓存,后续访问通过过滤后若有此
缓存,则直接调用缓存
片段缓存:后面介绍
1)缓存钩子(控制器中)
caches_page :some_action #设定某个action的页面缓存
caches_action :some_action #设定某个action的action缓存
注:缓存只要在生产模式被开启,手动设置为在environement.rb中设置
config.action_controller.perform_caching=true,这里特别要注意,不是所有内容都能缓存,对于可变性很大的内容最好不要缓存,这个需要根据开发经验而定
2)手工清除缓存
缓存的内容被更新后,对于用户缓存的内容没有任何意义,并且没用的缓存会占用大量的资源。
expire_page :some_action #清除指定action的页面缓存
expire_action :some_action #清除指定action的页面缓存
3)缓存清扫器
人工清理缓存对于大型项目势必要漏清,这里引入清理器,清扫器应该放在model下
class SomeModelSweeper < ActionController::Caching::Sweeper
observe Article #设置要监视的模型
#表中添加新数据后执行页面缓存清理
def after_create(article)
expire_public_page
end
#表中数据被更新后执行action缓存清理
def after_update(article)
expire_article_page(article.id)
end
#表中数据被删除一条或多条时同事执行页面、action缓存清理
def after_destroy(article)
expire_public_page
expire_article_page(article.id)
end
private
def expire_public_page
expire_page(:controller => "content" , :action => 'public_content' )
end
def expire_article_page(article_id)
expire_action(:controller => "content" ,
:action => "premium_content" ,
:id => article_id)
end
end
控制器中的清理器钩子(在控制器中)
cache_sweeper :article_sweeper, #开启Article清理器
:onlye=>:some_action #监视的控制器
:except=>:some_action #忽略的控制器
注:若要对可变性较大内容进行缓存需要引入时间缓存失效策略:通过操作系统编写定时删除缓存的进程来控制
8CSRF安全策略
Rails2.x后引入了防止跨域访问攻击的pluging,具体操作如下
在控制器中定义protect_from_forgery钩子,在模版中使用form_for等标签时,服务器会在生成form_for等标签时 建立一个密钥(token),服务器会监视request回来的所有post以及AJAX行为,如果request没有token或者与服务器计算出的不 一致,将返回错误信息。
cookiestore的session存储机制下,token是根据CGI::Session.generate_unique_id生成的随即数并进行编码得到的,所以不需要为protect_from_forgery设置secret的键值
:active_record_store是根据session_id、protect_from_forgery的secret的值以及digest(默认是SHA1)计算得来,所以要为这种session机制设置secret值。