Layout
layout是一个视图的容器,当要把页面展示到浏览器时,会把视图的HTML嵌入到容器layout的HTML中。Rails3中为所有的controllers定义了一个名为:application.html.erb的layout。
partials(局部模版渲染)
app/views/comments/_comment.html.erb
<p>
<b>Commenter:</b>
<%= comment.commenter %>
</p>
<p>
<b>Comment:</b>
<%= comment.body %>
</p>
app/views/posts/show.html.erb
.
.
.
<h2>Comments</h2>
<%= render @post.comments %>
.
.
.
render方法会遍历@post.comments中的每一个comment,同时赋值给对应的局部变量comment,最后可以显示所有的comment。
View Helpers
存在app/helper文件夹中,为视图提供可重复使用的代码片段。
Migration change method
- add_column
- add_index
- add_timestamps
- create_table
- remove_timestamps
- rename_column
- rename_index
- rename_table
目前change方法只支持这些migration定义,如果要使用其他方法就得自己写up和down方法。
Migration中几个rake任务
- rake db:migrate
- rake db:rollback
- rake db:migrate:dedo
- rake db:reset
- rake db:migrate:up
- rake db:migrate:down
render和redirect_to的区别
render告诉rails使用哪个视图响应请求
def index
@books = Book.all
end
def show
@book = Book.find_by_id(params[:id])
if @book.nil?
render :action => "index"
end
end
上面代码中,如果@book为nil,会出现问题。
因为render :action不会执行目标action中的代码,所以@books变量中就不会有任何值,在index页面也就不能显示任何内容,要修复这个问题,应该用redirect_to。
redirect_to告诉浏览器发送一个请求到新的地址
def index
@books = Book.all
end
def show
@book = Book.find_by_id(params[:id])
if @book.nil?
redirect_to :action => :index
end
end
这样浏览器会重新发送请求到action:index,index中的代码会执行,@books变量中就会取到值,也就能在页面显示。
上面这种方法与浏览器会有一个交互的过程,这在效率上不太好,如果需要考虑效率问题,应该用下面这种方法:
def index
@books = Book.all
end
def show
@book = Book.find_by_id(params[:id])
if @book.nil?
@books = Book.all
render "index", :alert => 'Your book was not found!'
end
end
yield用法
yield存在于容器layout中,用来标示view中的content应该插入到那个节点
<html>
<head></head>
<body>
<%= yield %>
</body>
</html>
具有多个yield的layout
<html>
<head>
<%= yield :head %>
</head>
<body>
<%= yield %>
</body>
</html>
此时的view中应该这样写,content_for方法允许将content插入到具名yield块中
<% content_for :head do %>
A simple page
<% end %>
<p>Hello, Rails!</p>
<%= render @customer %> 语句解析
上面这个语句会用_customer.html.erb进行渲染
Rendering Collections
- index.html.erb
<h1>Products</h1>
<%= render :partial => "product", :collection => @products %>
_product.html.erb
<p>Product Name: <%= product.name %></p>
集合@products中的每个成员都会调用partial进行插入操作。
在rails3中上面的index.html.erb可以简写成:
<h1>Products</h1>
<%= render @products %>
而如果@products为空,我们只需修改一下index.html.erb:
<h1>Products</h1>
<%= render(@products) || 'There are no products available.' %>
default_scope 作用域
default_scope order: 'microposts.created_at DESC'
通过上面的代码设定了排序规则
<%= render 'shared/error_messages', object: f.object %>分析
<%= form_for(@micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<% end %>
表单的块变量f可以通过f.object获取当前对象,因此,在form_for(@user) do |f| 中,f.object 的返回值是@user;在form_for(@micropost) do |f|中,f.object 的返回值是@micropost。
<%= render partial: 'shared/feed_item', collection: @feed_items %>分析
当使用:collection时,:partial参数不可以省略,否则会出现错误。
helper_method方法解析
在controller里边定义的helper_method,可以在view里边使用
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_user
helper_method :user_signed_in?
helper_method :correct_user?
private
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def user_signed_in?
return true if current_user
end
def correct_user?
@user = User.find(params[:id])
unless current_user == @user
redirect_to root_url, :alert => "Access denied."
end
end
end
与此类似的是,如果在helper文件中定义的方法,只能被view使用,controller要想使用,需要显式的包含helper文件
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end
好吧,暂时先写这么多了,以后再慢慢的补充,to be continue......