| 请求(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 |
| |
|
| |
|
| |
|
| |
|
| |
|