Rails4.1 Action View概述

来源:互联网 发布:linux mkdir -m 编辑:程序博客网 时间:2024/06/05 15:55

原文:http://guides.rubyonrails.org/action_view_overview.html

通过此篇指导,你将学到:

  • l  什么是ActionView以及如何在Rails的使用它
  • l  如何更合理的使用模板、局部页面和布局
  • l  Action View提供了哪些帮助方法以及如何自定义自己的方法
  • l  如何使用本地化视图
  • l  如何在Rails外使用ActionView

1          什么是Action View?

Action View和ActoinController是Action Pack的两大主要组件。在Rails,请求被Action Pack捕获后,将其分配到控制器层(执行处理逻辑)和视图层(渲染模板)。尤其是,Action Controller将负责与数据库CRUD操作的连接。Action View负责编译中的响应。

Action View模板是使用内嵌Ruby语言到HTML标签中写成的。为了避免模板中引用代码变得杂乱,针对常用的表单、日期和字符串提供了一些帮助方法。针对自己的应用,自定义合适的帮助方法也非常简单。

注:Action View的一些特性虽然与ActiveRecord联系紧密,但是这并不意味着Action View依赖于Active Record。Action View是一个独立的包,可以配合其他一些Ruby库进行使用。

2          使用Action View的Rails

对于每个控制器,在app/views目录下都有相对应的模板目录进行关联。这些被关联的视图模板通常在控制器的对应动作调用后显示。

让我们看一下,通过Rails的脚手架命令,默认创建了哪些资源:

$ bin/rails generatescaffold post
[...]
invoke scaffold_controller
create app/controllers/posts_controller.rb
invoke erb
create app/views/posts
create app/views/posts/index.html.erb
create app/views/posts/edit.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/_form.html.erb
[...]

           Rails中视图有自己的命名约束。尤其是,可以从上例中看到,一些视图与控制器中的动作名称保持一致。例如对于posts_controller.rb中index动作,将使用app/views/posts中的index.html.erb模板。返回到浏览器端的HTML页面是组合了这个ERB文件和对应的布局文件以及一些局部页面的最终结果。在稍后的小节中,你将获取更多有关这三部分的只知识。

3          模板,局部页面和布局

像之前提到的,最终的HTML输出页面是由Rails的3部分元素组成:模板、局部视图和布局。下面是对各部分的简述。

3.1         模板

Avtion View模板可以通过以下几种方式编写。若模板文件名有.erb后缀,可以使用内嵌Ruby语言和HTML语言进行编写。若模板文件名有.builder后缀,将使用Builder::XmlMarkup库进行编写。

Rails支持多个模板系统,并通过文件名的后缀来分辨它们。例如,使用ERB的HTML文件将有.html.erb后缀。

3.1.1    ERB

在ERB模板中,Ruby代码被<%%>和<%= %>标签包裹着。对于<% %>标签中的代码,只执行不返回任何结果,比如条件、循环或块。而<%= %>标签中的代码,将返回你所需要的值。例如:

<h1>Names of allthe people</h1>
<% @people.each do |person| %>
  Name: <%= person.name %><br>
<% end %>

             循环的代码写在<%%>标签中,而对名字的输出代码写在<%= %>中。注意这并非用法建议,对于常规输出中使用的puts或print将无法用于ERB模板。因此如下写法是错误的:

                       <%#WRONG %>

Hi, Mr. <% puts "Frodo" %>

              若想去掉首尾的空格,可以使用<%-  -%>替代<%和%>。

3.1.2    Builder

Buider模板相对ERB来说是更具有标志性的。该模板能够方便生成XML内容。一个被命名为xml的XmlMarkup对象将可用于以.builder为后缀的模板中。

这是一些基本的例子:

xml.em("emphasized")xml.em { xml.b("emph & bold") }xml.a("A Link", "href" => "http://rubyonrails.org")xml.target("name" => "compile", "option" =>"fast")

             生成后的结果是:

<span style="white-space:pre"></span><em>emphasized</em><span style="white-space:pre"></span><em><b>emph & bold</b></em><span style="white-space:pre"></span><a href="http://rubyonrails.org">A link</a><span style="white-space:pre"></span><target option="fast" name="compile" />

             对于带有块参数的方法,将被看做XML标识标签,并且其内容被看做内嵌标签。例如:

<span style="white-space:pre"></span>xml.div {  <span style="white-space:pre"></span>  xml.h1(@person.name)  <span style="white-space:pre"></span>  xml.p(@person.bio)<span style="white-space:pre"></span>}

            生成的结果是:

<span style="white-space:pre"></span><div>  <span style="white-space:pre"></span>  <h1>DavidHeinemeier Hansson</h1>  <span style="white-space:pre"></span>  <p>Aproduct of Danish Design during the Winter of '79...</p><span style="white-space:pre"></span></div>

             以下是在Basecamp上常使用的RSS的例子:

xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/")do  xml.channeldo    xml.title(@feed_title)    xml.link(@url)    xml.description "Basecamp: Recent items"    xml.language "en-us"    xml.ttl "40"    for item in @recent_items      xml.item do        xml.title(item_title(item))        xml.description(item_description(item)) if item_description(item)        xml.pubDate(item_pubDate(item))        xml.guid(@person.firm.account.url + @recent_items.url(item))        xml.link(@person.firm.account.url + @recent_items.url(item))        xml.tag!("dc:creator", item.author_name) if item_has_creator?(item)      end    end  endend

3.1.3    模板缓存

默认情况下,Rails将编译模板中的方法以便渲染它。当你改变一个模板后,Rails将通过检查文件的修改时间,若在开发模式下将进行重新编译。

