1.View
1.1 view的原理
ActionView: actionview gem
ActionController: actionpack gem
actionview和actionpack都可以单独用于某个项目,rails就是由不同的gem包构成的。
1.2.View的查找
- app/views/
- 其他,自定义目录: append_view_path_method
1.3.View的分类
Template: index.html.erb 完整的页面
Partial:_ user.html.erb 部分可共用的模板页面
Layouts: application.html.erb 定义了view的父视图或者布局视图
1.4.View解析
- ERB
<% %> #=>没有输出,用于循环,遍历,赋值等操作
<%= %> #=>输出内容
<% @users.each do |user| %>
<tr>
<td><%= user.id %></td>
<td><%= user.username %></td>
</tr>
<% end -%>
注:这里<% end -%>
,end 后追加一个减号,可以减少多余的空白换行输出
2. HAML
3. Builder: json builder, xml builder etc.
都是完成Ruby语法到字符串的解释
1.5.View的命名
index.html.erb
- index: action对应的名称/ partial名称
- html:输出文件类型(mime type),text/html
- erb:解释引擎
2.render
2.1 render的作用
2.1.1 render在controller的作用
修改action的查找view的行为,组建当前request的response
def search
render text: 'ok'
render json: @users
render xml: @users
render file: 'ạpp/views/users/index'
render partial: 'app/ views/users/search'
end
注:一个action 只能使用一次render或redirect_to
2.1.2 render在view的作用
渲染和解释子视图(sub-view)
- 两者表现形式,效果相同
<%= render "shared/ menu" %>
<%= render partial: "shared/menu" %>
- 调用其他视图时进行传参。
<%= render "shared/ menu", locals: {var_1: 'value_1'} %>
2.2 render遍历输出
两种方式效果相同
<% @users.each do |user| %>
<%= render partial: "one_user", locals: {user: user} %>
<% end -%>
<%= render partial: "one_user", collection: @users, as: 'user' %>
as: ‘user’ 是因为你的模板中需要的变量是user.id 和user.username
2.3 实例变量
在所有的sub_view 子模板中,都能够访问当前view 或action的所有实例变量
2.4 渲染文本
调用 render 方法时指定 :plain 选项,可以把没有标记语言的纯文本发给浏览器:
render plain: "OK"
2.5 渲染 HTML
- 调用 render 方法时指定 :html 选项,可以把 HTML 字符串发给浏览器:
- 使用 html: 选项时,如果没调用 html_safe 方法把 HTML 字符串标记为安全的,HTML 实体会转义。
2.6 渲染 JSON
-
JSON 是一种 JavaScript 数据格式,很多 Ajax 库都用这种格式。Rails 内建支持把对象转换成 JSON,经渲染后再发送给浏览器。
-
在需要渲染的对象上无需调用 to_json 方法。如果有 :json 选项,render 方法会自动调用 to_json。
2.7 渲染 XML
Rails 也内建支持把对象转换成 XML,经渲染后再发给调用方
2.8 渲染普通的 JavaScript
Rails 能渲染普通的 JavaScript:
render js: "alert('Hello Rails');"
2.9 渲染原始的主体
- 调用 render 方法时使用 :body 选项,可以不设置内容类型,把原始的内容发送给浏览器:
- 只有不在意内容类型时才应该使用这个选项。多数时候,使用 :plain 或 :html 选项更合适。
- 如果没有修改,这种方式返回的内容类型是 text/html,因为这是 Action Dispatch 响应默认使用的内容类型。
2.10 render 方法的选项
render 方法一般可接受五个选项:
- :content_type:默认情况下,Rails 渲染得到的结果内容类型为 text/html(如果使用 :json 选项,内容类型为 application/json;如果使用 :xml 选项,内容类型为 application/xml)。如果需要修改内容类型,可使用 :content_type 选项:
- :layout:在当前动作中使用指定的文件作为布局,也可以告诉 Rails 根本不使用布局:layout:false
- :location::location 选项用于设置 HTTP Location 首部:
- :status:Rails 会自动为生成的响应附加正确的 HTTP 状态码(大多数情况下是 200 OK)。使用 :status 选项可以修改状态码:
- :formats:Rails 使用请求中指定的格式(或者使用默认的 :html)。如果想改变格式,可以指定 :formats 选项。它的值是一个符号或一个数组。
2.11 在运行时选择布局
根据当前请求决定使用哪个布局:
class ProductsController < ApplicationController
layout :products_layout
private
def products_layout
@current_user.special? ? "special" : "products"
end
end
2.2.13.3 根据条件设定布局
在控制器中指定布局时可以使用 :only 和 :except 选项。这两个选项的值可以是一个方法名或者一个方法名数组,对应于控制器中的动作
class ProductsController < ApplicationController
layout "product", except: [:index, :rss]
end
2.2.13.5 模板继承
与布局的继承逻辑一样,如果在约定的路径上找不到模板或局部视图,控制器会在继承链中查找模板或局部视图。因此,app/views/application/ 最适合放置共用的局部视图,
2.2.14 避免双重渲染错误
Can only render or redirect once per action
解决的办法很简单,确保在一次代码运行路径中只调用一次 render 或 redirect_to 方法。有一个语句可以帮助解决这个问题,那就是 and return。
render action: "special_show" and return
3 redirect_to 方法
你可以使用 redirect_back 把用户带回他们之前所在的页面。前一个页面的地址从 HTTP_REFERER 首部中获取,浏览器不一定会设定,因此必须提供 fallback_location
redirect_back(fallback_location: root_path)
4 使用 head 构建只有首部的响应
head 方法只把首部发送给浏览器,它的参数是 HTTP 状态码数字或符号形式(参见前面的表格),选项是一个散列,指定首部的名称和对应的值。例如,可以只返回一个错误首部:
head :bad_request
5. 静态资源标签辅助方法
Rails 提供了六个静态资源标签辅助方法:
auto_discovery_link_tag
javascript_include_tag
stylesheet_link_tag
image_tag
video_tag
audio_tag
6. yield
在布局中,yield 标明一个区域,渲染的视图会插入这里。(??)
7.content_for
content_for 方法还可以在通用布局中引入特定页面使用的 JavaScript 或 CSS 文件。
8 使用局部视图
- 局部视图把渲染过程分为多个管理方便的片段,把响应的某个特殊部分移入单独的文件。
- 局部视图的文件名以下划线开头,以便和普通视图区分开,不过引用时无需加入下划线。即便从其他文件夹中引入局部视图
- 与视图可以使用布局一样,局部视图也可使用自己的布局文件。例如,可以这样调用局部视图:
<%= render partial: "link_area", layout: "graybar" %>
- 使用
locals:
或local_assigns
可以将局部变量可以传入局部视图。 - 每个局部视图中都有个和局部视图同名的局部变量(去掉前面的下划线)。通过 object 选项可以把对象传给这个变量:
<%= render partial: "customer", object: @new_customer %>
- 如果要在局部视图中渲染模型实例,可以使用简写句法:
<%= render @customer %>
假设实例变量 @customer 的值为 Customer 模型的实例,上述代码会渲染 _customer.html.erb,其中局部变量 customer 的值为父级视图中 @customer 实例变量的值。