好得很程序员自学网
  • 首页
  • 后端语言
    • C#
    • PHP
    • Python
    • java
    • Golang
    • ASP.NET
  • 前端开发
    • Angular
    • react框架
    • LayUi开发
    • javascript
    • HTML与HTML5
    • CSS与CSS3
    • jQuery
    • Bootstrap
    • NodeJS
    • Vue与小程序技术
    • Photoshop
  • 数据库技术
    • MSSQL
    • MYSQL
    • Redis
    • MongoDB
    • Oracle
    • PostgreSQL
    • Sqlite
    • 数据库基础
    • 数据库排错
  • CMS系统
    • HDHCMS
    • WordPress
    • Dedecms
    • PhpCms
    • 帝国CMS
    • ThinkPHP
    • Discuz
    • ZBlog
    • ECSHOP
  • 高手进阶
    • Android技术
    • 正则表达式
    • 数据结构与算法
  • 系统运维
    • Windows
    • apache
    • 服务器排错
    • 网站安全
    • nginx
    • linux系统
    • MacOS
  • 学习教程
    • 前端脚本教程
    • HTML与CSS 教程
    • 脚本语言教程
    • 数据库教程
    • 应用系统教程
  • 新技术
  • 编程导航
    • 区块链
    • IT资讯
    • 设计灵感
    • 建站资源
    • 开发团队
    • 程序社区
    • 图标图库
    • 图形动效
    • IDE环境
    • 在线工具
    • 调试测试
    • Node开发
    • 游戏框架
    • CSS库
    • Jquery插件
    • Js插件
    • Web框架
    • 移动端框架
    • 模块管理
    • 开发社区
    • 在线课堂
    • 框架类库
    • 项目托管
    • 云服务

当前位置:首页>高手进阶
<tfoot draggable='sEl'></tfoot>

will paginate 样式

will paginate 样式

Ragnarok Studio Innovative, Insightful, Intelligent, Intriguing

Site Hots Apples Safari+ Plugins About

Meta Log in Entries RSS Comments RSS WordPress.org

Comments Neo on Jail-broken 4 Sunny on Jail-broken 4 Viva Hu on 经典回顾:魔兽星际完全对应表 Neo on Neophone 4 Sunny on Neophone 4

Cloud

Hide threads  |  Keyboard Shortcuts

Neo 4:02 pm on September 15, 2008 Reply  

MRP Progress II

MRP启动 之后,上次介绍了 Phase I 的完成情况,之后很久都没什么时间去折腾,最多是零零散散的更新几行代码——事实上对于大部分页面来说,也就几行代码就行了——直到开始实现查询部分的功能,这个有点麻烦,这次趁着假期才算是完成了这个部分,于是就有了这个 最初的发布版本 。这一篇就针对这个过程中的一些体会稍作回顾,主要涵盖的是Controller和View的部分。   我是完全意义上的Rails新手,所以这里不会有什么高深的东西,只是希望用一个例子来说进入这样一个新的体系的路径,以及可以得到的收获。

Warning!!! 非常非常的长,没有耐心的现在可以关闭这个页面了。

Step 0 一般性原则

一般来说对于新的技术学习,有一定的规律,虽然可能因人而异,但是下面这些原则是值得考虑的:

寻找一个可完整实现的、具有实际价值,但是又不要过于薄弱(换句话说,使用熟悉的技术可以轻易完成)的案例作为目标,注意控制时间,让它有始有终比什么都重要。 尽最大的可能寻找最一般的实现方案,了解和使用最大众化的技术和机制,学习最原汁原味的风格。 只要可能,就不要自己去实现那些一看就知道有人做过的功能——比如分页,基本上都可以找到高质量、封装的很好的可重用模块。 虽然这个案例有明确的目标和主题,但是在时间许可范围内,不要害怕把其他有趣的东西放进去。

毫无疑问,这次我就是这么干的,MRP是一个非常适合的目标,因为不需要写数据,所以非常简单,但是它对于Rails来说并不平凡,且实际价值明确, 目标 也很清晰适中,不会导致拖得很久完不成。同时,无论是Rails还是MRP都有很多可以延伸的点,例如AJAX,Rails内置了 Prototype / script.aculo.us ,但是我喜欢 jQuery ,借助 jRails 的帮助,我把它们换成了jQuery——所有这些都很有趣!