3.2         局部页面

局部模板——通常被称为‘partials’——是将渲染过程切分成多个可管理的块的机制。使用局部视图,你可以从你模板中将某些代码提取到单独文件中,并对这些文件进行重利用。

3.2.1    给局部视图命名

可以通过如下方式使用render方法来使用局部视图:

         <%= render"menu" %>

此例子中将在调用处渲染命名为_menu.html.erb的页面。注意开始的下划线字符:为了区分局部视图和普通视图,前者遵循以下划线最为命名第一个字符的命名约束。此约束同样可用于不同的目录之前:

<%= render "shared/menu" %>

该代码将调用位于app/views/shared/_menu.html.erb的局部文件。

3.2.2    使用局部视图来简化视图模板

可将局部视图看做为等效的子程序;将视图中的细节提取到局部视图,将更利于理解。例如:

<%= render "shared/ad_banner" %>
<h1>Products</h1>
<p>Here are a few of our fine products:</p>
<% @products.each do |product| %>
<%= render partial: "product", locals:{product: product} %>
<% end %>
<%= render "shared/footer" %>

在此例子中,_add_banner.html.erb和_footer.html.erb局部视图包含在整个应用中每个页面上通用的内容。当你在编写其他页面时,你不需要关注这些细节。

3.2.3    as和object参数

在默认情况下,ActionView::Partials::PartialRenderer在局部视图中将创建与视图模板名称一致的局部变量。如:

<%= render partial: "product" %>

在product局部视图中,需要获取@product变量,可如此写:

     <%= render partial:"product", locals: {product: @product} %>

使用as参数,我们可以为局部变量设定不同的名称。例如,假如我们想用item来替代product,可以如此做:

<%= renderpartial: “product”, as: “item” %>

            使用object参数,常用于声明模板中使用的具体对象;当模板中的对象在别处时(例如在不同的实例变量或在本地变量),此参数将非常有用。

            例如:可将一下写法:

                       <%= render partial:"product", locals: {product: @item} %>

            转换成:

<%= render partial: "product", object: @item %>

           object和as参数可以一起使用:

         <%= render partial:"product", object: @item, as: "item" %>

3.2.4    渲染集合

通常在一个模板中需要对集合进行迭代并为每个元素渲染子模板。可以通过接受数据参数的方法直接实现,该方法接受数组类型的参数并为数组中每个元素渲染局部页面。

例如此例子中渲染所有的产品对象:

<% @products.each do |product| %>

  <%= render partial:"product", locals: { product: product } %>

<% end %>

           可以改写成:

<%= render partial: "product", collection: @products %>

           当局部视图通过此方法被调用后,视图中的单个实例将可以访问集合的成员,并使用实例的名称对视图进行渲染。在此例子中,局部视图为_product,在此视图中你可以通过product变量来获取选择的实例的数据。

           你可以使用更简单的语法来渲染集合。假如@products是Product对象的集合,那么你可以使用如下写法:

                         <%= render @products %>

          Rails将自动寻找集合中对应模型的名称,即此例子中的Product。事实上,你可以创建一个多种类型对象的集合并以这种形式进行渲染,Rails将自动选择合适的局部视图来渲染。

3.2.5    间隔区模板

你也可以使用:spacer_template参数来指定第二个局部模板,该模板将用于主模板之间渲染,如:

<%= render partial: @products, spacer_template:"product_ruler" %>

Rails将在每对_product局部视图之间渲染product_ruler局部视图(没有传入数据对象)。

3.3         布局

布局通常用于渲染Rails控制器中动作对应的共享视图。尤其,每一个Rails应用有一对全局布局用户渲染绝大多数的页面。例如,一个网站会有一个布局用于登录的用户,并且有另一个布局用于市场销售。用于已登录用户的布局,可能包含一个顶层的导航栏,此栏上应该有许多的控制器动作接口。用于软件服务应用中销售模块的布局可能会包含像‘Pricing’和‘Contact Us’之类的顶层导航。你可能希望每个布局都会有不同的展现形式。你会在Layouts and Rendering in Rails章节获取等多知识。

4          局部布局

局部视图能够有自定义的布局。此类布局不同与全局布局,但是它们原理相似。

假若我们要显示博客内容到页面上,并通过div标签来显示。

首先,需要创建一个Post对象:

         Post.create(body:‘Partial Layouts are cool!”)

在show动作的模板中,调用_post局部视图进行渲染并使用box布局。

         post/show.html.erb

                   <%=render partial: ‘post’, layout: ‘box’, locals: {post: @post} %>

在box布局中使用div标签包裹_post局部视图:

         posts/_box.html.erb

                   <divclass=’box’>

                            <%=yield %>

                   </div>

在_post局部视图中,通过post的id属性调用div_for方法,使得div包裹post的body属性。

         posts/_post.html.erb

                   <%=div_for(post) do %>

                            <p><%=post.body %></p>

                   <%end %>

生成的结果为:

 <div class='box'>

  <div id='post_1'>

    <p>Partial Layouts are cool!</p>

  </div>

</div>

注意局部布局可以访问传递给render的post变量。但是不像普通布局,局部布局命名仍然以下划线开始。

你也可以通过渲染代码块来调用局部布局的方式,来替代使用yield。例如,若你不想使用_post局部视图你可以如此做:

<% render(layout: 'box', locals: {post: @post}) do %>

  <%= div_for(post) do %>

    <p><%= post.body %></p>

  <% end %>

<% end %>

假设在上例中使用相同的布局_box,那么我们得到的生成结果是一致的。

