Part 7 html
-首先咱们从总体的布局文件开始,开始美化以前我发现了一个明显的bug,就是当我点击一片文章显示内容时,再次点击导航栏的“文章列表”或者“关于博主”的时候,都会出现路由错误,缘由是由于我在这些连接里面写的地址都是固定的url地址,而不是路由,因此致使每次访问都会在当前的页面url后加上那个url后缀,而后页面就会由于找不到路径挂掉,好,修改以下: 前端
1.替换'Blog'连接为路由,由 程序员
<a class="navbar-brand" href="/">Blog</a>
改成 shell
<%= link_to 'Blog', root_path, class: 'navbar-brand' %>
2.替换'文章列表'连接为路由,由 数据库
<li class="active"><a href="articles">文章列表</a></li>
改成 安全
<li class="active"><%= link_to '文章列表', articles_path %></li>
3.替换'关于博主'连接为路由,由 ruby
<li><a href="about">关于博主</a></li>改成
<li><%= link_to '关于博主', about_path %></li>这段须要注意的是,<a>标签其实就是等同于link_to这个helper,可是当<a>里面还有CSS样式的时候,须要在最后添加一个class参数,相似class: 'navbar-brand'这样的。
-让咱们来美化文章列表页面views->articles->index.html.erb,根据咱们的要求,显示的应该是一个列表,相似于一个表格,因此咱们的主体就是一个table,但依然是占据着col-sm-8这么宽的区域。因此,最开始的作完以后的代码以下: app
<div class="row"> <div class="col-sm-8"> <table class="table"> <caption>文章列表</caption> <tbody> <% @articles.each do |article| %> <tr> <td><%= link_to article.title, article_path(article) %></td> <td><%= link_to '编辑', edit_article_path(article) %></td> <td><%= link_to '删除', article_path(article), method: :delete %></td> <td><%= article.created_at.to_s(:db) %></td> </tr> <% end %> </tbody> </table> </div> <div class="col-sm-4"> </div> </div>
你们能够看到,其实咱们原来的“写博客”的连接不见了,由于我想把它放到table的右上角,可是没找到好办法,想了下,由于标题<caption>其实也是一行,那就是一个row,那就可使用class=col-sm-6这样的class来控制,因此就改为这样了: 布局
<caption> <div class="row"> <div class="col-sm-6" align="left">文章列表</div> <div class="col-sm-6" align="right"><%= link_to '新博客', new_article_path %></div> </div> </caption>好了,到此articles的index页面初步完成了。
-开始articles部分的new页面,我但愿输入框的大小是不能够拖拽改变的。 测试
那么一样,留出右边的1/3的空白区域,左边为生成文章的区域,因此这个页面的代码能够改为:
<div class="row"> <div class="col-sm-8"> <%= form_for @article, url: articles_path do |f| %> <div class="form_content"> <%= f.label :title, "文章标题" %> <%= f.text_field :title, class: "form-control" %> <%= f.label :content, "文章内容" %> <%= f.text_area :content, class: "form-control", style: "resize:none;", rows: 10 %> </div> <%= f.submit "提交", class: "btn btn-primary" %> <% end %> </div> <div class="col-sm-4"> </div> </div>输入框和文本框的class都是"form-control",文本框默认是能够拖拽放大缩小的,要想保持大小,设置style属性为"resize:none;"便可,关于文本框的高度,设定rows值比较合适
同理,edit页面一样是这样。
-开始about页面。这个页面仅仅就是一个文字段落,相对比较容易。修改完的代码以下:
<div class="row"> <div class="col-sm-8"> <p>博主主要从事的工做是iOS开发,从2011年一次偶然的机会,喜欢上Rails,今后就变成成天想着Rails可是干着iOS的程序员。时至2015年1月9日,实在不容许这样的状况持续下去,并且我热切期待本身能有一个彻底属于本身的博客,因此就开始着这个项目的开发,仅以此记录开发的过程,若有问题,请来信告知。qingfengorlangyue#gmail.com</p> </div> <div class="col-sm-4"> </div> </div>
到此,博主的前端能力有限,心目中预计的第一步骤相关的美化工做结束,接下来就去掉一些冗余的代码,评论功能和页面的持续美化。
Part 8
-首先添加评论功能,因此咱们须要设计一个Comment数据模型,以及一系列关于它的CRUD,除此以外,由于评论和文章是有对应关系的,因此还须要考虑它与article之间的关系。
从产品的角度看,每一个文章都会有0~N条评论,而每条评论都只能属于某一片文章,因此看起来文章和评论之间的关系应该是1对多的关系。目前,以博主相对不成熟的Rails和前端技术,我就暂时设计评论的字段仅包含一个content来表示用户输入的内容,另外由于须要与article模型的联系,须要一个外键,因此总共是2个字段。
1.建立comment数据模型
rails generate model comment name:string article_id:integer在app->models里面就多了一个comment.rb模型文件,而后数据模型和数据库是对应起来的,因此会自动生成一个migrate文件,用户建立数据库表
2.指定与article数据模型的关系
article.rb文件中添加
has_many :comments
comment.rb文件中添加
belongs_to :article
刚发现原来我想要的comment的字段名字命错了,应该是content字段,却写成了name字段,因此在migrate目录下面相应的迁移文件中修改过来便可。接下来生成comment数据表
rake db:migrate好了数据模型肯定了,开始为comment添加CRUD吧。
-建立comment控制器,命令以下:
rails generate controller comments作"CRUD"就又会设计到相应的action,也相对应的会须要template,可是comment是依赖于article的,因此它的路由不能像article那样是一个独立的model路由,它的全部操做都须要先查出它所属的article是谁,而后再操做其它内容,大部分时候,一片文章的内容和它的评论是同时出现的,因此在routes.rb中有关article和comment的部分须要改一下以支持这种关系:
由
resources:articles
改成
resources :articles do resources :comments, controller: 'comments_controller' end-提供建立comment的界面接口
修改views->articles->show.html.erb页面:
<div class="row"> <div class="col-sm-8"> <div class="article_content"> <h3><%= @article.title %></h3> <p><%= @article.content %></p> </div> <hr size="1" noshade="noshade" style="#cccccc dotted;"/> <textarea class="form-control form_content", style="resize:none", rows="5", placeholder="评论"></textarea> <div align="right"> <button class="btn btn-primary">发布评论</button> </div> </div> <div class="col-sm-4"> </div> </div>
从这里咱们看到了进行评论的界面接口,可是你点击“发布”按钮是不会有什么反应的,由于这个按钮还未关联任何事件,从这里开始咱们须要把他看成一个独立的部分进行操做和HTTP请求,因此
1)这里把它改成一个form表单,而不只仅是一个textarea和button;
2)关于form表单,咱们须要注意须要提交的参数对象和字段;
因此关于评论的这部分的代码能够替换为:
<%= form_for [@article, @article.comments.build] do |f| %> <div class="form_content"> <%= f.text_area :content, class: "form-control", style: "resize:none", rows: "5", placeholder: "评论" %> </div> <div align="right"> <%= f.submit "发布评论", class: "btn btn-primary", align: "right" %> </div> <% end %>
这里面要注意的一个地方是
[@article, @article.comments.build]这是这个form须要提交的参数,并且会把这个消息发送到comment控制器的create方法中,但由于comment是依附于文章的,而routes中的代码以及它们之间的has_many和belongs_to关系
resources :articles do # you can use the custom controller name for comment. # eg. resource :comments, controller: article_comment resources :comments end会让comment的route和普通的resource不同,对比以前article的resource获得的对应方法和route:
Article.new Article.create Article.create!comment的resource对应的方法和route:
@article.comments.build @article.comments.create @article.comments.create!因此,这个form须要的内容除了comment对象自己还须要它关连的article对象。
那么相应的,咱们须要在comment控制器中加入create方法来处理comment的建立。接着面临的问题就是建立完评论以后,界面该如何动做?一般还须要呆在当前页面,可是若是有关联的comment的话,则须要显示(多是刚刚建立的)comment。因此article的show页面还须要加入显示comment的部分,这部分能够相似这样:
<% if @article.comments.any? %> <div class="article_content"> <table class="table" rules="groups"> <tbody> <% @article.comments.each do |comment| %> <tr> <td><%= comment.content %></td> <td align="right"><%= comment.created_at.to_s(:db) %></td> </tr> <% end %> </tbody> </table> </div> <hr size="1" noshade="noshade" style="#cccccc dotted;"/> <% end %>
在有comment的状况下再显示这个区域。
在开发过程当中,我调试过程当中常常须要从rails c的console中建立测试数据,也须要删除数据,建立咱们说过了,那么删除的方式相似这样:
# 删除表中全部数据 Comment.delete_all # 删除一条数据 comment = Comment.last comment.delete
好了,到这里咱们就能够正常的针对具体的文章发布评论了。
Part 9
到这里,你们能够看到整个页面咱们一直在作左边的2/3部分,右边的部分没有作过,因此接下来咱们就来设计右边的1/3部分的内容。
-首先更改welcome的index页面,这个页面须要显示全部的评论,并且须要是倒序的,代码以下:
<% @comments.each do |comment| %> <div class="article_content"> <%= link_to comment.content, article_path(comment.article) %> </div> <% end %>
因此,咱们须要在welcome的controller中获取到全部通过倒序排列的comment:
def index @articles = Article.all @comments = Comment.all.reverse_order end
但我发现,除了这个页面,我但愿全部的页面都是在最右边显示这个部分,因此我须要为每一个页面添加以下代码!这样将会很是的繁琐,并且其实失眠不少的网站的页面都是这的布局,那他们也是这么作的吗?其实有一个叫作“局部视图”的技术能够解决这个问题,就是解决复用的问题的。好,让咱们开始使用它吧!
-首先看welcome的index页面,把咱们刚刚加入的那个部分的代码粘贴到一个新的文件里面去,这个文件是app->views->welcome->_comment.html.erb而后把index里面的那段代码替换成
<%= render "comment" %>而后你能够刷新一下看看,构建完代码以后,是一样的效果,好的,那我么就把它加到每一个须要的页面中去吧!
-在article的index页面,去掉原来的
<div class="col-sm-4"> </div>替换为:
<%= render "./welcome/comment" %>
注:由于_comment.html.erb是放在welcome目录中的,而在搜索局部视图的时候,render后面的实际上是一个相对路径,因此这里咱们须要改变一下,把它的路径换成welcome中的路径,不然就会寻找当前目录下的_comment.html.erb文件,而由于找不到就报错了。
-在article的show页面,作一样的修改便可。
-welcome的about页面
-article的new页面
-article的edit页面
作完这些你会发现你须要在几乎每一个对应页面的action中添加一行代码
@comments = Comment.all.reverse_order
这也是一种代码的冗余,rails依然有比较好的作法可让代码优化,咱们可使用before_action来达到这一目的。before_action的意思是你在执行这个指令所包含的全部方法以前都须要之行另一个在这里规定好的方法。
1.修改welcome控制器,在全部方法的最前面添加以下代码:before_action :all_comments, only: [:index, :about]
这意味着在index和about方法执行前,先要执行all_comment方法,这个方法的定义以下:
def all_comments @comments = Comment.all.reverse_order end
其实就是获取了全部的comments,没什么特别的,当没有:only字段来限定的话,是对全部的方法都起做用的
2.一样的修改article控制器,在最前面添加
before_action :all_comments, only: [:index, :show, :edit, :new]
好了,到这里,这是我可以想到的全部的代码优化部分。
Ok,又发现一处能够去掉冗余代码的地方,就是article的new.html.erb 和 edit.html.erb页面中关于form的部分。
在article的目录中新建一个_form.html.erb,把相同的部分
<div class="form_content"> <%= f.label :title, "文章标题" %> <%= f.text_field :title, class: "form-control" %> <%= f.label :content, "文章内容" %> <%= f.text_area :content, class: "form-control", style: "resize:none;", rows: 10 %> </div>
相应的new和edit中相同的代码能够替换为
<%= render partial: "form", locals: { f: f } %>
此次的复用和上次优势不一样,多了一个参数locals,并且前面也多了个叫partial的symbol,这是由于此次咱们须要传递一个参数到局部视图中去,否则局部视图就不知道里面的那个“f”是什么意思了,而一旦须要传递参数,前面就须要添加partial这个symbol来保证参数的形式同样。
好了,接下来的工做就是网站的安全性部分,包括防意外脏数据的插入,字段不为空的检测,格式要求,和最主要的测试部分。之因此把测试放在最后,并非什么所谓的TDD和BDD,是由于咱们初学者须要成果的展现,须要成就感,仅是我的的观点,因此我就这么作。