Step 1 普通表格型数据展现

Controller从Model取得数据,包装成View所需要的形式,然后在View的模版中展现,这是最一般的流程,MRP需要展示的数 据:Category(分类) => Forum(论坛) => Post(主题) => Message(留言),通过4个不同的页面进行展现,同时借助超链接来逐级的钻取下去,这是最简单的部分。先来看看Controller的部分,下面是 app/controllers/categories_controller.rb 的片段:

1
2
3
4
5
6
7
8
9
10
11
12
 class  CategoriesController  <  ApplicationController
   # GET /categories 
   # GET /categories.xml 
   def  index
     @categories  = Category. find  (  :all ,  :conditions   =>   [  "id>1"  ] ,  :order   =>   "creation_date"  ) 
 
    respond_to  do   | format | 
       format . html   # index.html.erb 
       format . xml    {  render  :xml   =>   @categories   } 
     end 
   end 
  ...

先来看看Rails的八股。line 2-3的注释说明这个方法可以用来响应的HTTP请求,用来支持其他文件类型(如XML)的REST请求;line 7-10是生成对应不同格式文档的代码,对于HTML没有特定处理,这按照Rails的约定就会去 app/views/categories/ 目录下找 index.html.erb 这个模板并渲染它作为HTML输出;XML的输出调用Rails的缺省 render 方法进行,输出的XML可以在 这里 看到,如果你用Firefox打开这个链接(这是我现在知道的,除了插件之外Firefox对Safari的最大优势,Safari要展示XML必须使用隐藏的Develop菜单下的console),可以看到非常漂亮的XML输出( Firefox | Safari ),可用于各种非浏览器的客户端。这里你很容易加入你自己的格式,例如:

1
2
3
4
    respond_to  do   | format | 
      ...
       format . text    {  render  :text   =>   "Hi there!"   } 
     end 

format 后面跟的类型必须是标准 MIME 描述名,后面代码块的输出将作为请求这个类型资源 categories.txt 的响应。

整个关键在于line 5,调用Model类的 find 方法来生成一个对象数组,这是Rails框架中连接Model和Controller的环节。ActiveRecord的 find 方法 是一个强大灵活的机制,并通过Ruby优雅的语法展现出来——基本是不解自明的。这里是比较简单的一种形式,提供一个简单的条件,设定排序方式。顺便说一句,开始干活之前以及干活的过程中,应该不断的积累好用的工具箱,这里我推荐 RailsBrain 作为离线的API手册。

然后来看看View的部分,下面是对应模板 categories/index.html.erb 的片段:

1
2
3
4
5
6
7
8
  <tbody>
   <%   for  category  in   @categories   %> 
    <tr>
      <td> <% = link_to category. name , category_forums_path ( category )   %> </td>
      <td> <% = category. description   %> </td>
    </tr>
   <%   end   %> 
  </tbody>

ERB是Ruby标准的HTML template,使用常见的 <% %> 标记体系,所以这个很好懂。值得关注的是line 4,使Rails和之前其他的页面标记语言不大一样的,是大量被称为helper的方法(属于ActiveView包),这些方法使页面元素的管理更加简单,代码更加干净。这里两个需要提到的方法是:

link_to : 生成一个HTML超链接,参数是链接文字和URL;Rails提供大量的helper方法来生成各种HTML标记,包括页面标题、表单、CSS和JS引用等等。 category_forums_path : 这个不是预定义的helper方法,而是Rails框架自动生成的方法,用来通过对象产生REST风格的URL,具体到这个方法,它会生成 “指定category下面所有forums列表” 的URL,具体说明在下面关于RESTful的部分。

Step 2 了解框架的基本结构和机制

Rails的基本结构主要是包括目录结构、命名约定、运行环境和初始化脚本、工具集等内容(下面我们会谈到这些),那么什么称得上是Rails的基 本机制呢?我觉得是RESTful route,这个东西不仅仅是URL和代码之间的映射和连接方案,更是对应用结构的一种指导。REST的概念简单而深邃,这里就不展开了。Rails中使 用 config/routes.rb 文件来向Rails引擎注册对象,经过不断的优化,现在这个文件可以非常简单:

1
2
3
4
5
6
7
8
9
10
  map. search   'search' ,  :controller   =>   'search' ,  :action   =>   'index' 
  map. resources   :messages 
  map. resources   :posts ,  :has_many   =>   :messages 
  map. resources   :forums ,  :has_many   =>   :posts 
  map. resources   :categories ,  :has_many   =>   :forums   # Exactly the same as below 
   #  map.resources :categories do |category| 
   #    category.resources :forums 
   #  end 
 
  map. root   :controller   =>   "categories" 

line 5的写法和line 6-8是等价的,这种 :has_many 的语法是Rails 2.0引入的,不仅更加简洁,也和ActiveRecord的风格更加一致,这定义了一个 1:n 的”nested resource”,即嵌套的资源,这种关系在关系模型中表现为主外键,在对象模型中表现为包含关系(include),在REST中则通过这行代码表现为 /categories/13/forums 这样的URL,这表示forums资源属于某个特定的category资源,非常直观有效的R(elational)-O(bject)-R(esource)映射,不是么?

更进一步,Rails不需要你自己写这样的URL,Rails会自动生成一组helper方法来从对象出发按照约定规则生成正确的URL,这就是在前一节我们看到的类似 category_forums_path 这样的方法,新手经常搞不清这些方法里单数、复数、排列顺序等,不过Rails早就为此准备好了绝妙的工具,进入项目根目录,运行:

rake routes

系统会扫描整个项目,生成所有routes并列出相关的helper方法,下面列出其中的一行( 截图 ):

category_forums GET  / categories / :category_id / forums  { : controller = >  "forums" , : action = >  "index"  } 

第一项是helper方法前缀,后面加上 _path 的方法会输出这个资源的相对于Web根的URL,后面加上 _url 的方法则会输出完整的URL;第二项是HTTP方法,只有GET才有对应的helper方法;第三项是URL模板;最后一项是这个资源的handler,包括对应的Controller和行为方法。

前面的 routes.rb 中line 1&10则是另外一种方式,相对来说比较不RESTful的方式,这个和一般Web框架用来把URL和handler绑定的那些定义文件差不多,其效果在 rake routes 的输出中也可以看到,这个强大的工具基本是排错的利器,如果发现和route有关的问题第一时间去看这个基本就搞定了。

回过头来说说Rails框架的基本结构,关于Rails框架内部的机制,我强烈推荐Obie Fernandez的’ The Rails Way ‘,和那本著名的’ Agile Web Development with Rails ‘相对看,非常互补——这里只针对我的一些体会说几点零散的经验。

Rails的目录结构基本是固定的,很少有人想过去改变它——这是Rails的”convention over configuration”精神的体现,这种相对固定带来一系列方便之处,例如引用CSS样式表的时候,只需要:

1
 <% = stylesheet_link_tag  "pagination"   %> 

后缀名自动补齐,前面的路径也是缺省的 /stylesheet/ 。

在MRP的摸索过程中,多次遇到和版本有关的问题。首先是2.1和2.0的兼容性问题。我自己的电脑上永远有最新的发布版本,所以早就是 2.1.0(前几天到了2.1.1),而很长一段时间DreamHost的服务器上都是2.0.2,这两个版本是不兼容的,当我在本地开发和测试完毕,把 最新的代码commit到SVN服务器上,然后在Web服务器上checkout或者update之后,运行会出错——而DreamHost配置的 Passenger(mod_rails)本来的目标就是drop and run,这形成了绝妙的讽刺——难道我要在本地装个2.0来开发?或者使用 rake rails:freeze:gems 来把本地环境部署到服务器上?这都是我不喜欢的事情,还好经过研究,这个问题还是比较容易解决的,只要修改两个文件,并且这两个文件都是平时不需要修改的:

config/environment.rb 将RAILS_GEM_VERSION改为目标系统的版本(”2.0.2″);注释掉关于 time_zone 的那一行。 config/initializers/new_rails_defaults.rb 把所有的四行内容都注释掉。

Done. DreamHost不久前终于升级了它的缺省Rails配置,现在是2.1.0了,所以这些hacking也就没意义了。

还有一个问题也和DreamHost的共享主机机制有关,也就是安装自己的gems比较麻烦,所以目前我采用的都是把需要的gems放到 vender/plugins 目录下的办法,这个只需要使用下面的命令就可以了:

 cd  vendor / plugin
gem unpack  < gem names > 

Rails 2.1对于plugins和gems的隔离以及管理更简单了,有兴趣的可以看看Ryan Daigle著名的 What’s New in Edge Rails 系列中的 这篇介绍 。