5          视图路径

暂无

6          Action View提供的帮助方法概述

WIP:并非所有的帮助方法都在这介绍。详细列表请查看APIdocument。

接下来仅是简单概述一下ActionView中常用的帮助方法。建议多多参考API document,在那里可以查找到所有的方法,但这篇是很好的开端。

6.1         RecordTagHelper

此模块主要介绍一些生成div之类容器标签的方法。这是一种通过Active Record对象来生成容器标签的快捷方式,并且它们会自动生成id和class属性。你可以遵循命名约定来调用这些容器标签,而不要去考虑应该用什么样的id和class属性。

6.1.1    content_tag_for

渲染一个容器标签并关联到你的ActiveRecord对象。

例如,对于Post类的@post实例对象,进行如下操作:

<%= content_tag_for(:tr, @post) do %>

  <td><%= @post.title %></td>

<% end %>

将生成HTML输出为:

<tr id="post_1234" class="post">

      <td>Hello World!</td>

</tr>

你也可以通过哈希来添加额外的HTML属性,例如:

<%=content_tag_for(:tr, @post, class: "frontpage") do %>

  <td><%= @post.title %></td>

<% end %>

生成的HTML输出为:

<tr id="post_1234" class="post frontpage">

  <td>HelloWorld!</td>

</tr>

你可以传入Active Record对象集合。此方法能够循环操作对象并为每个元素创建容器标签。例如,传入一个@posts对象,该对象为包含两个Post对象的数组:

<%=content_tag_for(:tr, @posts) do |post| %>

  <td><%= post.title %></td>

<% end %>

生成的HTML输出为:

<tr id="post_1234" class="post">

  <td>HelloWorld!</td>

</tr>

<tr id="post_1235" class="post">

  <td>Rubyon Rails Rocks!</td>

</tr>

6.1.2    div_for

此方法实际上是content_tag_for的:div标签的便捷实现。你可以传入一个Active Record对象或对象集合。例如:

<%= div_for(@post, class: “frontpage”) do %>

<td><%= @post.title%></td>

<% end %>

生成的HTML结果是:

<div id="post_1234" class="postfrontpage">

  <td>HelloWorld!</td>

</div>

6.2         AssetTagHelper

此模块主要介绍与资源(如图片,JS脚本,样式和初始化数据)调用相关的方法。

默认情况下,Rails链接这些资源的目录为当前主机的public文件夹,但你可以通过设置config.action_controller.asset_host来改变此路径,尤其是在config/environments/production.rb中。例如,假设你的资源主机为assets.example.com:

config.action_controller.asset_host = "assets.example.com"

image_tag("rails.png")

# => <img src="http://assets.example.com/images/rails.png"alt="Rails" />

6.2.1    register_javascript_expansion

此方法用于注册一个或多个Javascript脚本,当其符号形式传入javascript_include_tag方法自动包含这些脚本文件。这个方法主要目的是对于安装在vendor/assets/javascripts中的插件在被调用时,初始化注册所需要的Javascript脚本。

ActionView::Helpers::AssetTagHelper.register_javascript_expansionmonkey: ["head", "body", "tail"]

javascript_include_tag :monkey # =>

  <scriptsrc="/assets/head.js"></script>

  <scriptsrc="/assets/body.js"></script>

  <scriptsrc="/assets/tail.js"></script>

6.2.2    register_stylesheet_expansion

此方法用于注册一个或多个样式文件,当其符号形式传入到stylesheet_link-tag中的时候自动包含这些文件。此方法主要用于安装在vendor/assets/stylesheets的插件被调用时初始注册包含的样式文件。

ActionView::Helpers::AssetTagHelper.register_stylesheet_expansionmonkey: ["head", "body", "tail"]

stylesheet_link_tag :monkey # =>

  <linkhref="/assets/head.css"media="screen" rel="stylesheet" />

  <linkhref="/assets/body.css"media="screen" rel="stylesheet" />

  <linkhref="/assets/tail.css"media="screen" rel="stylesheet" />

6.2.3    auto_discovery_link_tag

返回一个可供浏览器或feed阅读器获取的链接,常用于RSS或Atome feed。

auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss",{title: "RSS Feed"}) # =>

  <link rel="alternate" type="application/rss+xml"title="RSS Feed" href="http://www.example.com/feed"/>

6.2.4    image_path

计算出图片资源相对于app/assets/image目录的路径。文档根目录的全路径将被传入。通常使用image_tag内部方法来创建图片路径。

image_path("edit.png") # => /assets/edit.png

若config.assets.digest设为true,那么将在每个文件名后面添加指纹码:

image_path("edit.png") # =>/assets/edit-2d1a2db63fc738690021fedb5a65b68e.png

6.2.5    image_url

计算出app/assets/images目录下图片资源的url路径。此方法通过内部调用image_path方法与当前主机或资源主机合并生成。

image_url("edit.png") # => http://www.example.com/assets/edit.png

6.2.6    image_tag

返回图片资源的image资源标签。传入的资源可以是绝对路径或文件存在app/assets/images目录下的文件:

image_tag("icon.png") # => <imgsrc="/assets/icon.png" alt="Icon" />

6.2.7    javascript_include_tag

返回包含脚本资源的HTML script标签。你能够传入当前页面包含的脚本文件的名字(.js后缀可以不写),该脚本文件须存在于app/assets/javascript目录下,否则你需要传入相对于文档根目录的相对路径。

javascript_include_tag "common" # => <scriptsrc="/assets/common.js"></script>

