Rails3 入门之六 建立一个资源

来源:互联网 发布:怎么屏蔽网络垃圾短信 编辑:程序博客网 时间:2024/05/17 21:34

在blog 应用程序中。你可以通过脚手架(scaffolded)开始建立一个资源。

这将是单一的blog 提交。请输入以下命令

$ rails generate scaffold Post name:string title:string content:text
脚手架将会建立一些文件和目录,然后编辑config/routes.rb文件。

下面是脚手架建立的文件概要。

FilePurposedb/migrate/20100207214725_create_posts.rb建立 posts 表在你的数据库整合程序(名字将包含一个不同时刻)app/models/post.rbPost 模型test/fixtures/posts.yml虚设的 posts 用来测试app/controllers/posts_controller.rbPosts控制器app/views/posts/index.html.erb显示所有Post的视图app/views/posts/edit.html.erb编辑一个已经存在的Post的视图app/views/posts/show.html.erb显示单个post的视图app/views/posts/new.html.erb新建一个新的post的视图app/views/posts/_form.html.erb一个局部模板用在编辑和显示页面上的app/helpers/posts_helper.rbpost视图里面用的一些帮助函数app/assets/stylesheets/scaffold.css.scss脚手架样式表可以让页面看起来更加好app/assets/stylesheets/post.css.scsspost控制器使用的样式表app/assets/javascripts/post.js.coffeepost控制器使用的CoffeeScripttest/unit/post_test.rbpost模型的单元测试工具test/functional/posts_controller_test.rbpost控制器的功能测试工具test/unit/helpers/posts_helper_test.rbpost帮助函数的测试工具config/routes.rbposts的路由

虽然脚手架将得到您快速启动和运行,它生成的代码是不可能成为一个完美契合您的应用程序。你很可能要自定义生成的代码。许多经验丰富的Rails开发完全避免脚手架,宁愿写所有或从头开始自己的源代码。 Rails的,但是,它真的很简单,自定义生成的模型,控制器,视图和其他源文件的模板。 Rails的控制器及模板指导的创建和定制,你会发现更多的信息在 http://guides.rubyonrails.org/generators.html

6.1 运行一个DB整合(Migration)

rails的一个产品,产生脚手架命令是一个数据库整合。

整合是一个ruby类被设计成可以简单的建立新的数据库表和修改数据库表。

rails用Rake命令来运行数据库整合。也可以取消一次已经申请到数据库中的

数据库整合,整合文件名包含一个时间,以确保按照根据创建时间顺序处理。

如果你去看db/migrate/20100207214725_create_posts.rb这个文件(请注意

你一定是有一个不一样的名字)。下面是这个文件的内容。

class CreatePosts < ActiveRecord::Migration  def change    create_table :posts do |t|      t.string :name      t.string :title      t.text :content       t.timestamps    end  endend

上面的整合新建了一个change方法。当你运行migration命令,将会调用到这个方法。

这个方法是可以逆转运行的。也就是说rails知道怎么运行这个命令的逆转。如果你想

以后运行逆转的话。默认的话,你运行这个整合,将会创建一个表,有5个字段,包含

2个string列和一个text列。他还会建立2个时间字段记录数据建立时间和更新时间。想

知道更多信息,请点击Rails DatabaseMigrations链接。

这个时候,你可以运行rake命令进行数据整合。

$ rake db:migrate
rails将会运行整合命令,并且告诉你帮你建立好了posts表.
==  CreatePosts: migrating ====================================================-- create_table(:posts)   -> 0.0019s==  CreatePosts: migrated (0.0020s) ===========================================

因为你在开发环境中工作在默认情况下,该命令将适用于config / database.yml文件开发部分定义数据库

如果你想其他环境数据库整合在产品(production)环境中实例执行,你必须明确地传递给它在调用命令

rake db:migrate RAILS_ENV=production.


6.2 增加一个链接

为了可以访问你已经建立好的posts的页面,我们在主页上面增加一个链接。