MRP本身用到的plugins和gems很少(关键的就一个,下面会提到的 mislav-will_paginate ,还有一个 jrails ),所以维护还是很简单的。

另外我也对Ruby 1.9做了一些测试,事实证明,只要作一行修改(即去掉 config/boot.rb 中的 load_rubygems 调用,这在Ruby 1.9下是多余的 ),现在的Rails就可以在Ruby 1.9下运行,而问题是其他支持性gems上——其中最核心的是MySQL等数据库驱动,我的测试表明:

mysql 2.7: 经典MySQL驱动,编译本地接口时出错,无法安装。 mysqlplus 0.1.0: 这是 eSpace 最近掀起的 NeverBlock 狂热的一部分,一个使用纤程(fiber)来实现客户端无阻塞通讯的MySQL驱动,这个驱动可以正常的安装,甚至也可以“几乎”正常的运行,但是会导致某些地方显示中文出现乱码,主要是在行尾,估计是双字节的计数问题。 mislav-will_paginate : 可以安装,但是运行出错,其他一些gems也有这类问题(例如我喜爱的 utility_belt )。

我相信通过某种hacking,这些问题都是可以解决的,但是我没时间。

Step 3 分页显示

在Rails 1.2中有一个内置的分页解决方案,但是因为不够灵活以及效率低下而饱受诟病,一些第三方的分页方案于是纷纷应运而生,其中最受追捧、乃至几乎成为“非官方的官方实现”的,是mislav的 will_paginate ,早先经RoR社区著名的 err.the_blog 的介绍推广,随即因其无与伦比的简单和高效而风行。Rails 2.0将早先的内置分页从核心移除,will_paginate于是成为几乎必备的plugin。will_paginate推荐的使用方式是安装为gem:

 sudo  gem  install  mislav-will_paginate

但是在DreamHost虚拟主机上这无法实现,于是我直接把插件代码下到 vender/plugins 下面:

 cd  vender / plugins
git clone git: // github.com / mislav / will_paginate.git

——以后只要在 vender/plugins/will_paginate 目录下运行 git pull 即可。然后在 config/environment.rb 最后加上下面这行就行了:

1
 require   'will_paginate' 

MRP中在主题(posts)列表采用了will_paginate来实现分页——和不分页的版本相比,差别仅仅是几行代码。首先来看 posts_controller.rb 的代码片段:

1
2
3
4
5
6
7
8
 class  PostsController  <  ApplicationController
   # GET /posts 
   # GET /posts.xml 
   def  index
     @forum  = Forum. find  ( params [  :forum_id  ]  ) 
     @category  = Category. find  ( @forum. category_id  ) 
     @posts  =  @forum . posts . paginate   :page   =>  params [  :page  ] ,  :per_page   =>  posts_per_page,  :order   =>   "creation_date" 
    ...

line 5用URL参数 forum_id 作为id查找forums表中对应的行生成全局对象 @forum (将被模板使用的对象实例都应设定为全局的);line 6用 @forum 来查找对应的分类并保存在全局对象 @category 中;line 7首先用 @forum.posts 找出这个论坛下所有的主题,然后调用will_paginate插件注入的 paginate 方法,其中 posts_per_page 是全局方法,返回我设定的缺省每页条数值。对比一下不分页的版本:

1
2
3
    ...
     @posts  =  @forum . posts . find   :all ,  :order   =>   "creation_date" 
    ...

嗯,就是那么回事!再来看模板部分:

1
2
3
4
5
6
7
    ...
    <div class="digg_pagination">
       <% = page_entries_info posts  %> 
       <% = will_paginate posts,  :inner_window   =>   3 ,  :outer_window   =>   2 ,
         :previous_label   =>   'Prev' ,  :next_label   =>   'Next'   %> 
    </div>
    ...

line 3显示分页信息;line 4-5显示分页导航条,参数 inner_window 和 outer_window 控制显示当前页和首/末页临近的多少个链接。你可以在 这里 看到实际的效果( 截图 )。

will_pagination采用URL参数 ?page= 来传递分页信息;事实上URL参数是它会使用的唯一的参数传递方式,如果要分页的结果集是通过条件查询得到的,这些条件也必须通过URL参数来传递,这就决定了对应form的提交方式必须是 GET 而不是 POST ,否则你点击分页链接的时候所有form条件都会丢失——这算一个个小小的catch,不过这是没办法的事情。