如果应用不使用资源通道,若要在应用中包含jQueryJavaScript库,传入:defaults作为资源文件。当使用:defaults时,若应用的app/assets/javascripts目录下存在application.js文件,该文件将被包含:

javascript_include_tag :defaults

你也能够使用:all参数包含app/assets/javascripts目录下所有的脚本文件。

      javascript_include_tag :all

你也可以在一个文件中缓存多个JS文件,这样通过gzip(比较快速的压缩方法)压缩后,将减少下载脚本文件的HTTP连接数量。若ActionController::Base.perform_caching设置为true(生产模式中默认为true,开发模式中没有此项设置)时才可进行缓存。

javascript_include_tag :all, cache: true # =>

  <scriptsrc="/javascripts/all.js"></script>

6.2.8    javascript_path

计算出JS资源相对于app/assets/javascripts目录的相对路径。若源文件没有后缀名,那么.js将默认被添加。文档根目录的全路径将可被传入。此方法在内部通过调用javascript_include_tag来实现。

javascript_path "common" # => /assets/common.js

6.2.9    javascript_url

计算出JS资源相对于app/assets/javascripts目录的url。此方法内部通过调用javascript_path获取路径并与当前的主机或资源主机合并生成。

javascript_url "common" # => http://www.example.com/assets/common.js

6.2.10 stylesheet_link_tag

返回传入资源的样式表链接标签。若你未传入文件后缀,将自动添加.css:

stylesheet_link_tag "application" # => <linkhref="/assets/application.css" media="screen"rel="stylesheet" />

你可以使用:all参数来包含样式资源目录下的所有样式:

stylesheet_link_tag :all

你可以缓存多个文件到一个文件中,这样通过gzip压缩后,将减少对样式表的HTTP下载连接数。只能在ActionController::Base.perform_caching设置为true的情况下(此参数只在生产环境中有效),使用缓存功能。

stylesheet_link_tag :all, cache: true

# => <link href="/assets/all.css"media="screen" rel="stylesheet" />

6.2.11 stylesheet_path

计算出样式资源相对于app/assets/stylesheets目录的相对路径。若传入的资源没有后缀,将自动添加.css后缀名。文档的根目录的全路径将被传入。此方法在内部通过stylesheet_link_tag来实现:

     stylesheet_path"application" # => /assets/application.css

6.2.12 stylesheet_url

计算出传入的资源相对于app/assets/stylesheets目录的相对路径。此方法内部通过stylesheet_path获取相对路径,并和当前主机或资源主机进行合并实现。

stylesheet_url "application" #=> http://www.example.com/assets/application.css

6.3         AtomFeedHelper

6.3.1    atom_feed

通过此方法可以很方便的创建Atomefeed。以下是完整的例子:

config/routes.rb         resources :postsapp/controllers/posts_controller.rbdef index  @posts = Post.all   respond_todo |format|    format.html    format.atom  endendapp/view/posts/index.atom.builderatom_feed do |feed|  feed.title("PostsIndex")  feed.updated((@posts.first.created_at))   @posts.each do |post|    feed.entry(post) do|entry|      entry.title(post.title)      entry.content(post.body, type: 'html')       entry.author do |author|        author.name(post.author_name)      end    end  endend

6.4         BenchmarkHelper

6.4.1    benchmark

允许你测量模板中块代码的时间,并记录到日志中。将可能耗时的代码块或可能产生瓶颈的代码使用此方法进行包裹,衡量其消耗的时间。

<% benchmark "Process data files" do %>

  <%= expensive_files_operation %>

<% end %>

 这将添加一些诸如“Process data files(0.34523)”到日志文件中,你可以通过此信息来优化代码。

6.5         CacheHelper

6.5.1    cache

此方法用于缓存视图片段而不是全部的动作或页面。这个技术在缓存菜单列表,新主题列表,静态的HTML片段等等,非常有用。这个方法对块中包含的内容进行缓存。可查看ActionController::Caching::Fragments获取更多信息。

<% cache do %>

  <%= render"shared/footer" %>

<% end %>

6.6         CaptureHelper

6.6.1    capture

此方法允许你提取部分模板赋值给变量。你可以在你模板或布局中使用这些变量。

<% @greeting = capture do %>

  <p>Welcome! The date and time is <%= Time.now%></p>

<% end %>

被捕获赋值的变量可以在任何地方使用:

<html>

  <head>

    <title>Welcome!</title>

  </head>

  <body>

    <%= @greeting %>

  </body>

</html>

6.6.2    content_for

使用该方法来存储被标记的块,以便在以后调用。你可以在随后将存储的模板内容或布局以参数形式传入到yield方法中。

例如,已经有标准的应用布局,但是在一个特殊页面需要使用特定的布局。那么我们可以通过使用content_for方法来包含javascript到我们当前的页面中,并且不需要修改其他页面。

app/views/layouts/application.html.erb

<html>

  <head>

    <title>Welcome!</title>

    <%= yield :special_script %>

  </head>

  <body>

    <p>Welcome! The date and time is<%= Time.now %></p>

  </body>

</html>

app/views/posts/special.html.erb

<p>This is a special page.</p>

 

<% content_for :special_script do %>

  <script>alert('Hello!')</script>

<% end %>

6.7         DateHelper

6.7.1    date_select

返回select标签集合(年、月、日的选择下拉框),并通过关联的日期数据属性列进行初始化。

date_select("post", "published_on")

6.7.2    datetime_select

返回select标签集合(包含年、月、日、小时和分钟的选择下拉框),并通过关联时间类型的数据属性列进行初始化。

datetime_select("post", "published_on")

6.7.3    distance_of_time_in_words