打开app/views/home/index.html.erb 像下面那样编辑。

<h1>Hello, Rails!</h1><%= link_to "My Blog", posts_path %>
link_to方法是rails的视图帮助里面的方法。他新建了一个超级链接

并且显示出来。在这个例子中是指向posts路径。


6.3 在浏览器里面运行post

现在你可以运行post了。打开浏览器访问 http://localhost:3000,

然后点击“My blog"链接。可以看到下面的页面。

这是访问post主页的页面。现在数据库里面没有一条

post。你可以点击“New Post"建立一个新的post。

建好之后,你会发现你可以编辑他们并且删除他们,

查看他们的细节。所有的这些逻辑都是用rails的脚手架

命令完成的。

在开发模式下(默认的开发模式),rails会重新装载你的程序根据http请求,所以在开发模式下,不需要重启你的rails程序。

恭喜你,你已经成功运行rails。现在是时候需要知道他们怎么工作了。

6.4 模型

模型文件app/models/post.rb。是一个非常简单的文件。

class Post < ActiveRecord::Baseend
在这个文件里面没有很多东西。

你可以注意到这个Post类继承自ActiveRecord::Base类。

ActiveRecord提供了很多有用的免费函数给我们rails模型。

例如基本的数据库操作(增/改/查询/删除),数据校验。

和支持先进的多个模型之间的查询。

6.5 增加部分校验

rails包含一些校验的方法。

可以校验你发给模型的数据。

打开app/models/post.rb文件,编辑它。

class Post < ActiveRecord::Base  validates :name,  :presence => true  validates :title, :presence => true,                    :length => { :minimum => 5 }end

上面表示post提交的时候,必须有name和title。并且title的长度

不能小于5. 

rails可以做很多的校验在模型中,包括存在性,唯一性,他们的格式,

相关连对象的存在性校验。


6.6 使用控制台(console)

为了可以看见校验的效果。你可以使用控制台命令。

控制台是一个工具,可以在你工程的上下文中运行ruby代码。

$ rails console

默认的console命令下,运行代码将会改变数据库。如果你不想让数据库改变,运行完代码能够自动回滚的话,

请使用rails console --sandbox 命令。

当控制台加载完以后,你可以使用你的模型类。

>> p = Post.new(:content => "A new post")=> #<Post id: nil, name: nil, title: nil,     content: "A new post", created_at: nil,     updated_at: nil>>> p.save=> false>> p.errors=> #<OrderedHash { :title=>["can't be blank",                           "is too short (minimum is 5 characters)"],                   :name=>["can't be blank"] }>
这段代码是想建立一个新的post。想存储到数据库。但是遇到模型的校验,

发生错误了。


如果你想退出控制台环境,请输入exit 和 hit 退出控制台环境。

不像在开发模式情况下,你如果修改代码,将会自动反应。

当你在打开控制台的情况下,模型发生改变的话,请运行

reload! 命令,将会加载最新的模型。


6.7 所有的post列表

最简单的学习rails的功能是看列表的代码。

打开app/controllers/posts_controller.rb 文件,看index方法。

def index  @posts = Post.all   respond_to do |format|    format.html  # index.html.erb    format.json  { render :json => @posts }  endend
Post.all是通过post模型返回当前数据库中的所有post数据。
这个方法返回的数组结果我们存储在@posts这个实例变量里面。

想知道更多关于查询数据的activerecord.请ActiveRecord Query Interface.章节。

在上面块代码里面返回2种格式,HTML和JSON.

如果你访问http://localhost:3000/posts.json。会看到返回的json数据包含所有的post。

html格式是寻找app/views/posts/目录下和action名字一样的视图。rails保证

所有在action里面的实例变量在视图中可以访问。下面是

app/views/posts/index.html.erb

