锁定老帖子 主题:利用rails轻松建立个性化主页门户
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-07-04
简单来说,个性化主页就是结合了各种小模块和网络信息的个人主页。与传统网站的区别是:用户可以非常自由地控制其内容(通过RSS,email等等),内容会更适合用户口味并且使用查看也非常方便,由于有了ajax技术,所以更像是一个桌面软件。例如http://www.netvibes.com/就提供了比较酷的个性化主页服务。 1 页面中的内容是一个个小模块,其内容来自于其他站点或者服务 2 用户可以根据自己的喜好通过拖拽随意摆放这些小模块 3 用户可以添加自己感兴趣的小模块 4 用户可以删除任意已添加的小模块 5 用户可以改变自己的页面风格以及布局。 用rails解决这些问题显得极为简洁,为了简化说明,这里不考虑用户权限,如下:
1 在主应用(也就是提供主页服务的系统)建立模块加载机制和代理转发功能(依据dlee翻译的《ajax模式与最佳实践》最后一章的MVC模式),在这里简化下就是一个user有N个page,一个page有N列,一列有N个模块。建立模型如下: class User < ActiveRecord::Base has_many :pages end class Page < ActiveRecord::Base has_many :columns belongs_to :user end class Column < ActiveRecord::Base has_many :cells belongs_to :page end class Cell < ActiveRecord::Base belongs_to :column end #在后台发起向其他系统调用服务,当然可以带有一些查询参数比如username已取得和该用户相关的模块内容。 def show @cell = Cell.find params[:id] Net::HTTP.start(@cell.url,@cell.port) do |http| response = http.get('#{@cell.path}', 'Accept' => 'text/xml') end render :text => @response.body end #其他系统处理请求并返回,返回结果可以是html/xml/rss/flash/js等等,这里暂用字符串文本代替。 def show render :text => "ok" end 其中需要说明的是:cells表中应存有name、来源URl、port、path,name表示改模块的名字,URl的作用是记录该cell的内容来自于哪个外部站点的rest服务,port指定外部站点的端口,path指定服务的路径。
2 利用rails内置的ajax功能处理拖拽,代码如下: #为简明起见,取id为1的 page,当然也可以根据user来取page def index @page = Page.find 1 @columns = @page.columns end
<%= javascript_include_tag :defaults %> <table id="table_<%= @page.id %>" align="center"> <tr id="tr_<%= @page.id %>"> <% for column in @page.columns %> <td id="td_<%= column.id %>" style="height:auto;word-break:break-all;vertical-align:top;"> <% for cell in column.cells %> <div id="cell_<%= cell.id %>" class="cell"> 正在载入…… </div> <% end %> </td> <% end %> </tr> </table> <% for column in @page.columns %> <%= sortable_element "td_#{column.id}", :url => { :action => "sort" , :column_id => column.id } , :dropOnEmpty => true , :tag => "div" , :containment => [ #一个页面最多可以支持4列,总之把page的所有column设置为拖拽容器即可。 "td_#{@page.columns[0].id}" , "td_#{@page.columns[1].id}" , "td_#{@page.columns[2].id}" , "td_#{@page.columns[3].id}" ] , :constraint => false %> <% end %> <% end %> 异步地为每个小模块加载内容
<script> window.onload = function(){ <% for column in @page.columns %> <% for cell in column.cells %> new Ajax.Updater('cell_<%= cell.id %>', '/Cell/show/<%= cell.id %>', {asynchronous:true,evalScripts:true,method:'get'}); <% end %> <% end %> } <script>
后台处理排序 def sort @column = Column.find params[:column_id] td_index = "td_" + @column.id.to_s list = params[td_index] list.each_with_index { |id,idx| cell = Cell.find id cell.column = @column cell.row_index = idx.to_i cell.save } end
3 向页面添加模块,这里默认向页面的第一列添加,添加模块的div可以做成弹出的浮动div形式。 <div> <% for cell in @cells %> <%= link_to_remote cell.name , :update => "td_#{@page.columns[0].id}" , :mothod => :get , :url => {:action => "add_cell" , :page_id => @page.id , :id => cell.id} ,:position => "top" %> <% end %> </div> 后台代码如下: def add_Cell @page = Page.find params[:page_id] #获取该页面的第一列,column_index表示改列的列标 @column = Column.find :first , :conditions => ["page_id=? and column_index=?" , @page.id , 1] @cell = Cell.find params[:id] @cell.column = @column @cell.row_index = 0#row_index 表示该模块在一列中的位置 @cell.save end
4 删除模块 #在这里简单的删除该cell记录,前台直接隐藏该cell的div再向后台发送ajax请求。 def delete_cell Cell.delete params[:id] end
5 关于设置主题和列数,这个用ajax实现比较容易也比较常见,在此不做解释了。
6 这里仅提供了一个思路,很多地方可以完善和扩展,比如在现实中column和cell应为多对多的关系,这里简化为一对多,这个方案已经过简单的扩展和测试,效果还不错。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 5970 次