ruby on rails入门教程之post构建七

1. 重构

现在, 我们博客的文章和评论都可以工作了, 但是如果我们看下 app/views/posts/show.html.erb 模板, 你会发现其代码又长又笨, 还记得Rails的信条么? DRY!(不要做重复的事, Dont Repeat Yourself)

现在我们使用局部模板来清理下这些代码吧.

首先我们制作一个comment模板来显示一条文章下的所有评论. 创建 app/views/comments/_comment.erb :

  1. < p >   
  2.   < b > Commenter: </ b >   
  3.   < %= comment.commenter % >   
  4. </ p >   
  5.    
  6. < p >   
  7.   < b > Comment: </ b >   
  8.   < %= comment.body % >   
  9. </ p >   

然后修改 posts下面的show.html.erb模板:

  1. < p   class = "notice" > < %= notice % > </ p >   
  2.    
  3. < p >   
  4.   < b > Name: </ b >   
  5.   < %= @post.name % >   
  6. </ p >   
  7.    
  8. < p >   
  9.   < b > Title: </ b >   
  10.   < %= @post.title % >   
  11. </ p >   
  12.    
  13. < p >   
  14.   < b > Content: </ b >   
  15.   < %= @post.content % >   
  16. </ p >   
  17.    
  18. < h2 > Comments </ h2 >   
  19. < %= render @post.comments % >   
  20.    
  21. < h2 > Add a comment: </ h2 >   
  22. < %= form_for([@post, @post.comments.build]) do |f| % >   
  23.   < div   class = "field" >   
  24.     < %= f.label :commenter % > < br   />   
  25.     < %= f.text_field :commenter % >   
  26.   </ div >   
  27.   < div   class = "field" >   
  28.     < %= f.label :body % > < br   />   
  29.     < %= f.text_area :body % >   
  30.   </ div >   
  31.   < div   class = "actions" >   
  32.     < %= f.submit % >   
  33.   </ div >   
  34. < % end % >   
  35.    
  36. < br   />   
  37.    
  38. < %= link_to 'Edit Post', edit_post_path(@post) % >  |  
  39. < %= link_to 'Back to Posts', posts_path % >  |  

这将为每条评论渲染 app/views/comments/下面的_comment.erb局部模板, 因为传入 render 方法的参数是一个集合 (<%= render @post.comments %>), rails会自动判断参数是否是集合, 如果是, 将遍历集合同时输出局部模板 (在这里, _comment.erb局部模板的变量名称为 comment, 然后comments集合的每个元素分配给该comment变量)

请想想 form_for [@post, @post.comments.build] 方法生成表单的action为: posts/:id/comment, 那么对于REST路由, 我们在后面将会深入了解.

同样, 我们把创建评论部分也移到局部模板中去, 创建文件 app/views/comments/_form.erb:

  1. < %= form_for([@post, @post.comments.build]) do |f| % >   
  2.   < div   class = "field" >   
  3.     < %= f.label :commenter % >   
  4.     < %= f.text_field :commenter % >   
  5.   </ div >   
  6.   < div   class = "field" >   
  7.     < %= f.label :body % >   
  8.     < %= f.text_area :body % >   
  9.   </ div >   
  10.   < div   class = "actions" >   
  11.     < %= f.submit % >   
  12.   </ div >   
  13. < % end % >   

最后的show.html.erb为这个样子:

  1. < p   class = "notice" > < %= notice % > </ p >   
  2.    
  3. < p >   
  4.   < b > Name: </ b >   
  5.   < %= @post.name % >   
  6. </ p >   
  7.    
  8. < p >   
  9.   < b > Title: </ b >   
  10.   < %= @post.title % >   
  11. </ p >   
  12.    
  13. < p >   
  14.   < b > Content: </ b >   
  15.   < %= @post.content % >   
  16. </ p >   
  17.    
  18. < h2 > Comments </ h2 >   
  19. < %= render @post.comments % >   
  20.    
  21. < h2 > Add a comment: </ h2 >   
  22. < %= render "comments/form" % >   
  23.    
  24. < br   />   
  25.    
  26. < %= link_to 'Edit Post', edit_post_path(@post) % >  |  
  27. < %= link_to 'Back to Posts', posts_path % >  |  

  第二个局部模板就比较简单了, 没有变量的赋值, 仅仅引用了comments下的_form.erb模板, 通过"/", rails知道你渲染的是comments文件夹下的_form模板.

