请求(request)信息 |
获取请求信息 |
params[:参数名]
可以获得的信息 |
主机信息 |
《form method="POST"》下定义的表格传送来的信息 |
询问信息
query |
url后面 ?键名=值&...下面的信息 |
路径参数 |
路径/books/1这样的1的部分 |
|
数组 |
路径 |
key后面加[]
例: /...?sampleArray[]=...&... |
方法参数 |
还是单纯的符号(symbol)
params[:sampleArray] |
|
哈希表 |
路径 |
key后面加上[哈希值]
例: /...?hashArray[hashVal]=...&... |
方法参数 |
还是单纯的符号(symbol)
params[:hashArray] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
指定可以获取的数据
黑白名单 |
params.require(model).permit(attr,...)
参数 |
model |
模型名 |
attr, ... |
允许获取的属性值的哈希值(符号symbol) |
|
|
|
|
|
|
|
遇到获取不允许值时指定处理 |
默认拒绝
config.action_controller.action_on_unpermitted_parameters |
|
|
|
|
|
|
|
获取头信息 |
头信息 |
附加的一系列和用户操作无关的信息 |
例 |
客户端(浏览器)对应的语言,浏览器种类,链接地址等 |
其他 |
请求时的成为请求头信息 (request header
information) |
|
|
|
|
request.headers['...']
主要的头信息标签 |
内部名 HTTP_....
例子: HTTP_ACCEPT_LANGUAGE
Accept |
客户端支持的内容种类 |
Accept-Language |
客户端支持的语言(按优先度排) |
Authorization |
证书信息 |
Host |
请求的主机信息 |
Referer |
链接信息 |
User-Agent |
客户端种类 |
|
|
|
|
|
|
|
|
|
还可以获取服务器环境变量
request.headers['...'] |
GATEWAY_INTERFACE |
CGI的校对
返回值例:
CGI/1.2 |
QUERY_STRING |
请求信息
返回值例:
id=1 |
PATH_INFO |
路径信息
返回值例:
/ctrl/req_head2 |
REMOTE_ADDR |
客户端的ip地址
返回值例:
::1 |
REQUEST_METHOD |
HTTP方法
返回值例:
GET |
REQUEST_URI |
请求是的url
返回值例:
/ctrl/red_head2?id=1 |
SERVER_NAME |
服务器名
返回值例:
localhost |
SERVER_PORT |
服务器接口号
返回值例:
3000 |
SERVER_PROTOCOL |
服务器用的协议
返回值例:
HTTP/1.1 |
SERVER_SOFTWARE |
使用的服务器软件
返回值例:
puma 3.6.0
Sleepy Sunday Serenity |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
获取头信息和服务器信息的专用方法 |
#TODO:
F2634985-5CD9-4CBD-B8E0-C7B7A4184923
p333~334
因为上面的也可以用,暂时省略 |
文件上传 |
传上的文件的接收
form_tag/for ...multipart: true do
...
submit_tag
...
end
form_tag
form_for 选项设置 |
必须 multipart: true |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
上传的文件方法 |
类型UploadedFile
original_filename |
源文件名 |
content_type |
内容的类型
? |
size |
大小
1.megabyte这样来进行比较 |
read |
读取文件内容 |
File.extname(...).downcase
File.extname(...).upcase |
获取文件拓展名
注意:参数应该是文件名 |
|
|
|
|
|
|
|
|
|
|
File.extname(你的文件.original_filename).downcase |
文件保存
本地系统 |
File.open("/Users/xxxx/Desktop/github/Learning-Ruby/File/#{name}",
'wb') do |file|
file.write(upload.read)
end |
文件保存
数据库 |
# TODO: p337~339 |
获取文件后缀 |
File.extname(你的文件.original_filename).downcase |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
回应(response)的操作 |
response |
返回处理的结果等 |
概览 |
render |
呼出模板/文本/脚本等,输出通用的结果 |
redirect_to |
向指定地址重定向 |
send_file |
输出文件 |
send_data |
输出二进制文件 |
head |
只输出回应的头信息?(応答ヘッダー) |
|
|
|
|
|
|
|
|
|
|
|
render(1) |
最常用。
如果没有呼出,则默认呼出这个,执行设定好的模板(get '.../...')
呼出模板的用法
呼出同一个视图控制器的模板(templata) |
render action: 't1' |
呼出其他视图控制器的模板(templata) |
render template: 'sample/t1' |
呼出应用外部的模板(templata) |
render file: '...'
绝对路径
多个应用共有一个模板时候用 |
三个的符号都可以省略 |
|
呼出部分模板
传送门
|
位置 |
模板内(layout或者部分模板template) |
文件命名规则 |
开头带_
|
呼出方法 |
render url
render partial: url
render "sample"
render partial: "sample"
注:
● 全体通用的(/app/views/ application)看做全体的部分模板, 呼出不需要相对路径
● 路径是 /app/views/后面的相对路径
● 和主模板在一个文件夹的呼出时可以省略到该文件夹部分
|
|
|
|
注意: render默认放回200(:ok)状态码,可以通过status: 选项自己指定 |
render(2) |
直接输出
只用在debug
会使layout无效
输出纯文本
无视一切符号的意义 |
render plain: '...' |
输出纯文本
有符号的意义 |
render html: '...'.html_safe |
用erb输出 |
render inline: '...'
erb的代码字符串 |
主要 |
这三个都会使layout无效
因为这是debug
如果需要layout,要自己制定 |
|
|
|
|
|
|
|
|
|
|
|
|
注意: render默认放回200(:ok)状态码,可以通过status: 选项自己指定 |
head |
只返回状态码
head status [, opt]
参数 |
status |
状态
数值或者符号 |
opt |
应答头(応答ヘッダー)
头: 值的形式 |
|
status |
符号 |
状态码 |
含义 |
:ok |
200 |
成功 |
:created |
201 |
资源生成成功 |
:moved_permantly |
301 |
资源永久性移动了 |
:found |
302 |
资源暂时移动了 |
:see_other |
303 |
资源在其他地方 |
:unauthorized |
401 |
要认证 |
:forbidden |
403 |
访问被禁止 |
:not_found |
404 |
资源不存在 |
:method_not_allowed |
405 |
HTTP方法不被允许 |
:internl_server_error |
500 |
サーバーエラー |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
redirect_to |
返回结果并且重定向
redirect_to url [,status=302]
url |
和url_for一样的参数
controller |
视图控制器名 |
action |
动作(方法名)(controller#method) |
host |
主机名(覆盖现在的主机) |
protocol |
协议名(覆盖现在的协议) |
anchor |
锚名? |
only_path |
是否返回相对url(是否省略协议/主机/接口)
不指定host的话默认true |
trailing_slash |
末尾要不要/
默认false |
user |
HTTP识别用的用户名 |
password |
HTTP识别用的密码 |
只指定一个:back |
链接向之前一个链接
(返回Referer header) |
|
status |
数字或者符号
符号 |
状态码 |
含义 |
:ok |
200 |
成功 |
:created |
201 |
资源生成成功 |
:moved_permantly |
301 |
资源永久性移动了
crawler记录 |
:found |
302 |
资源暂时移动了
crawler不记录 |
:see_other |
303 |
资源在其他地方 |
:unauthorized |
401 |
要认证 |
:forbidden |
403 |
访问被禁止 |
:not_found |
404 |
资源不存在 |
:method_not_allowed |
405 |
HTTP方法不被允许 |
:internl_server_error |
500 |
サーバーエラー |
|
添加flash |
redirect_to @sample, notice: '...'
两个基本一样的
notice |
用于传出通知
任意值 |
alert |
用于穿出警告和错误(error)
任意值 |
redirect_to ({controller: :controller_test, action: :t8}),
test_flash: 'just a test' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
redirect_back |
重定向到前一个(Referer头的前一个)
redirect_back fallback_location: url
fallback_location: url
前一个不存在的时候重定向的目的地
url |
和url_for一样的参数
controller |
视图控制器名 |
action |
动作(方法名)(controller#method) |
host |
主机名(覆盖现在的主机) |
protocol |
协议名(覆盖现在的协议) |
anchor |
锚名? |
only_path |
是否返回相对url(是否省略协议/主机/接口)
不指定host的话默认true |
trailing_slash |
末尾要不要/
默认false |
user |
HTTP识别用的用户名 |
password |
HTTP识别用的密码 |
只指定一个:back |
链接向之前一个链接
(返回Referer header) |
|
|
send_file
send_data |
发送文件 |
send_file path [,opt]
也就是下载链接 |
发送二进制文件 |
send_data path [,opt]
表示图片用 |
参数 |
|
opts |
filename |
下载的文件名
默认: 原文件名 |
type |
内容的种类
默认: application/octet-stream |
disposition |
是inline表示(:inline)
还是直接使用户下载(:attachment) |
status |
状态码
默认200(ok) |
url_based_filename |
是否根据下载的链接生成文件名
默认: false
(filename指定了的话优先filename) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(补充)
输出日志 logger |
p350
logger.unknow(msg) |
未知错误 |
loggger.fatal(msg) |
致命错误 |
logger.error(msg) |
错误 |
logger.warn(msg) |
警告 |
logger.info(msg) |
信息 |
logger.debug(msg) |
bug信息 |
|
|
优先度 |
从上到下递减 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HTML以外的回应处理 |
概要 |
将处理结果以XML/JSON形式输出
用途: 普通的回应是给人看的,而这种回应是用来把数据输出给其他app |
生成xml/json |
xml |
render xml: :sample |
json |
render json: :sample |
注: 一次可以指定多个不同的model,不用完全一样 |
JBuild生成JSON |
文件后缀 |
.json.jbuilder |
构成 |
Ruby脚本 |
生成json |
json.array!(coll, partial: template, as:
var)
参数 |
coll |
对象数组 |
partial: template |
描绘每个元素所用的部分模块
注意: 部分模块命名开头_ |
as: var |
部分模块里获取每个元素的变量 |
|
|
|
|
|
|
|
例: json.array! @books, partial:
'books/book', as: :book
其他写法: https://www.rubydoc.info/github/rails/jbuilder/Jbuilder:array!
|
部分模板内的方法 |
输出键与值
一个 |
json.key value
注意: 键和值之间没有空格
参数 |
|
可以嵌套
接闭包 |
json.key do
json.subkey2 val1
json.subkey2 val2
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例: json.url book_url(book, format: :json)
book_url: 由resources自动生成 |
输出键与值
多个 |
json.extract! obj, prop, ...
参数 |
obj |
模型对象 |
prop |
模型的属性
生成的相当于 |
|
|
|
|
|
|
|
备注 |
json.pro-name Model.pro-name
也就是说键名和模型的属性名相同 |
省略型 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例: json.extract! sample, :pro1, :pro2, ... |
|
|
|
|
|
|
|
|
|
|
|
Build生成XML |
要在Gemfile最后一句
gem 'activemodel-serializers-xml'
然后运行bundle install
文件后缀 |
.xml.builder |
构成 |
Ruby脚本 |
生成xml |
xml.element([contet] [,attr: value, ...)
do
...content...
end
参数 |
element |
要素名 |
attr |
属性名 |
value |
属性值 |
content |
代码块的内容 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
根据格式要求输出 |
respond_to_do |format|
format.type { statements
}
...
end
参数 |
format |
格式控制对象 |
type |
回应的格式 |
statements |
描绘的代码 |
|
|
|
|
|
注 |
也可以带条件
if ...
format.type
{statements}
...
end |
可用的形式 |
html, xml, json, rss, atom, yaml, text, js,
css, csv, ics |
追加形式 |
http/mime_types.rb
格式 Mime::Type.register "text/richtext", :rtf |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
状态管理 |
Rails可用的状态管理方法 |
cookie |
保存在浏览器的信息
(Rails以外也可用) |
session |
保存在cookie, cash, database的做法
(最常用) |
flash |
只对现在和下一个HTTP要求有效的特殊session |
|
Cookie |
设置Cookie值 |
cookies[:name] = {key: value, ...}
参数 |
name |
cookie名 |
key |
option |
value |
选项值 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
option |
value:
必须 |
cookie的值
例:
sample@wings.msn.to |
expires:
必须 |
cookie的有效期限
例: 3.hours.from_now
不指定的话,关了浏览器就没了
|
domain: |
cookie有效的域名 |
path: |
cookie有效的路径 |
secure: |
是否安全化
注: 如果选true, 则只在https下才会
发送cookies |
httponly: |
是否只对HTTP有效
防止JavaScript来盗取 |
|
|
|
|
|
|
|
|
|
永久性cookie |
cookies.permanent[:key] =
{...}
注意: 有效期为20年, 优先级最高, 设定了expire也无视
|
加密cookies |
cookies.encrypted[:key] = {...}
yaoyushe/app/config/secrets.yml |
既加密又永久化 |
cookies.permanent.encrypted[:key] =
{...} |
|
|
|
|
|
|
|
|
|
|
|
删除cookie |
cookies.delete(:key)
对于设置了domain/path的,需要明确指定domain/path
cookies.delete(:key, path: '...') |
读取 |
cookies[:key] |
|
|
|
|
Session |
概要 |
默认情况下使用cookie来保存(CookieStore)
和Cookie基本上一样
不同点: 可以自由改变保存处
CookieStore |
默认保存方法
优点: 快的一笔2333
缺点: 不安全,不保存重要的
单个上限4kb |
CacheStore |
保存在服务器cache(应用的cache处)
保存不怎么重要的短期数据
|
ActiveRecordStore |
保存在服务器数据库
适合保存核心数据 |
|
设定session值 |
session[:key] = value
session默认有效期限是关闭浏览器前
保存方法,期限等在/app/config/ |
设定session本身 |
位置 |
/app/config/initializer/session_store.rb 如果没有则在该位置自己建一个 |
文件内容 |
Rails.application.config.session_store
:cookie_store, key: '_XX_session' |
第一个参数 |
数据存储的种类
cookie |
:cookie_store
默认值 |
缓存 |
:cache_store |
数据库 |
:active_record_store
Rails4以后和本体分离,需要另外安装
active record-session_store |
使session无效 |
:disabled |
|
|
|
可指定参数 |
key |
存储session使用的键名
默认_session_id(根据项目名来决定) |
domain |
session键有效的域名
默认nil(现在的域名) |
path |
session键有效的pass
默认/ |
expire_after |
session有效期限
nil(关闭浏览器为止)
要永久就设定20.years
● 也可以写成expire_in
|
secure |
保密通信(HTTPS)下session才有效
默认false |
httponly |
HTTP cookie是否有效
默认true |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
读取 |
sample = session[:key]
注: 得到的是以字符串为标签的哈希表 |
删除 |
session[:key] = nil |
全部删除 |
reset_session |
Flash |
概要 |
只对当前和下一个请求有效
主要用于确认信息等情况,如填完提交了表格提示保存成功等等 |
使用例 |
redirect_to
@sample, notice: '...'
两个基本一样的
notice |
用于传出通知
任意值 |
alert |
用于穿出警告和错误(error)
任意值 |
|
设定值 |
flash[:key] = value |
获取值 |
flash[:key] |
相关方法 |
flash.now[:key] |
只对当前方法有效的flash |
flash.keep(:key) |
指定的key保存到下一个方法 |
flash:discard(:key) |
删除指定的key
不指定的话全部删除 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
筛选(filter)
预处理与后处理 |
前或后执行 |
before_action :method [, ...]
after_action :method [, ...]
使用的方法用private藏起来
可以用多个方法,直接往后加
用render/redirect_to或者发出异常来中止before_action
选项 |
|
只对一部分方法生效 |
only: [:t1, :t2, ...] |
except |
except: [t1, t2, ...] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
前后执行 |
around_action :method [,
...]
使用的方法用private藏起来
注: 用yield来表明action的执行时刻
例
around_action :test
private
def test
...before...
yield
...after...
end |
敲过部分筛选处理 |
母类---子类---孙类
去除继承子母类的 |
skip_before_action :action-name
skip_around_action :action-name
skip_after_action :action-name |
注 |
也可以用only,except |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rails自带认证的问题 |
①.只能用自带的认证对话框
②.没办法logout,浏览器关闭前一直是登陆状态 |
用户认证
Rails自带的简单认证 |
authenticate_or_request_with_http_basic(realm) do |name, passwd|
login_procedure
end
返回true/false
参数 |
realm |
realm名
默认"Application" |
name |
用户名 |
passwd |
密码 |
login_procedure |
登陆处理 |
|
|
|
|
|
|
|
|
用户认证
Rails自带的更安全认证 |
authenticate_or_request_with_http_digest(realm) do |name|
...
end
返回密码,如果符合就成功,不符合就失败
例:
before_action :auth_
REALM = 'SAMPLE'
USER = { name: 'name', password: '1234'}
def auth_
authenticate_or_request_with_http_digest(REALM) do |n|
USER[:password]
end
|
实现认证密码 |
安装bcrypt库 |
在Gemfile最后添加 |
gem 'bcrypt', '~>3.1.7' |
执行: |
bundle install |
重启动服务器 |
|
|
|
|
|
|
使用brcypt库 |
建立用户的模型rails generate model users user_name:string password:string |
在模型里添加
has_secure_password
不要confirmation验证的话 has_secure_password
validation:false
注:这个方法(method)自动添加了
password/password_confirmation属性 |
假想属性,不是一定要的 |
password属性的必须的认证,字符串长度验证(72以内) |
|
password/password_confirmation属性的confirmation认证 |
不要的话
|
认证方法 authenticate |
|
|
在模型里添加列(string)
password_digest
注意: 此列作为密码
登录密码时候用BCrypt::Password.create(@password) |
@user = Login.new(:user => @username,
:password_digest =>
BCrypt::Password.create(@password)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
定义共有的动作(application controller) |
位置 |
/app/controller/application_controller.rb |
作用 |
所以视图控制器的母类
用于定义
子类需要的帮助类方法(helper method)
大部分视图控制器使用的筛选功能(filter)
应用全体的设定 |
异常处理 |
不应该在每一个具体的视图控制器里,应该在母类里
rescue_from except, with: rescuer
参数 |
except |
异常 |
with: rescuer |
处理该异常的方法(method) |
|
|
|
|
|
|
|
|
|
|
|
|
|
注 |
实际产品环境(production)下产生异常会自动呼出异常相对应的页面
位置: /public/
如404.html |
|
防范
跨站请求伪造(CSRF)
Cross-site request fogery |
protect_from_fogery with: :...
with: :... |
遇到伪造请求的处理方法
:exception |
生成异常
ActionController:
invalidAuthenticityToken |
:reset_session |
删除session |
:set_session |
换成空的session
默认值 |
|
|
|
|
|
|
|
|
|
|
按设备分配页面 |
设备信息 request.headers['User-Agent']
request.variant = :mobile |
呼出后缀为
html+mobile.erb
网址...t1?type=mobile |
request.variant = :tablet |
呼出后缀为
html+tablet.erb
网址...t1?type=tablet |
没设定request.variant |
呼出后缀为
html.erb
也就是默认 |
|
增加flash变量 |
add_flash_type(type, ...)
redirect_to里面有两个,notice, alert
增加除此之外的用
add_flash_type(:test1, :test2, ...)
type |
键(符号symbol) |
使用 |
redirect_to url, test: 'test' |
|
|
|
|
|
|
|
多个视图控制器/模型共有的逻辑 |
放置位置 |
/app/controllers/concerns/
/app/models/concerns |
写法
p399 |
module name
extend ActiveSupport::Concern # 只含有实例方法的话可以省略extend ActiveSupport::Concern
included do
#call_clazz # 呼出包含此模块的类的类方法
end
module ClassMethods
#clazz # 类方法的定义
end
#instance # 实例方法
end
call_clazz |
呼出方法
呼出包含此模块的类的类方法
|
module ClasssMethod |
类方法的定义 |
instance |
实例方法 |
extend ActiveSupport::Concern |
共通的内容
只含有实例方法的话可以省略
include的成为实例方法
extend的成为静态方法
|
|
|
例子
module
Login
extend
ActiveSupport::Concern
included
do
before_action :login
end
private
def login
#render
plain: 'login module test successfully'
end
end
|
使用 |
include Module-Name |
文件命名规则 |
字母要一直,单词之间_间隔,module名的单词首字母大写
如 test.rb ---> module Test
ni_hao.rb
---> module NiHao |
|
|
|
|
|
|
|
|
|
|