得到两个时间或日期对象或秒级别时间之间的相近距离。若你想更精确的近似值,可以设置include_seconds为true。

distance_of_time_in_words(Time.now, Time.now +15.seconds)        # => less than aminute

distance_of_time_in_words(Time.now, Time.now + 15.seconds,include_seconds: true)  # => less than 20 seconds

6.7.4    select_date

返回html下拉标签集合(包含年、月、和日),可以通过传入的日期初始化。

# Generates a date select that defaults to the date provided (sixdays after today)

select_date(Time.today + 6.days)

# Generates a date select that defaults to today (no specified date)

select_date()

6.7.5    select_datetime

返回日期时间的html下拉选择标签集合(包含年、月、日、小时和分钟),可通过传入的日期时间初始化。

# Generates a datetime select that defaults to the datetime provided(four days after today)

select_datetime(Time.now + 4.days)

# Generates a datetime select that defaults to today (no specifieddatetime)

select_datetime()

6.7.6    select_day

返回可在1到31之间选择的下拉标签,默认以当天日期进行初始化。

# Generates a select field for days that defaults to the day for thedate provided

select_day(Time.today + 2.days)

# Generates a select field for days that defaults to the numbergiven

select_day(5)

6.7.7    select_hour

返回可在0到23之间选择的下拉标签,默认以当前小时进行初始化。

# Generates a select field for hours that defaults to the hours forthe time provided

select_hour(Time.now + 6.hours)

6.7.8    select_minute

返回可在0到23之间选择的下拉标签,默认以当前小时进行初始化。

# Generates a select field for minutes that defaults to the minutesfor the time provided.

select_minute(Time.now + 6.hours)

6.7.9    select_month

返回可在0到23之间选择的下拉标签,默认以当前小时进行初始化。

# Generates a select field for months that defaults to the currentmonth

select_month(Date.today)

6.7.10 select_second

返回可在0到59之间选择的下拉标签,默认以当前秒进行初始化。

# Generates a select field for seconds that defaults to the secondsfor the time provided

select_second(Time.now + 16.minutes)

6.7.11 select_time

返回选择时间的下拉标签集合(包含小时和分钟)。

# Generates a time select that defaults to the time provided

select_time(Time.now)

6.7.12 select_year

返回选择年份的下拉标签,以当前所选定的年份为轴,并前后提供各5个年份供选择。年份的选择范围可以通过:start_year和:end_year来设置。

# Generates a select field for five years on either side ofDate.today that defaults to the current year

select_year(Date.today)

# Generates a select field from 1900 to 2009 that defaults to thecurrent year

select_year(Date.today, start_year: 1900, end_year: 2009)

6.7.13 time_ago_in_words

与distance_of_time_in_words相似,但to_time修改为Time.now。

time_ago_in_words(3.minutes.from_now)  # => 3 minutes

6.7.14 time_select

返回下拉选择标签集合(包含小时、分钟和可选的秒),并与时间数据属性列相关联。这个选择器将多个参数赋值给Active Record对象。

# Creates a time select tag that, when POSTed, will be stored in theorder variable in the submitted attribute

time_select("order", "submitted")

6.8         DebugHelper

返回pre标签并显示YAML格式的对象数据。通过此方法使得对象信息变得更易读。

my_hash = {'first' => 1, 'second' => 'two', 'third'=> [1,2,3]}

debug(my_hash)

生成结果为:

<pre class='debug_dump'>---first: 1second: twothird:- 1- 2- 3</pre>

6.9         FormHelper

表单帮助方法使得标准的HTML表单标签更易与数据模型层进行相关联创建。这些帮助方法会生成HTML的表单标签,并为每个输入框提供方法(例如,text,passoword,select等等)。当表单被提交(例如,点击提交按钮或通过javascript脚本操作提交),表单中的内容将全部放入到参数对象中并传入到控制器。

有两种类型的表单帮助方法:一些与数据模型关联;另一些则不关联。这类帮助方法处理着数据模型的相关属性;可在ActionView::Helpers::FormTagHelper文档中查看到与数据模型层不关联的例子。

此帮助方法的核心是,form_for,通过它可以创建数据模型层的表单;例如,对于Person类的数据模型,创建一个新的实例对象:

# Note: a @person variablewill have been created in the controller (e.g. @person = Person.new)<%= form_for @person, url: {action: "create"} do |f|%>  <%= f.text_field :first_name %>  <%= f.text_field :last_name %>  <%= submit_tag 'Create' %><% end %>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">生成的HTML结果为:</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><p><form action="/people/create" method="post"></p><p><span style="color: rgb(34, 34, 34);">  </span><input id="person_first_name" name="person[first_name]" type="text" /></p><p><span style="color: rgb(34, 34, 34);">  </span><input id="person_last_name" name="person[last_name]" type="text" /></p><p><span style="color: rgb(34, 34, 34);">  </span><input name="commit" type="submit" value="Create" /></p><p></form></p>

               当此表单被提交后,提交的对象为:

{"action" => "create", "controller"=> "people", "person" => {"first_name"=> "William", "last_name" => "Smith"}}

             参数哈希中有一个内嵌的person键值对,在控制器中可以通过访问params[:person]来获取值。

6.9.1    check_box

返回单选框标签,并与属性列进行关联。

# Let's say that @post.validated? is 1:

check_box("post", "validated")

# => <input type="checkbox"id="post_validated" name="post[validated]"value="1" />

#    <input name="post[validated]"type="hidden" value="0" />

6.9.2    fields_for

创建具体数据模型对象的标签,与form_for相似,但是不会创建form标签。在同一个表单中,此方法适合指定具体的数据模型对象:

<%= form_for @person, url: {action: "update"} do|person_form| %>  First name: <%= person_form.text_field :first_name%>  Last name : <%= person_form.text_field :last_name%>  <%= fields_for @person.permission do|permission_fields| %>    Admin?  : <%=permission_fields.check_box :admin %>  <% end %><% end %>

6.9.3    file_field

返回一个关联数据属性列的上传文件输入框。

file_field(:user, :avatar)

# => <input type="file" id="user_avatar"name="user[avatar]" />

6.9.4    form_for

创建一个表单,并关联数据模型,在此表单区域可实现具体属性列的关联。

<%= form_for @post do |f| %>  <%= f.label :title, 'Title' %>:  <%= f.text_field :title %><br>  <%= f.label :body, 'Body' %>:  <%= f.text_area :body %><br><% end %>

6.9.5    hidden_field

返回隐藏的输入标签,可以关联具体的属性。

hidden_field(:user, :token)

# => <input type="hidden" id="user_token"name="user[token]" value="#{@user.token}" />

6.9.6    label

返回label标签,并可关联到具体属性上。

label(:post, :title)

# => <label for="post_title">Title</label>

6.9.7    password_field

返回输入密码的input标签,可关联属性列。

password_field(:login, :pass)

# => <input type="text" id="login_pass"name="login[pass]" value="#{@login.pass}" />

6.9.8    radio_button

返回单选按钮标签,可关联属性列。

# Let's say that @post.category returns "rails":

radio_button("post", "category","rails")

radio_button("post", "category","java")

# => <input type="radio"id="post_category_rails" name="post[category]"value="rails" checked="checked" />

#    <input type="radio"id="post_category_java" name="post[category]"value="java" />

6.9.9    text_area

返回textarea标签,可设置特定的属性。

text_area(:comment, :text, size: "20x30")

# => <textarea cols="20" rows="30"id="comment_text" name="comment[text]">

#      #{@comment.text}

#    </textarea>

6.9.10 text_field

返回text类型的input标签,可设置特定的属性。

text_field(:post, :title)

# => <input type="text" id="post_title"name="post[title]" value="#{@post.title}" />

6.9.11 email_field

返回email类型的input标签,可设置具体的属性。

email_field(:user, :email)

# => <input type="email" id="user_email"name="user[email]" value="#{@user.email}" />

6.9.12 url_field

返回url类型的input标签,可设置具体的属性。

url_field(:user, :url)

# => <input type="url" id="user_url" name="user[url]"value="#{@user.url}" />

6.10      FormOptionsHelper

提供一些方法将不同类型的容器转变成选项标签集合。

6.10.1 collection_select

返回select和option标签,并赋以对象的类方法返回的值集合。

例如,对象的结果及方法如下:

class Post < ActiveRecord::Base  belongs_to:authorendclass Author < ActiveRecord::Base  has_many :posts  def name_with_initial    "#{first_name.first}. #{last_name}"  endend

简单示例(为Post类的实例对象@post选择关联的Anthor对象):

      collection_select(:post, :author_id,Author.all, :id, :name_with_initial, {prompt: true})

若@post_author.id是1,将返回如下信息:

<select name="post[author_id]">  <option value="">Pleaseselect</option>  <option value="1" selected="selected">D.Heinemeier Hansson</option>  <option value="2">D.Thomas</option>  <option value="3">M.Clark</option></select>

6.10.2 collection_radio_buttons

返回radio_button标签,并赋以对象的类方法返回的值集合。

例如,对象的结果及方法如下:

class Post < ActiveRecord::Base  belongs_to:authorendclass Author < ActiveRecord::Base  has_many:posts  def name_with_initial    "#{first_name.first}. #{last_name}"  endend

             简单示例(为Post类的实例对象@post选择关联的Anthor对象):

collection_radio_buttons(:post, :author_id, Author.all, :id,:name_with_initial)

            若@post_author.id是1,将返回如下信息:

<span style="white-space:pre"></span><input id="post_author_id_1" name="post[author_id]" type="radio" value="1" checked="checked" /><span style="white-space:pre"></span><label for="post_author_id_1">D. HeinemeierHansson</label><span style="white-space:pre"></span><input id="post_author_id_2" name="post[author_id]" type="radio" value="2" /><span style="white-space:pre"></span><label for="post_author_id_2">D. Thomas</label><span style="white-space:pre"></span><input id="post_author_id_3" name="post[author_id]" type="radio" value="3" /><span style="white-space:pre"></span><label for="post_author_id_3">M. Clark</label>

6.10.3 collection_check_boxes

返回check_box标签,并赋以对象的类方法返回的值集合。

例如,对象的结果及方法如下:

class Post < ActiveRecord::Base  has_and_belongs_to_many :authorsend class Author < ActiveRecord::Base  has_and_belongs_to_many :posts  def name_with_initial    "#{first_name.first}. #{last_name}"  endend

简单示例(为Post类的实例对象@post选择关联的Anthor对象):

collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial)

若@post.author_id是1,将返回如下信息:

<input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" /><label for="post_author_ids_1">D. Heinemeier Hansson</label><input id="post_author_ids_2" name="post[author_ids][]" type="checkbox" value="2" /><label for="post_author_ids_2">D. Thomas</label><input id="post_author_ids_3" name="post[author_ids][]" type="checkbox" value="3" /><label for="post_author_ids_3">M. Clark</label><input name="post[author_ids][]" type="hidden" value="" />

6.10.4 country_options_for_select

返回所有的国家选择标签。

6.10.5 country_select