Step 4 查询

解决了分页之后,基本上所有MRP对象的REST式访问逻辑很快就搞定了,加上了导航条等必备功能之后,就只剩下查询的功能需要实现了。这个功能的核心是表单的处理,另外因为我希望把查询表单变成主页上一个可动态加载的模块,所以这里也就“顺便”成了AJAX的试验场。

一开始花了比较多的时间来考虑查询的逻辑,经过对功能和实现复杂性的权衡,最后的决定如下:

查询的对象是主题(posts),也就是说一个post中任何一个message符合条件,那么这个post作为符合条件的结果输出,重复的结果记录应该合并。 可以查询的属性包括:标题、作者、所属论坛、发表时间和内容,其中最后一项属于全文检索,暂不实现;标题的查询应该支持某种形式的自定义运算,例如AND、OR之类的,作者和论坛属于限定性条件,指定具体一个值,而发表时间是个起止范围。 为了使结果有意义,标题和作者条件至少必须输入一个,其他属于可选的。

Rails提供了一组helper方法来生成输入表单以及其内的各类field,看看下面的代码片段:

1
2
3
4
5
6
 <%  form_for  :post ,  :url   =>   {   :action   =>   "result"   } ,  :html   =>   {   :method   =>   "get" ,  :class   =>   "cmxform"   }   do   | f |   %> 
   <% = text_field_tag  :subject , params [  :subject  ]   %> <br />
   <% = text_field_tag  :user_name , params [  :user_name  ]   %> <br />
  ...
   <% = submit_tag  "Search"   %> 
 <%   end   %> 

line 1生成 form 标签,并指明提交的目标动作是当前Controller的 result 方法, :html 参数用来直接添加HTML标签属性,例如指明使用 GET 方法,而不是 POST (参见上面关于分页的说明)。第一个参数 :post 只有当这个form是和一个Model类关联的时候才有用,这里实际上是不发生效果的。

line 2&3生成两个文本输入框,参数指定了它们的名字和缺省值如 params[:subject] ;line 5生成提交按钮,参数是按钮文本。上面的代码会生成这样的HTML:

1
2
3
4
5
6
<form action="/search/result" class="cmxform" method="get">
  <input id="subject" name="subject" type="text" /><br />
  <input id="user_name" name="user_name" type="text" /><br />
  ...
  <input name="commit" type="submit" value="Search" />
</form>

日期的输入呢?这个:

1
  <%= select_date(Time.now, :prefix => "start_date") %>

Rails会生成年、月、日的下拉列表框,很遗憾,到目前为止,这还是跨平台兼容性最好的方案,这里没有 :name 参数,只有一个 :prefix 参数,而我们在后台要用 params[:start_date][:year] 这样的语法来访问输入值。我在这里用了个小trick,我把起始日期设为当日,而结束时间设为当日的后一天,这样如果后台收到的结束日期比当日晚就无视这个条件。

如此这般,所以这一端的事情很简单——我们来试试复杂一点的,那个选择论坛的列表,为了加点难度,让我们想办法用categories来做group——其实这也没啥,因为对于Rails来说,都是几行代码:

1
2
3
4
<select name="forum_id" id="forum_id">
  <option value="0" selected="selected">All</option>
   <% = option_groups_from_collection_for_select ( @categories,  :forums ,  :name ,  :id ,  :name  )   %> 
</select>

出来的效果可以在 这里 看到(截图: Firefox | Safari ),哈!那几个参数稍微需要解释下:第1个是分组用的对象集合(数组),这里是所有的分类(全局变量 @categories 需要在Controller中准备好);第2个是这个数组中的每个对象用来取得子元素集合(这里是论坛数组)的方法名—— category.forums 可以取出一个category下的所有forums,在 Part 1 我们看到了,不是么?第3个是取分组名的方法名;第4和第5个是子元素取id和名字的方法名——看出来了吧,其实这个魔术很简单,动态语言的power嘛。

