`
topgun107
  • 浏览: 5623 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

ROR with AJAX support

阅读更多

ROR with AJAX support

 

 

         Ruby on Rails AJAX这两个炙手可热的应用,相信大家都已经不再陌生。前者完全遵循MVC、约定优于配置等思想给开发人员带来了无与伦比的生产率;后者则是RIA(Rich Internet Application)的代表技术之一。

最近笔者就如何在ROR项目当中使用AJAX来增强用户体验,尤其是如何将一些成熟的AJAX框架融入ROR当中,做了一些尝试和总结。下面分别介绍一下Prototype, script.aculo.us,EXTStreamlineRails框架中的应用(欢迎和我探讨交流,偶在西安一家软件公司供职。MSN:josephzy@hotmail.com)

 

一.    Prototype

prototype.js是由Sam Stephenson写的一个javascript类库,Rails框架中得到了内在的支持。prototype.js文件默认是在public/javascripts目录下。在Rails应用中使用Prototype的步骤如下:

rhtml页面中导入prototype.js

<%= javascript_include_tag :defaults %>

或者

<%= javascript_include_tag :prototype%>

要将 Ajax 添加到这个应用程序中,需要以下几个步骤:

1.      配置 Rails 以使用 JavaScript

2.      更改链接来提交 JavaScript Ajax 请求,而不是仅呈现一个 HTML 链接。

3.      指定要更新的 HTML 片断。

4.      为更新的 HTML 内容准备一个位置。

5.      构建一个控制器方法,或者一个视图来呈现 Ajax 响应。

具体的例子大家可以参考Bruce Tate的跨越边界系列和<<Ajax on Rails>>

二.script.aculo.us

script.aculo.us(http://script.aculo.us)是另一个提供对Rails框架直接支持的javascript类库。它的安装和使用也很简单,从script.aculo.us的下载页面取得以下的几个js文件:prototype.js, scriptaculous.js, builder.js, effects.js, dragdrop.js, slider.js controls.js,同样放在public/javascripts目录下。在header中加入

<%= javascript_include_tag : prototype%>

<%= javascript_include_tag : scriptaculous %>

默认情况下,scriptaculous.js会加载该类库所有的特性。如果你在项目中并不需要多余的特性,可以在引用的时候加以限制

<script src="scriptaculous.js?load=effects,dragdrop" type="text/javascript"></script>

这就是说,仅选用builder effects dragdrop controls slider 中的两个特性。

     为节省篇幅,举一个简单的UI component通过拖拽排序的简单例子

Rhtml页面:

<ul id="list">

  <% 6.times do |i| -%>

  <li id="item_<%= i+1 %>" class="expand_ticket_box">Number <%= i+1 %></li>

  <% end -%>

</ul>

<p id="list-info"></p>

<%= sortable_element 'list',

      : update => 'list-info', 

      : complete => visual_effect(:highlight, 'list'),

      :url => { :action => "order" } %>

Action

def order

    @order = params[:list]

    render :partial => 'list'

end

 

_list.rhtml:

Updated order is:<%= @order.join(', ') %>.

 

在实际的应用中,我们可以把6.times 替换成实际的DB数据。

 

1 排序前

  2 鼠标拖拽排序

.EXT

EXT(http://extjs.com)也许是目前功能最强大,最流行的javascript框架。将EXT用于ROR,的确是一件很cool的应用。

本例是一个在可排序的表格中显示上映影片的例子,其中使用了JSON来传递数据到浏览器。

在需要显示的页面页面中,我们除了导入必要的CSS以外,还必需导入prototype.js, scriptaculous.js, effects.js, ext-prototype-adapter.js, and ext-all-debug.js。我们将以上这些必须的js文件放在public/javascripts/ext目录下。

application.rhtml页面的head中加入如下代码:

<%= stylesheet_link_tag "../javascripts/ext/resources/css/ext-all.css" %>

        <%= javascript_include_tag "ext/adapter/prototype/prototype.js" %>

        <%= javascript_include_tag "ext/adapter/prototype/scriptaculous.js" %>

        <%= javascript_include_tag "ext/adapter/prototype/effects.js" %>

        <%= javascript_include_tag "ext/adapter/prototype/ext-prototype-adapter.js" %>

        <%= javascript_include_tag "ext/ext-all-debug.js" %>

在视图模板list.rhtml中,我们创建一个Div,用来显示将要生成的表格。我们给该Div赋一个id 'movies_grid' 。这个id将会在随后的js代码中使用,以初始化表格信息。

视图模板 (list.rhtml)

 

<%= javascript_include_tag "grid-paging.js" %>

<div id="movies_grid" style="border:5px solid #99bbe8; overflow:hidden; width:650px;"></div>

      

接下来,我们需要编写一些javascript代码来初始化并显示Ext表格。首先创建一个js文件grid-paging.js,在其中持有将在页面显示的数据。通过调用Ext.onReady方法,表格会在页面加载的时候初始化。先创建一个Ext.data.Store对象作为client端的 data store。在这个对象中,再创建一个Ext.data.HttpProxy通知表格从什么地方取得数据。同时,制定一个JsonReader来读取数据。最后,把remoteSort设置为true,以通知store排序会在server端进行,每次当任意一个column header被点击,一个新的数据请求就会被发往server处理。

       store对象被创建后,接下来需要创建Ext.grid.ColumnMmodel对象以制定如何对表格进行布局处理。之后,设置ColumnModel的属性defaultSortabletrue,这样每一次点击任意一个column header后都会进行排序操作。

       最后,我们以之前创建的StoreColumnModel对象为参数,创建Ext.grid.Grid对象。接下来就是调用Store对象的load方法显示表格。

       其代码如下:

JavaScript Code (grid-paging.js)

 

 

var grid;

var ds;

分享到:
评论
1 楼 topgun107 2008-04-25  
var grid;
var ds;

Ext.onReady(function(){
init_grid();  
});

function init_grid() {
    ds = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url: '/movie/grid_data'}),

        reader: new Ext.data.JsonReader({
            root: 'Movies',
            totalProperty: 'Total',
            id: 'id'
        }, [
            {name: 'title', mapping: 'title'},
            {name: 'plot', mapping: 'plot'},
            {name: 'release_year', mapping: 'date'},
            {name: 'genre', mapping: 'genre'},
            {name: 'mpaa', mapping: 'mpaa'},
            {name: 'directed_by', mapping: 'directed_by'}
        ]),       
        // turn on remote sorting
        remoteSort: true
    });

    var cm = new Ext.grid.ColumnModel
    ([{
           id: 'title',
           header: "Title",
           dataIndex: 'title',
           width: 250
        },{
           header: "Release Year",
           dataIndex: 'release_year',
           width: 75
        },{ 
           header: "MPAA Rating",
           dataIndex: 'mpaa',
           width: 75
        },{ 
           header: "Genre",
           dataIndex: 'genre',
           width: 100
        },{ 
           header: "Director",
           dataIndex: 'directed_by',
           width: 150
        }]);
       
    cm.defaultSortable = true;

    grid = new Ext.grid.Grid('movies_grid', {
        ds: ds,
        cm: cm,
        selModel: new Ext.grid.RowSelectionModel({singleSelect:true}),
autoExpandColumn: 'title'
    });

    grid.render();   
    ds.load({params:{start:0, limit:20}});
}

事情还没有结束,server端的Rails代码还没有实现。
一个Controller是必不可少的,我们创建一个Rails controller类,MovieController。留意一下刚才的js代码,你会发现我们使用了一个URL” '/movie/grid_data'”作为数据源。在Rail应用中,这意味着MovieController存在一个grind_data方法。

class MovieController < ApplicationController

    def list
    end

    # Called from the list page to get the movie list data to populate the grid.
    def grid_data
        start = (params[:start] || 1).to_i     
        size = (params[:limit] || 20).to_i
        sort_col = (params[:sort] || 'id')
        sort_dir = (params[:dir] || 'ASC')

        page = ((start/size).to_i)+1
   
        @movie_pages = Paginator.new(self, Movie.count, size, page)   

        @movies = Movie.find(:all,
                             :select => "id, title, plot, date, genre, mpaa, directed_by",
                             :limit=>@movie_pages.items_per_page,
                            ffset=>@movie_pages.current.offset,
                            rder=>sort_col+' '+sort_dir)
 
        return_data = Hash.new()     
        return_data[:Total] = @movie_pages.item_count     
        return_data[:Movies] = @movies.collect{|u| {:id=>u.id,
                                            :title=>u.title,
                                            :plot=>u.plot,
                                            :date=>u.date,
                                            :genre=>u.genre,
                                            :mpaa=>u.mpaa,
                                            :directed_by=>u.directed_by} }     
        render :text=>return_data.to_json, :layout=>false
    end
end

补充说明:限于篇幅,这个例子中没有说明数据库结构,不过读者从代码中很容易就可以构造出来。
利用类似的方法,我们也可以很容易的实现Ext的tree和其它功能,关键在于改变数据源。有兴趣的读者可以尝试改写Ext的demo代码。

四.Streamlined
Streamlined(www.streamlinedframework.org) 由 Relevance LLC 创建,脱胎于进行自动培训(叫作 Code Site )的一组开源工具,而且每次 Relevance 构建商业 Rails 应用程序时,它都会得到改进。最终,此团队生成了通用的 Streamlined 框架,可以解决跨越众多项目的公共问题。
自从 Rails 出现以来,各种形式的和各种大小的 Rails 插件一直在提升所有应用程序开发的抽象程度。其中,Streamlined 以其产品级质量的应用程序生成器超越了scaffold。
在Streamlined提供的众多优秀特性之中,就包括了对AJAX的支持.
Streamlined的安装很简单:
script/plugin install http://svn.streamlinedframework.org/branches/stable/streamlined

在下图由Streamlined生成的scaffold中,每个列都是可排序的,并且增删查改操作都只会产生页面的局部刷新。

                               图3 Streamlined生成的scaffold
除了Streamlined以外,类似的Rails插件还有Hobo(http://hobocentral.net/) ,activescaffold
(http://activescaffold.com/)和AutoAdmin(http://code.trebex.net/auto-admin/)。它们都提供了Rails对AJAX的支持。

相关推荐

Global site tag (gtag.js) - Google Analytics