返回指定对象方法的关联的下拉选择框,并使用country_options_for_select来生成选择列表。

6.10.6 option_groups_from_collection_for_select

返回option标签,像options_from_collection_for_select,但是通过optgroup标签基于对象参数之间的关联关系来组织他们。

例如,对象的结果及方法如下:

class Continent < ActiveRecord::Base

  has_many:countries

  # attribs:id, name

end

class Country < ActiveRecord::Base

  belongs_to:continent

  # attribs:id, name, continent_id

end

简单用法:

option_groups_from_collection_for_select(@continents, :countries,:name, :id, :name, 3)

 可能的输出为:

<optgroup label="Africa">

  <option value="1">Egypt</option>

  <option value="4">Rwanda</option>

  ...

</optgroup>

<optgroup label="Asia">

  <option value="3" selected="selected">China</option>

  <option value="12">India</option>

  <option value="5">Japan</option>

  ...

</optgroup>

 注意:只有optgroup和option被返回,因此你仍然需要使用select标签包裹它们。

6.10.7 options_for_select

接收一个容器(哈希,数组,枚举,你的类型)并返回一个option标签包裹的字符串。

options_for_select([ "VISA", "MasterCard" ])

# => <option>VISA</option><option>MasterCard</option>

注意:只有option标签被返回,你需要使用select标签包裹它们。

6.10.8 options_from_collection_for_select

通过对collection参数的迭代,通过value_method获取value属性的值,通过text_method获取text属性的值,返回option标签包裹的字符串。

# options_from_collection_for_select(collection, value_method,text_method, selected = nil)

例如,通过对@project.people中每个person的迭代,生成选择栏:

options_from_collection_for_select(@project.people, "id","name")

# => <optionvalue="#{person.id}">#{person.name}</option>

注意:返回的只是option标签,你需要使用select标签包裹结果。

6.10.9 select

创建下拉选择列表框,和通过提供的方法和对象获取的一系列的可选选项。

例如:

select("post", "person_id", Person.all.collect{|p| [ p.name, p.id ] }, {include_blank: true})

若@post.person_id的话,将变成:

<select name="post[person_id]">

  <option value=""></option>

  <option value="1" selected="selected">David</option>

  <option value="2">Sam</option>

  <option value="3">Tobias</option>

</select>

6.10.10     time_zone_options_for_select

返回世界所有时区的可选择option标签选项。

6.10.11     time_zone_select

返回世界所有时区的下拉列表框,通过time_zone_options_for_select来生成可选标签。

time_zone_select( "user", "time_zone")

6.10.12     date_field

返回date类型的input标签,并可关联属性。

date_field("user", "dob")

6.11      FormTagHelper

提供了一些方法来不依赖ActiveRecord对象(与FormHelper不同),来创建表单标签。在创建的时候,你只需要手动提供命名和值即可。

6.11.1 check_box_tag

创建一个选择按钮。

check_box_tag 'accept'

# => <input id="accept" name="accept"type="checkbox" value="1" />

6.11.2 field_set_tag

为HTML中标签元素创建区域集合。

<%= field_set_tag do %>

  <p><%= text_field_tag 'name' %></p>

<% end %>

# => <fieldset><p><input id="name"name="name" type="text" /></p></fieldset>

6.11.3 file_field_tag

创建文件上传选择框。

<%= form_tag({action:"post"}, multipart: true) do %>

  <label for="file">File toUpload</label> <%= file_field_tag "file" %>

  <%= submit_tag %>

<% end %>

示例输出:

 file_field_tag'attachment'

# => <input id="attachment"name="attachment" type="file" />

6.11.4 form_tag

以具体的路由路径来创建一个表单。该路径可通过与ActionController::Base#url_for相似的url_for_options进行设置。

<%= form_tag '/posts' do %>

  <div><%= submit_tag 'Save' %></div>

<% end %>

# => <form action="/posts"method="post"><div><input type="submit"name="submit" value="Save" /></div></form>

6.11.5 hidden_field_tag

创建一个隐藏的数据输入框,通常来保存一些无法在HTTP传输中保持的状态信息。

hidden_field_tag 'token', 'VUBJKB23UIVI1UU1VOBVI@'

# => <input id="token" name="token"type="hidden" value="VUBJKB23UIVI1UU1VOBVI@" />

6.11.6 image_submit_tag

显示指定图片作为提交按钮,点击图片即提交表单。

image_submit_tag("login.png")

# => <input src="/images/login.png"type="image" />

6.11.7 label_tag

创建标签域。

label_tag 'name'

# => <label for="name">Name</label>

6.11.8 password_field_tag

创建密码输入框,并使用标记符隐藏输入的密码。

password_field_tag 'pass'

# => <input id="pass" name="pass"type="password" />

6.11.9 radio_button_tag

创建了点选按钮;使用一组点选按钮使用相同的命名,允许用户对同组中按钮进行单选。

radio_button_tag 'gender', 'male'

# => <input id="gender_male" name="gender"type="radio" value="male" />

6.11.10     select_tag

创建下拉选择框。

select_tag "people","<option>David</option>"

# => <select id="people"name="people"><option>David</option></select>

6.11.11     submit_tag

使用传入的文本,创建提交按钮。

submit_tag "Publish this post"

# => <input name="commit" type="submit"value="Publish this post" />

6.11.12     text_area_tag

创建文本输入框;常使用textarea作为长文本的输入例如发布博客或描述信息。

text_area_tag 'post'

# => <textarea id="post"name="post"></textarea>

6.11.13     text_field_tag

创建标准的文本输入框;常使用该类文本框作为小块文本输入,如用户名或搜索框。