前台就这么多了,后台的处理有几个问题要解决。首先是不同类型的输入数据的处理,然后是怎么处理条件——因为不是每个条件都一定在那儿,需要动态的判断和组合有输入的那些条件,而忽略掉其他的,这个有很经典的解决方案——下面就是这里展示的最长的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
   def  result
    subject = params [  :subject  ] 
    user_name = params [  :user_name  ] 
    forum_id = params [  :forum_id  ] 
    start_date =  Time . mktime  ( params [  :start_date  ]  [  :year  ] , params [  :start_date  ]  [  :month  ] , params [  :start_date  ]  [  :day  ]  ) 
    end_date =  Time . mktime  ( params [  :end_date  ]  [  :year  ] , params [  :end_date  ]  [  :month  ] , params [  :end_date  ]  [  :day  ]  ) 
 
    cond =  [  ] 
     if  subject  and   not  subject. empty ?
      cond  <<   "subject regexp :subject"     # MySQL only 
     end 
 
     if  user_name  and   not  user_name. empty ?
      user = User. find  (  :all ,  :conditions   =>   [  "user_name = ?" , user_name ] ,  :order   =>   "id"  ) . first 
      params [  :user_id  ]  = user. id 
      cond  <<   "user_id = :user_id" 
     end 
 
     if  forum_id  and   not  forum_id. empty ?  and  forum_id. to_i   >   0 
      params [  :forum_id  ]  = forum_id. to_i 
      cond  <<   "forum_id = :forum_id" 
     end 
 
     if  end_date  and  end_date  <   Time . now 
      params [  :start_date  ]  = make_db_time ( start_date ) 
      params [  :end_date  ]  = make_db_time ( end_date ) 
      cond  <<   "creation_date between :start_date and :end_date" 
     end 
 
    messages = Message. find  (  :all ,  :select   =>   "distinct post_id" , 
       :conditions   =>   [ cond. join  (  " and "  ) , params ]  ) . collect   {   | m |  m. post_id   } 
 
     @results  = Post. find  (  :all ,  :conditions   =>   [  "id in (?)" , messages ] ,  :order   =>   "creation_date" 
       ) . paginate   :page   =>  params [  :page  ] ,  :per_page   =>  posts_per_page
   end 

首先初始化一个数组,如果某个条件是有效的那么就把对应的SQL判断语句放进这个数组,Rails的 find 方法接受的查询条件中可以使用参数,既可以用用匿名参数(用 ? 来占位),也可以用命名参数,用 :subject 这样的symbol来标记,然后把参数值放到一个哈希表里一起送进 find 方法就可以了。这里我用了另外一个trick,因为大部分参数其实已经在一个哈希表了,那就是保存HTML参数的 params ,所以我们的参数名就跟着 params 里面的键值,处理后的参数也写入 params ,这样可以省去另外构造一个查询参数值哈希表的代码和开销。

每组条件都测试完毕之后,我们用Ruby数组那漂亮的 join 方法,用 ' and ' 把 条件串起来,在line 30-31送进 Message 类的 find 方法的 :conditions 参数里,然后我们用 collect 方法来把结果集转换成一个整数数组,里面是查出来的所有message的post_id,好用在下一个查询里,那个查询把这些post_id对应的post对象找出来,排序,然后分页——

另外几个小的说明:

最后我决定不去费精力处理标题查询的组合,而是直接使用正则表达式,这使得这个部分变成MySQL only的,但是我觉得这个值得。 使用一个简单的查询从输入的用户名取得用户id。 从 params 取出的 forum_id 是字符串,所以需要转换成整数才好直接应用在SQL查询参数表中。 make_db_time 是定义在 /controllers/application.rb 中的全局工具方法,使用 Progress I 里提到的算法来生成数据库里需要的时间串。

That’s all.

Step X1 用户体验

这个问题和下面的问题都属于贯穿始终的共性问题,所以我用’X'来标记。

对于Web应用,尤其是Rails这么具有 N.0 (N>=2) 时代气息的技术,用户体验是很重要的的一环。对于我来说,至少应该努力做到:

尽量使用标准化的技术产生符合W3C标准的HTML。 使用CSS来隔离样式和内容,也使得改变样式变得简单,MRP的表格、分页导航条、输入表单都使用标准的CSS来定义显示样式,从而是高度可定制的。 必要时可以使用AJAX技术来增加可用性,作为尝试,可以试试在查询表单空着所有格子直接提交,这里有使用jQuery编写的校研和反馈 代码;查询表单在站点主页上还可以动态的加载,点击Search链接之后通过AJAX技术将查询页面读取并注入到主页分类列表的下面。BTW, jQuery的文档 写的很好,很容易看明白,有空可以多玩玩。