<h1>Listing posts</h1> <table>  <tr>    <th>Name</th>    <th>Title</th>    <th>Content</th>    <th></th>    <th></th>    <th></th>  </tr> <% @posts.each do |post| %>  <tr>    <td><%= post.name %></td>    <td><%= post.title %></td>    <td><%= post.content %></td>    <td><%= link_to 'Show', post %></td>    <td><%= link_to 'Edit', edit_post_path(post) %></td>    <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>  </tr><% end %></table> <br /> <%= link_to 'New post', new_post_path %>

这个视图循环@posts来显示所有的post内容和链接。下面是一些注意点:

link_to是代表建立了一个链接。

edit_post_pathnew_post_pathRails的RESTful路由一部分提供

    你会看到多种不同的动作控制器包括这些

在以前版本的Rails,你必须使用<%= H post.name%>,让任何HTML会被插入到页面中之前,进行转义。在Rails3.0,这是现在的默认。要得到的HTML不转义的,你现在可以使用<%=raw post.name%。

想要知道更多关于render请看Layouts and Rendering inRails.


6.8 定制你自己的布局

视图是用来控制显示在浏览器里面的html。rails当然也有布局的功能,

布局包含视图。当rails想显示视图的时候,他会将视图的html代码嵌入到

布局中来显示。在以前的rails版本中,rails会给每个控制器建立布局。

像app/views/layouts/posts.html.erb,是post控制器的。然而

在rails 3.0里面这个已经改变了,有一个全局的布局为所有的控制器,

app/views/layouts/application.html.erb。打开这个文件,

可以修改里面的Body标签。

<!DOCTYPE html><html><head>  <title>Blog</title>  <%= stylesheet_link_tag "application" %>  <%= javascript_include_tag "application" %>  <%= csrf_meta_tags %></head><body style="background: #EEEEEE;"> <%= yield %> </body></html>

如果你刷新下posts 页面,你会发现背景色变成灰色了。

这个将会使post相关的所有页面都改变。

6.9 创建一个新的Post

创建新的post需要2个步骤。第一个步骤就是下面的new方法。

他建立了一个空的post。

def new  @post = Post.new   respond_to do |format|    format.html  # new.html.erb    format.json  { render :json => @post }  endend
new.html.erb显示的是建立一个空的post给用户。
<h1>New post</h1> <%= render 'form' %> <%= link_to 'Back', posts_path %>

<%= render 'form' %>这行代码是我们第一次介绍partials.

snippet是一个包含ruby代码的html片段。可以在很多页面重复使用。

上面的例子中的form也可以用在post编辑页面。因为编辑页面也有同样的

名字,内容字段和提交按钮可以新建和编辑存在的post。

下面是form partials的代码。

<%= form_for(@post) do |f| %>  <% if @post.errors.any? %>  <div id="errorExplanation">    <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>    <ul>    <% @post.errors.full_messages.each do |msg| %>      <li><%= msg %></li>    <% end %>    </ul>  </div>  <% end %>   <div class="field">    <%= f.label :name %><br />    <%= f.text_field :name %>  </div>  <div class="field">    <%= f.label :title %><br />    <%= f.text_field :title %>  </div>  <div class="field">    <%= f.label :content %><br />    <%= f.text_area :content %>  </div>  <div class="actions">    <%= f.submit %>  </div><% end %>

partials可以使用任何调用它的页面里面的实例变量。在上面的例子里面,

控制器把新建的post实例变量设定到@post里面,所以这个变量可以在

视图和partials里面使用。

想了解更多partials的信息,请参考Layouts and Rendering inRails 。

form_for块是用来创建一个新的html form。你可以使用form的方法
建立各种控件。例如:f.text_field :name的意思是让rails建立一个
文本框在form里面,并且显示实例变量@post的name属性的值。

你只能使用这些方法的参数所实例的属性。例子中的话,只能是

名称,标题和内容。rails用form_for是为了写出更简洁的代码,

更接近html代码。可以让from和实例变量紧紧联系在一起。

form_for非常灵活,可以在新建post和更新post时候使用。

将会适当的设定form的action和提交按钮的名字显示成html。