再次说明一点的是: @post 作用于任何该视图下的局部模板, 因为它是一个实例变量.

2. 删除评论

博客中另一个重要特性是可以删除垃圾评论, 要实现该功能, 我们需要在每条评论下建立一个链接, 并实现CommentController下面的destroy动作.

所以首先, 我们先在_comment.erb模板下添加一条删除链接:

  1. < p >   
  2.   < b > Commenter: </ b >   
  3.   < %= comment.commenter % >   
  4. </ p >   
  5.    
  6. < p >   
  7.   < b > Comment: </ b >   
  8.   < %= comment.body % >   
  9. </ p >   
  10.    
  11. < p >   
  12.   < %= link_to 'Destroy Comment', [comment.post, comment],  
  13.                :confirm  = >  'Are you sure?',  
  14.                :method  = >  :delete % >   
  15. </ p >   

同样也请留意下 link_to 生成的url: posts/:id/comments/:id, 以及产生一个delete请求(注意不是get, 想想如果可以通过get来删除数据是不是很糟糕? 一般来说对于查询数据我们使用get请求, 对于操作数据使用post请求, 所以对于一个搜索功能来说, 即使是表单提交, 那么我们也应该把表单的method设为get)

接下来我们实现CommentsController下的destroy方法(怎么会调用该方法? 记住这是一个REST)

  1. def  destroy  
  2.   @post  = Post.find(params[ :post_id ])  
  3.   @comment  =  @post .comments.find(params[ :id ])  
  4.   @comment .destroy  
  5.   redirect_to(post_path(@post ))  
  6. end   

destroy方法首先找到该篇文章, 然后在@post.comments集合内锁定需要删除的评论, 删除之后跳转到该文章地址.

3. 删除关联对象

如果你删除一篇文章, 那么相关的评论也一并删除. 否则评论还将继续留在数据库中占用空间. Rails同样允许你使用依赖选项来激活. 修改Post模型:

  1. class  Post < ActiveRecord::Base  
  2.   validates :name ,   :presence  =>  true   
  3.   validates :title:presence  =>  true ,  
  4.                     :length  => {  :minimum  => 5 }  
  5.   has_many :comments:dependent  =>  :destroy   
  6. end   

:dependent => :destroy 告诉rails当删除一条post时, 相关的comments将调用destroy方法一并删除, 如果设置为 :delete_all 那么关联对象将被删除而不调用 它 们的 destroy 方法, 如果设置为 :nullify, 所有关联对象的外键将被设为 null 而不调用他们的 save 回调; 如果设置为 :restrict 那么该对象在有关联对象存在的时候无法被删除. (注意一点的是 :dependent 在使用 :through 选项时将被忽略)

4. 安全

现在我们要发布博客里, 可以我们发现所有人都可以添加 删除 修改文章和评论.

那么rails提供了一个非常简单的HTTP认证, 那么我们需要在全局控制器内实现它:

app/controllers/application_controller.rb

  1. class  ApplicationController < ActionController::Base  
  2.   protect_from_forgery  
  3.    
  4.   private  
  5.    
  6.   def  authenticate  
  7.     authenticate_or_request_with_http_basic do  |user_name, password|  
  8.       user_name == 'admin'  && password ==  'password'   
  9.     end   
  10.   end   
  11.    
  12. end   

然后我们需要在PostsController阻止未认证用户的一些动作的访问, 那么在这里我们可以使用 before_filter 过滤器. 该方法将在每个动作执行前运行, 除非一些通过 :except 设置的方法:

  1. class  PostsController < ApplicationController  
  2.    
  3.   before_filter :authenticate:except  => [ :index:show ]  
  4.   ...  
  5. end   

同样的, 我们只允许认证用户可以删除评论:

  1. class  CommentsController < ApplicationController  
  2.    
  3.   before_filter :authenticate:only  =>  :destroy   
  4.   ...  
  5. end   

现在如果你创建post, 你将被要求输入用户名和密码.

Good Luck!

 

来自: http://blog.csdn.net/emerald0106/article/details/7078923

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值