具体内容因为和主旨关系不大,就不多说了,有兴趣的可以去看源码。

Step X2 DRY

DRY=Don’t Repeat Yourself,这是Rails的重要哲学,其实按照我的理解,这个不过是对于一致性和复用性的一种感性的强调(不仅仅针对代码本身,对于开发的big picture都适用)。我的骨子里是非常’DRY’的,所以我很喜欢Rails!

Rails中有很多内建的机制来帮助你变得更DRY,例如全局和局部helper类、layout等,但是其中最重要的,莫过于partial了。 partial是可重用的页面块,一般用下划线开头的文件名就是partial,凡是多次出现的长的差不多的页面结构,应该都可以考虑将之转化为 partial,然后在需要的地方用Rails标准的 render 方法来引用:

1
2
 <% = render  :partial   =>   "shared/post_list" , 
            :locals   =>   {   :posts   =>   @results ,  :show_forum   =>   true ,  :is_search_result   =>   true   }   %> 

可以看到,partial是可以接受参数的, :locals 参数给partial中的局部变量赋值,这给与了partial非常好的封装性和灵活性。MRP的主题列表就是一个可重用的partial,当它用在某个 forum的主题列表时,它有4栏,而作为查询结果显示时,则增加了”In Forum”一栏,这就是通过参数实现的。

可重用的页面模块并不新鲜,但是Rails的partial设计的精巧使它真正成为一个好用的、能够经常使用的工具。

 

Reply Cancel reply

Required fields are marked *

Name *

Email *

Website

← MRP 0.1 Released

Chinese Full-text Searching →

Proudly powered by WordPress. P2 theme by Automattic .

c compose new post j next post/next comment k previous post/previous comment r reply e edit o show/hide comments t go to top l go to login h show/hide help esc cancel

loading

查看更多关于will paginate 样式的详细内容...

声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did43601

更新时间:2022-09-24   阅读:36次

上一篇: activerecord查询语法for rails3

下一篇:发现星期六日的电视比较好看

相关资讯

最新资料更新

  • 1.文心一言 VS 讯飞星火 VS chatgpt (79)-- 算法导论7.4 4题
  • 2.【LeetCode字符串#06】KMP巩固练习:重复子串
  • 3.《算法导论》笔记 第8章 8.3基数排序
  • 4.文心一言 VS 讯飞星火 VS chatgpt (92)-- 算法导论8.3 5题
  • 5.1159: 零起点学算法66——反话连篇
  • 6.AES算法
  • 7.二分查找 (四种写法)
  • 8.Java中常见的查找算法与排序算法总结
  • 9.HOG算法基础
  • 10.《落实算法安全主体责任基本情况》范文,修改主体即可提交4
  • 11.解读未知:文本识别算法的突破与实际应用
  • 12.快速指数算法
  • 13.算法学习笔记(18): 平衡树(一)
  • 14.Java数据结构之选择排序算法的实现与优化
  • 15.算法总结--动态规划
  • 16.大牛,求一个最值,你能提出什么好的算法么
  • 17.【LeetCode回溯算法#07】子集问题I+II,巩固解题模板并详解回溯算法中的去重问题
  • 18.代码随想录算法训练营第二十五天| 216.组合总和III 17.电话号码的字母组合
  • 19.【算法数据结构专题】[延时队列算法]史上手把手教你针对层级时间轮(TimingWheel)实现延时队
  • 20.Quine-McCluskey两级逻辑化简算法原理解析

CopyRight:2016-2025好得很程序员自学网 备案ICP:湘ICP备09009000号-16 http://www.haodehen.cn
本站资讯不构成任何建议,仅限于个人分享,参考须谨慎!
本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。
本网站刊载的所有内容(包括但不仅限文字、图片、LOGO、音频、视频、软件、程序等)版权归原作者所有。任何单位或个人认为本网站中的内容可能涉嫌侵犯其知识产权或存在不实内容时,请及时通知本站,予以删除。

网站内容来源于网络分享,如有侵权发邮箱到:kenbest@126.com,收到邮件我们会即时下线处理。
网站框架支持:HDHCMS   51LA统计 百度统计
Copyright © 2018-2025 「好得很程序员自学网」
[ SiteMap ]