如果你想新建一个form来显示任何字段,而不是绑定一个model的话,

你应该使用form_tag方法,它提供了建立form而不需要绑定model实例。


当你点击create post按钮,浏览器将会把信息发送到控制器的create方法。

(这个调用是rails框架完成的)

def create  @post = Post.new(params[:post])   respond_to do |format|    if @post.save      format.html  { redirect_to(@post,                    :notice => 'Post was successfully created.') }      format.json  { render :json => @post,                    :status => :created, :location => @post }    else      format.html  { render :action => "new" }      format.json  { render :json => @post.errors,                    :status => :unprocessable_entity }    end  endend

create动作将会建立一个新的Post对象实例,这个对象实例数据是从form中取出来的。

rails把这个对象实例存在params散列表里面。控制器可以 自由访问。

在上面的代码里,数据库存储好post之后,根据用户请求的返回适当的格式给用户。

在上面的例子里,是转到show动作页面来显示结果。并且通知用户post已经成功建立了。


如果post不能成功的保存到数据库。假设是一个校验错误,控制器会返回到new页面,显示错误信息,

用户可以根据错误信息修改重新提交。


“Post was successfully created”信息存储在Rails flash散列表里面。这样的话,才能把这些信息

传递到其他动作里面。用户可以获取request的状态信息。在上面create的情况下,用户没有能看到

任何页面显示在post建立的时候,是因为rails立即转向到new post。同时也很快的保存好了记录。

flash把装载着一个信息传给下个动作,所以当用户重定向到show动作,他们可以显示

“Post was successfully created”信息。

6.10 显示一个独立的Post

当你点击主页的show链接。他将会显示一个这样的URL地址。http://localhost:3000/posts/1

rails把这个处理调用show动作。并且传递1给show动作。下面是show动作的代码,

def show  @post = Post.find(params[:id])   respond_to do |format|    format.html  # show.html.erb    format.json  { render :json => @post }  endend
这个show动作里面调用Post.find方法去检索一条post记录。在检索到之后,

通过show.html.erb来显示页面。

<p class="notice"><%= notice %></p> <p>  <b>Name:</b>  <%= @post.name %></p> <p>  <b>Title:</b>  <%= @post.title %></p> <p>  <b>Content:</b>  <%= @post.content %></p>  <%= link_to 'Edit', edit_post_path(@post) %> |<%= link_to 'Back', posts_path %>

6.11 编辑post

像新建一个post一样,编辑post也需要2步。第一步是调用

edit_post_path(@post)请求,这将会调用edit动作在控制器里面。

def edit  @post = Post.find(params[:id])end
在查询到post记录之后,rails使用edit.html.erb来显示。

<h1>Editing post</h1> <%= render 'form' %> <%= link_to 'Show', @post %> |<%= link_to 'Back', posts_path %>

在这里和新建post一样都用了form模板(partial),但这时候

将会有调用put动作到控制器,submit按钮将会变成“Update Post”。

提交按钮将会调用update动作在控制器里面。

def update  @post = Post.find(params[:id])   respond_to do |format|    if @post.update_attributes(params[:post])      format.html  { redirect_to(@post,                    :notice => 'Post was successfully updated.') }      format.json  { render :json => {}, :status => :ok }    else      format.html  { render :action => "edit" }      format.json  { render :json => @post.errors,                    :status => :unprocessable_entity }    end  endend

在更新的动作里面,rails第一次使用了:id参数来定位需要编辑的数据。

update_attributes根据参数传过来的rest更新数据库。如果更新成功,将会

去显示页面。如果更新失败,将会回到编辑页面以便修改重新提交。

6.12 删除post

点击destory链接,将会调用destory动作。

def destroy  @post = Post.find(params[:id])  @post.destroy   respond_to do |format|    format.html { redirect_to posts_url }    format.json { head :ok }  endend

destory方法将会删除数据库中的记录。在这做完以后,

因为记录被删除了,所以将会回到index页面。