在blog 应用程序中。你可以通过脚手架(scaffolded)开始建立一个资源。
这将是单一的blog 提交。请输入以下命令
- $ rails generate scaffold Post name:string title:string content:text
脚手架将会建立一些文件和目录,然后编辑config/routes.rb文件。
下面是脚手架建立的文件概要。
File | Purpose |
---|---|
db/migrate/20100207214725_create_posts.rb | 建立 posts 表在你的数据库整合程序(名字将包含一个不同时刻) |
app/models/post.rb | Post 模型 |
test/fixtures/posts.yml | 虚设的 posts 用来测试 |
app/controllers/posts_controller.rb | Posts控制器 |
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.rb | post视图里面用的一些帮助函数 |
app/assets/stylesheets/scaffold.css.scss | 脚手架样式表可以让页面看起来更加好 |
app/assets/stylesheets/post.css.scss | post控制器使用的样式表 |
app/assets/javascripts/post.js.coffee | post控制器使用的CoffeeScript |
test/unit/post_test.rb | post模型的单元测试工具 |
test/functional/posts_controller_test.rb | post控制器的功能测试工具 |
test/unit/helpers/posts_helper_test.rb | post帮助函数的测试工具 |
config/routes.rb | posts的路由 |
- 虽然脚手架将得到您快速启动和运行,它生成的代码是不可能成为一个完美契合您的应用程序。你很可能
- 要自定义生成的代码。许多经验丰富的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
- end
- end
上面的整合新建了一个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::Base
- end
在这个文件里面没有很多东西。
你可以注意到这个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 }
- end
- end
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_path和new_post_path是Rails的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 }
- end
- end
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里面使用。
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
- end
- end
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 }
- end
- end
这个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
- end
- end
在更新的动作里面,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 }
- end
- end
destory方法将会删除数据库中的记录。在这做完以后,
因为记录被删除了,所以将会回到index页面。