text_field_tag 'name'

# => <input id="name" name="name"type="text" />

6.11.14     email_field_tag

创建标准邮箱类型输入框。

email_field_tag 'email'

# => <input id="email" name="email"type="email" />

6.11.15     url_field_tag

创建标准url类型的标准输入框。

url_field_tag 'url'

# => <input id="url" name="url"type="url" />

6.11.16     date_field_tag

创建标准的日期输入框。

date_field_tag "dob"

# => <input id="dob" name="dob"type="date" />

6.12      JavaScriptHelper

提供你视图中包含Javascript的方法。

6.12.1 button_to_function

然会一个拥有onclick事件的按钮。例如:

button_to_function "Greeting", "alert('Helloworld!')"

button_to_function "Delete", "if (confirm('Really?'))do_delete()"

button_to_function "Details" do |page|

  page[:details].visual_effect:toggle_slide

end

6.12.2 define_javascript_funtions

将Action PackJavascript库通过一个script标签包含。

6.12.3 escape_javascript

编码javascript中的字符,使得脚本传输后仍可执行。

6.12.4 javascript_tag

返回一个Javascript标签包裹着传入的代码。

javascript_tag "alert('All is good')"

生成的HTML为:

<script>

//<![CDATA[

alert('All is good')

//]]>

</script>

6.12.5 link_to_function

返回一个链接,该链接可触发onclick事件并返回false。

link_to_function "Greeting", "alert('Hello world!')"

# => <a onclick="alert('Hello world!'); returnfalse;" href="#">Greeting</a>

6.13      NumberHelper

提供方法将数字转换成指定格式的字符串。对手机号、货币、百分数、精度、地理位置和文件大小提供了帮助方法。

6.13.1 number_to_currency

将数字转换成货币字符串。(例如:$13.65)

number_to_currency(1234567890.50) # => $1,234,567,890.50

6.13.2 number_to_human_size

将字节形式的大小表示转换成更易读的形式;在报告文件大小的时候非常有用。

number_to_human_size(1234)         # => 1.2 KB

number_to_human_size(1234567)       #=> 1.2 MB

6.13.3 number_to_percentage

将数字转成百分比字符串。

number_to_percentage(100, precision:0)        # => 100%

6.13.4 number_to_phone

将数字转换成美国电话号码。

number_to_phone(1235551234) # => 123-555-1234

6.13.5 number_with_delimiter

以每三位插入一个分隔符的形式格式化数字。

number_with_delimiter(12345678) # => 12,345,678

6.13.6 number_with_precision

通过具体的精度等级,来格式话数字,默认为3为有效小数。

number_with_precision(111.2345)     # =>111.235

number_with_precision(111.2345, 2)  # => 111.23

6.14      SanitizeHelper

该模块提供了一些方法,这些方法用于净化文本中不希望存在的HTML元素。

6.14.1 sanitize

该方法将对html进行编码,去除所有不允许的属性。

      sanitize @article.body

若:attributes或:tags参数被传入,只有这些被传入的标签和属性可以通过,其他都想被去除。

sanitize@article.body, tags: %w(table tr td), attributes: %w(id class style)

通过以下途径可以更改默认的过滤设置,例如在默认的列表中添加table标签:

class Application <Rails::Application

  config.action_view.sanitized_allowed_tags= 'table', 'tr', 'td'

end

6.14.2 sanitize_css(style)

净化CSS代码块。

6.14.3 strip_links(html)

从链接标签中剥去其他元素,直流链接的文本。

例1:

strip_links("<a href="http://rubyonrails.org">Rubyon Rails</a>")

# => Ruby on Rails

例2:

   strip_links("emailsto <a href="mailto:me@email.com">me@email.com</a>.")

# => emails to me@email.com.

例3:

strip_links('Blog: <a href="http://myblog.com/">Visit</a>.')

# => Blog: Visit.

6.14.4 strip_tags(html)

从html文本中剥去所有的HTML标签,包括注释。这个通常用于html扫描分词器,因此HTML的解析能力被html扫描器限制。

strip_tags("Strip <i>these</i> tags!")

# => Strip these tags!

strip_tags("<b>Bold</b> no more!  <ahref='more.html'>See more</a>")

# => Bold no more!  See more

            注:输出可能仍然包含有未逃逸的字符’<’,’>’,’&’字符并迷惑浏览器。

7          本地化视图

Action View有能力渲染根据不同的地址位置渲染不同的模板。

例如,假设你的PostsController下有show动作。默认情况下,调用此动作将渲染app/views/posts/show.html.erb页面。但是,你若设置了I18n.locale= :de,那么将渲染app/views/posts/show.de.html.erb。若本地化模板不存在,未本地化的模板将会调用。这就意味着你不需要提供为所有情况提供本地化模板,你只需要提供你所需要的本地化模板即可。

你能够用同样的技术去本地化你public目录下的错误页面。例如,若设置了I18n.locale = :de并创建了public/500.de.html和public/404.de.html,将允许你使用本地化的错误页面。

自从Rails不限制I18n.locale时的符号,你能够利用此机制来根据你的需求显示不同的内容。例如,假设你有一些专家用户,这些用户可以看到普通用户无法看到的特殊页面。那么你可以如此的配置app/controller/application.rb:

before_action:set_expert_locale

def set_expert_locale

  I18n.locale= :expert if current_user.expert?

end

             然会你可以通过创建特定的视图,如app/views/posts/show.expert.html.erb来显示专家用户可查看的内容。

             你可以在RailsInternationalization(I18n) API章节获取更多信息。
0 0
原创粉丝点击