一, 功能设计
借鉴例子my Blog,构造个人空间网站my Zone。基于restful风格实现基本的文章发布和文章评论功能。设计两个实体:post和comment。
二, 环境配置
采用ruby –v 1.8.6版本,rails更新为2.3.8。使用默认数据库sqlite3。Sqlite3.exe文件下载到C盘目录下才能正常安装。
三, 实施步骤
1. 创建Rails项目
创建myZone项目,实现文章(Post)发布,和文章评论(Comment)
2. 通过scaffold命令
ruby script/generate scaffold post title:string doc:text
ruby script/generate scaffold comment post:references doc:text
scaffold生成了默认的Controller,Model,View,数据迁移文件,以及路由。此处考虑到用scaffold命令可以直接生成comments MODEL模型,免去手工创建的麻烦,于是post和comment都采用了scaffold命令。而且定义了外键约束references。
3. Model
在ActiveRecord中添加如下表示外键约束的关系:
class Post < ActiveRecord::Base (手动修改)
has_many :comments
end
Class Comment < ActiveRecord::Base (自动生成) belongs_to :post
end
4. 设置路由
默认情况下,scaffold自动生成的路由如下:
map.resources :posts
map.resources :comments
我们现在要实现一个嵌套路由,所以修改如下:
map.resources :posts, :has_many=>:comments
# map.resources :posts
5. controller的设置
设置了路由以后,我们必须准备让CommentsController被嵌套,所以我们对Controller作以下修改:
要修改的Controller包括两部分。
一部分是要找到Comments所依赖的“父“资源:
before_filter :load_post
def load_post
@post=Post.find(params[:post_id])
end
这里的@post将在所有的comments控制器的action中设置好了。
第二部分是要修改或的comment的命令,思想是:不是获得所有comments,而是获得@post下的所有comments
修改前 |
修改后 |
Comment.find |
@post.comments.find |
Comment.new |
@post.comments.build |
Redirect_to(@comment) |
Redirect_to([@post,@comment]) |
Redirect_to(comments_url) |
Redirect_to(post_comments_url(@post)) |
6. view的修改
1)comments视图
修改所有的具名路由,对于嵌套路由,comment是依赖于post而存在的。
#-----_comment.html.erb (没有这个文件,手工创建)
<% form_for([@post,@comment]) do |f|%>
Doc
<%=f.text_area :doc%>
<%= f.submit button_name%>
<%end%>
#------new.html.erb
<%= error_messages_for :comment %>
<%= render :partial=>@comment,:locals=>{:button_name=>'Create'}%>
<%= link_to 'Back', post_comments_path(@post) %>
#-----edit.html.erb
<%= error_messages_for :comment %>
<%= render :partial =>@comment,:locals=>{:button_name=>'update'}%>
<%= link_to 'Show', [@post,@comment] %> |
<%= link_to 'Back', post_comments_path(@post) %>
new和edit视图的修改都很小。直接渲染_comment.html.erb文件产生表单。但请注意,并非使用:partial=>’comment’,而是使用 :partial=>@comment,然后再一次他能够从类名推断出局部模板的名字。还有一点就是路由[@post,@comment]跟post_comment_path(@post,@comment)是等价的。
#-----show.html.erb
Post:
<%=h @comment.post %>
Doc:
<%=h @comment.doc %>
<%=link_to 'Edit',[:edit,@post,@comment]%>
<%= link_to 'Back', post_comments_path(@post) %>
#-----index.html.erb
….
<% for comment in @comments %>
<% end %>
<%= link_to 'New comment', new_post_comment_path(@post) %>
2)posts视图
最后,链接Comments列表页面到Post页面,我需要做:
在/app/views/posts/show.html.erb中添加一行代码:
<%= link_to 'Comments', post_comments_path(@post) %>
<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>…
7. 非空判断
视图初步完成。但是post页面最好还应该显示已经有的comments列表和一个提交新注解的表单,所以我们现在还需要进行一些小小改编。
<% unless @post.comments.empty? %>
<% @post.comments.each do |comment| %>
<%= h comment.body %>
<% end %>
<% end %>
<%= render :partial => @comment = Comment.new,
:locals => { :button_name => 'Create'}%>
<%= link_to 'Comments', post_comments_path(@post) %>
<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>
最后的一点调整:当提交一个新注解之后我们希望回到它的POST页面,这就需要改写下comments_controller.rb中的路由
把app/controllers/comments_controller.rb中的旧路由:
redirect_to(@post, @comment)
替换成新路由:
redirect_to(@post)
四, 网站截图
1)主页posts页面,comments链接在show页面
2)show页面以及new comments的链接
3)comments主页
4)空评论则直接显示增加评论