首页 > Web开发, 动态语言, 挨踢(IT) > 《Agile Web Development with Rails》抄书笔记(06):美化商品列表

《Agile Web Development with Rails》抄书笔记(06):美化商品列表

2013年4月24日 发表评论 阅读评论 1,099 人阅读    

《Agile Web Development with Rails》抄书笔记系列

  “《Agile Web Development with Rails》抄书笔记系列”目录

  在看了产品相关的应用后,我们的客户有一个要求(客户似乎总有提不完的要求。对吧?):商品列表太丑了。提议我们进行美化,看能否将商品图片一起展示出来?

  这让我们有点进退维谷。作为开发人员,我们职业性地深吸一口气,带着不置可否的摇头,低声问道”你想要什么?”同时,我们也想想炫耀一下,Rails可以轻松应付这些变化。我们打开我们信赖的编辑器。

  在我们进行更深入的开发之前,最好使用一组测试来确保应用的可行性。我们可以使用自动生成的套件,在浏览器表单中输入数据等。如果我们这样做,未来工作在同一个代码库上的程序猿也必须这样做。如果我们作为一个项目组的一个成员,同时参与一个项目,那么每位成员都不得不输入自己的数据。如果我们可以以一种可控的方式将数据加载到数据库中,这将是非常完美的。事实证明,我们可以这么干。Rails提供了导入种子数据(seed data)的能力。

  首先,我需要简单修改一下在db目录下的种子数据文件,seeds.rb。

  下面让让我们添加一些代码,来完成向产品表中添加数据的工作。这就需要使用Product的create()方法了。下面就是想要的文件。不需要手动输入,你可以直接拷贝走或者下载我托管到Github上的源代码。

  相关图片,你需要拷贝到你应用的%depot%/app/assets/image/目录下。注意:这个seeds.rb脚本文件会删除products表中已有的数据。也许,你不想让其删除你自己耗费数小时,辛辛苦苦一点点输入的数据。

D呱呱

  D瓜哥将这个应用的源代码都托管到了Github上。下载链接如下:完整项目的代码,https://github.com/diguage/depot;另外,针对本节的代码:开始之前,https://github.com/diguage/depot/tree/v-06.1;本节完成后,https://github.com/diguage/depot/tree/v-06.2

  刚刚检查一下D瓜哥项目中的种子文件内容,由于D瓜哥的失误,这个种子文件没有添加进去相应的内容,请大家到本书作者提供的网站上下载,网站:http://media.pragprog.com/titles/rails4/code/rails32/depot_a/db/seeds.rb


# encoding: utf-8
Product.delete_all
Product.create(title: 'CoffeeScript',
  description: 
    %{<p>
        CoffeeScript is JavaScript done right. It provides all of JavaScript's
        functionality wrapped in a cleaner, more succinct syntax. In the first
        book on this exciting new language, CoffeeScript guru Trevor Burnham
        shows you how to hold onto all the power and flexibility of JavaScript
        while writing clearer, cleaner, and safer code.
      </p>},
  image_url:   'cs.jpg',    
  price: 36.00)
# . . .
Product.create(title: 'Programming Ruby 1.9',
  description:
    %{<p>
        Ruby is the fastest growing and most exciting dynamic language
        out there. If you need to get working programs delivered fast,
        you should add Ruby to your toolbox.
      </p>},
  image_url: 'ruby.jpg',
  price: 49.95)
# . . .

Product.create(title: 'Rails Test Prescriptions',
  description: 
    %{<p>
        <em>Rails Test Prescriptions</em> is a comprehensive guide to testing
        Rails applications, covering Test-Driven Development from both a
        theoretical perspective (why to test) and from a practical perspective
        (how to test effectively). It covers the core Rails testing tools and
        procedures for Rails 2 and Rails 3, and introduces popular add-ons,
        including Cucumber, Shoulda, Machinist, Mocha, and Rcov.
      </p>},
  image_url: 'rtp.jpg',
  price: 34.95)

  (你可以已经注意到,这里使用了%{…}。这是定义字符串的又一种语法,和双引号功能相同,在遇到长语句或者需要换号的时候使用很方便。另外还需要注意,因为使用了Rails的create()方法,如果因为验证失败而导致不能插入数据时,该方法会”悄无声息”地失败掉。)

  执行如下命令,将测试数据插入到products表中:

depot> rake db:seed

  现在,让我们来收拾一下商品列表展示。这里有两步要走,以定义一组样式规则,二通过向HTML标签添加class属性,让样式在相应的页面生效。

  我们需要一个地方来放置我们的样式定义。正如之前你使用的Rails那样,按照惯例,generate scaffold命令已经在幕后生成相关的文件。我们只需要将样式添加到空样式文件products.css.scss中即可,这个文件在%depot%/app/assets/stylesheets/目录下。

D呱呱

  这里定义样式使用的是Sass。Sass是程序化的CSS。使用教程:“Sass使用介绍”;官方教程:“入门教程(英文)”

// Place all the styles related to the Products controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

.products {
  table {
    border-collapse: collapse;
  }
  
  table tr td {
    padding: 5px;
    vertical-align: top;
  }
  
  .list_image {
    width: 60px;
    height: 70px;
  }
  
  .list_description {
    width: 60%;
    
    dl {
      margin: 0;
    }
    
    dt {
      color: #244;
      font-weight: bold;
      font-size: larger;
    }
    
    dd {
      margin: 0;
    }
  }
  
  .list_actions {
    font-size: x-small;
    text-align: right;
    padding-left: 1em;
  }
  
  .list_line_even {
    background: #e0f8f8;
  }
  
  .list_line_odd {
    background: #f8b0f8;
  }
}

  仔细看这个样式定义文件,你会发现CSS规则是嵌套的,针对dl定义的规则在.list_description规则的里面,它本身就是定义在产品规则里面的。这可以减少规则重复出现的可能性,更加容易阅读、编写、理解以及维护。

  这点,你应该熟悉以.erb结尾的文件,它们会预处理嵌在其中的Ruby表达式和语句。如果你注意到这个文件是以scss结尾的,你也许会猜到这个文件是Sassy CSS,处理后可以生产css文件。

D呱呱

  这里,D瓜哥要着重指出,书中并没有提如果处理这个文件。但是,如果你不处理,样式根本无法生效。在以前的版本中,是个CSS文件,虽然使用方式不妥,但是你拷贝到%depot%/public/assets/目录下,也能生效。但是,现在Sass,必须经过处理才能生效。那么该如何处理呢?其实,很简单,只需要一条命令即可:

rake assets:precompile

  编译之后,会在%depot%/public/assets/目录下生成相应的CSS文件,同时图片也会自动拷贝到这个目录下。

  D瓜哥在“《Agile Web Development with Rails》抄书笔记(02):Rails之初体验”中给出了部分命令。但是,这个命令不够全面。再给大家一个全面的:“Rails命令”

  同样,就像ERb文件,SCSS不访问编写正确的CSS。SCSS提供了一种额外的语法,可以让样式文件更加容易编写和维护。你所写的所有的SCSS都可以转化成浏览器可以处理的标准的CSS。

  最后,我们还需要定义一下商品的class属性。如果你在刚刚创建的.html.erb文件中查找,那么你找不到任何引用样式文件的地方。你甚至找不到标签。取而代之的是,Rails单独创建了一个用于整个应用的标准页面,这个文件被命名为application.html.erb,可以控制网页的整体布局,文件在%depot%/app/views/layouts/目录下。修改文件的代码如下:

<!DOCTYPE html>
<html>
<head>
  <title>Depot</title>
  <%= stylesheet_link_tag "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
</head>
<body class="<%= controller.controller_name %>">

<%= yield %>

</body>
</html>

  因为Rails会加载所有的样式文件,所以我们需要建立一个约定,想限制一个样式文件只针对相应的Controller页面生效。使用Controller名称作为class属性的名称是一个简单实现方法。上面的代码修改正是完成这个工作。

  现在,我们拥有了所需的样式文件,我们还修改模板,来自定义展示效果。编辑在%depot%/app/views/products/目录下的index.html.erb文件,删除默认生成的视图代码,将其修改成如下代码:

<h1>Listing products</h1>

<table>
<% @products.each do |product| %>
  <tr class="<%= cycle('list_line_odd', 'list_line_even') %>">
<td>
<%= image_tag(product.image_url, class: 'list_image') %>
    </td>
    
<td class="list_desctiption">
<dl>
<dt><%= product.title %></dt>
<dd><%= truncate(strip_tags(product.description), length: 80) %></dd>
</dl>
</td>
<td class="list_action">
<%= link_to 'Show', product %><br />
      <%= link_to 'Edit', edit_product_path(product) %><br />
<%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %>
    </td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Product', new_product_path %>

  虽然这个模板很简单,但是它还是使用了一些Rails内建的特性:

  • 列表中的行背景色交替显示。Rails的辅助方法cycle()来设置每列的CSS class属性,list_line_even或者list_line_odd,而且会在相邻两行之间交替出现。
  • truncate()辅助方法用于展示商品描述的前八十个字符。在调用truncate()方法之前,调用strip_tags()可以将描述中的HTML标签删除掉。
  • 注意看”link_to ‘Destroy’”那行,看看为啥有参数”confirm:’Areyou sure?’”。如果你点击这个链接,Rails会让你浏览器弹出来一个对话框,来询问你是否确认删除商品。(下面我们会专门说明一下弹出框)

method: :delete是何须玩意?

  你也许注意到了生成了的Destroy链接包含一个参数method::delete。这个决定调用ProductsController 中的哪个方法,同时影响HTTP的方法。

  浏览器使用HTTP和服务器进行交流。HTTP协议定义了一组可以让浏览器采用的动词(一般说成HTTP方法),同时协议规定了使用时机。举例说明一下,一个常规的超链接,使用HTTP的Get请求。Get请求被定义用来获取数据,它不应该产生其他的影响。显式声明使用这个参数,是说明这个链接使用HTTP的DELETE方法。Rails使用这个信息来决定应该将这个请求路由给Controller中的那个action方法。

  注意,当在浏览器中使用时,Rails会使用POST HTTP方法代替PUT和DELETE方法,并添加一个额外的参数,这样Router就能确定最初是使用哪个方法了。无论使用哪个方式,这个请求都不会被Web爬虫缓存或爬取。

  我们向数据库中添加了一些测试数据,我还重写了展示商品列表的index.html.erb文件,我们还填充了products.css.scss文件中的样式,同时样式也会通过布局文件application.html.erb加载到我们的页面。现在,启动服务器,打开浏览器,输入http://localhost:3000/products,商品列表美好后的结果是否如下显示的这样呢?

Listing Products

  我们将我们的成果展示给客户,她很满意。

  上一节内容和本节内容是本书的第五章,一个迭代。这两节,我们完成了网店的后台开发。具体如下:

  • 我们创建了开发库;
  • 我们使用迁移脚本创建并修改了数据库;
  • 我们创建了products表,同时使用生成器创建了一个应用来维护表中的数据;
  • 我们更新了一个应用级别的布局,将页面展示对应到相应Controller视图,方便展示商品列表;

  下一步,我们该创建网店的前台页面了。



作 者: D瓜哥,https://www.diguage.com/
原文链接:https://wordpress.diguage.com/archives/12.html
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

  1. railsnew
    2013年5月28日14:15 | #1

    按照步骤做了,可是样式表还是不生效啊!

    • D瓜哥
      2013年5月30日22:43 | #2

      我给你发邮件了,有我的联系方式,直接加我好友,给我留言吧。哈哈

  2. miss
    2014年3月21日11:38 | #3

    楼主是个大好人!好人一生平安!

  3. 2014年3月21日22:56 | #4

    样式表没生效。

  1. 2013年5月24日17:04 | #1