`
Ivan_Pig
  • 浏览: 388278 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

使用Groovy on Grails实现Ruby on Rails15分钟创建的Blog

阅读更多
    事先说明,我对Ruby只懂个皮毛。而Rails则没有接触过。看了视频后,还是能看懂的,语法什么的大概都能猜到意思。现在学习Grails,所以想用Grails来实现看看。

    先分析下,视频里面所讲的Blog的内容。以Grails的名词来解释。(不知道Rails里面的专业术语。。。。)

1.首先是两个领域模型,Post和Comment。是一对多的关系。Post里面有title和body属性,不能为空。Comment里面持有Post的id以及body属性。
2.身份的验证。发布,编辑Post需要身份验证。
3.实现RSS浏览Post
4.回复Comment
5.AJAX实现动态显示添加的Comment

    下面就开始使用Grails来实现这个Blog。开发工具是Intellij Idea + Grails插件。

    首先,创建Blog项目,和创建Java项目是类似的。如果你爱用命令行那就敲命令吧。

    创建完了项目,那么就开始着手实现了,当然是先创建两个领域模型Post和Comment.
class Post {
    static hasMany = [comment:Comment]
    
    String title
    String body
}
class Comment {
    Post post
    String body
}

    如果使用过任何ORM框架,那么这段代码没有难理解的地方吧!

    静态的hasMany设置是个Groovy的hashmap:键是comment;值是Comment类.

    接着创建Post和Comment的CRUD.
新建两个Controller,GroovyController和CommentController。如下所示。

class PostController {
    def scaffold = Post
}
class CommentController {
    def scaffold = Comment
}


    def scaffold = ***的意思就是创建最基本的CRUD。这样你就可以运行项目了。看看效果。



    框框内就是两个Controller。首先看看PostController。在你点击了NewPost之后,你会立刻发现两个问题。Body在Title的上方,Body的输入区域是textfield,而一般应该是textarea。先不管这个,随便输入点信息进去,是没有问题的。说明目前基本流程对了,那么下面开始修改刚才说的问题,并给Title和Body加上不能为空的限制。其实排序和限制可以说是一样的东西。往下看。

打开Post领域模型。修改代码如下

class Post {
    static hasMany = [comment:Comment]
    
    String title
    String body

    static constraints = {
        title(maxLength:50,blank:false)
        body(blank:false)
    }
}

    这个闭包应该很好理解吧?title长度不能超过50,不能为空,body也不能为空。而排序也已经被完成了。Grails会按照限制里面的顺序来列出内容。但是这里需要重新启动服务。否则不会出先效果。重启服务器试试看吧。
    顺个便给Comment也加个限制。
class Comment {
    Post post
    String body

    static constraints = {
        post()
        body(blank:false)
    }
}

 
    这里对post没有限制,但是如果你想要post在body前面,那么需要这么写。
   
    接着修改页面显示。你需要general-all controller。我没有在Intellij Idea里面找到哪里可以做此操作(希望知道的告知一声,谢谢。)手动删除PostController和CommentController.使用命令行到项目的根路径下面。输入grails generate-all。在出现提示:Domain Class name not specified. Please enter:时,输入Post。结束以后再次输入grails generate-all,接着输入Comment。这样就可以了。

    现在你会发现两个Controller里面多了很多代码,不管这些。到views目录下面,找到post目录,里面会有四个gsp文件(类似jsp的东西,学过jsp,看gsp没障碍)。刚才出问题的是add.gsp。进入此页面。找到body,将input标签替换为textarea标签即可,这里有个问题,<textarea></textarea>需要这样写,否则会有问题。至少我这里是。
    
    接着就是身份验证了。
    视频里面是使用了一个filter来过滤的(看着是挺简单的)。也没写页面什么,迷惑。
    在Grails里面我是这么实现的!添加一个新的领域模型User来控制访问权限,登录后存放到session里面,然后编辑或创建的时候检查session。没有则转到登录页面。
    这里也和视频里面一样就不查数据库了,检验用户名和密码是否都为admin,是就登录,否则就还在登录页面。
    先建立User领域模型。然后generall-all。

class User {
    String userId
    String password

    static constraints = {
        userId(blank:false)
        password(minLength:6,blank:false)
    }
}


    接着手动的创建登录页面和添加action。
    这里的动作比较大一点。在UserController里面添加如下代码

def login = {
        if (request.method == "GET") {
            session.userId = null
            def userInstance = new User()
        }
        else {
            if(params.userId == "admin" && params.password == "admin"){
                def userInstance = new User(userId:params.userId,password:params.password)
                session.userId = userInstance.userId
                redirect(controller: 'post')
            }else {
                flash['message'] =
                    'Please enter a valid user ID and password'
            }
        }
    }

    如果登录成功则跳转到post控制器,否则打印错误信息。
    再在views目录下的user里面添加一个login.gsp,添加如下代码。

<html>
<head>
<meta http-equiv="Content-Type"
      content="text/html; charset=UTF-8"/>
<meta name="layout" content="main" />
<title>Log in</title>
</head>
<body>
<div class="body">
   <h1>Please log in</h1>
    <g:if test="${flash.message}">
        <div class="message">${flash.message}</div>
    </g:if>
    <g:hasErrors bean="${race}">
        <div class="errors">
           <g:renderErrors bean="${user}" as="list" />
        </div>
    </g:hasErrors>
    <g:form controller="user" method="post" >
        <div class="dialog">
        <table>
           <tr class='prop'>
               <td valign='top' class='name'>
                  <label for='userId'>User ID:</label>
               </td>
               <td valign='top' class='value '>
                  <input type="text" maxlength='8'
                         name='userId'
                         value='${user?.userId}'/>
               </td>
           </tr>
           <tr class='prop'>
               <td valign='top' class='name'>
                  <label for='password'>
                      Password:
                  </label>
               </td>
               <td valign='top' class='value '>
                  <input type="password" maxlength='8'
                         name='password'
                         value='${user?.password}'/>
               </td>
           </tr>
        </table>
        </div>
        <div class="buttons">
           <span class="button">
               <g:actionSubmit value="Log in" />
           </span>
        </div>
    </g:form>
 </div>
 </body>
 </html>


     现在登录就做好了,怎样把他给添加到流程里面去。这里需要一个Filter,在conf文件夹里面创建一个LoginFilters的groovy类,一定要以Filters结尾。
添加如下代码:
class LoginFilters {
    def filters = {
        loginCheck(controller: 'post', action: '*') {
            before = {
                if (!session.userId) {
                    if (actionName.equals('create')||actionName.equals('delete')||actionName.equals('update')||actionName.equals('edit')) {
                        redirect(controller: 'user', action: 'login')
                        return false
                    }
                }
            }
        }
    }
}

    作用就是,当post里面调用的是create,delete,edit或者update Action的时候,如果没有登录则跳转到登录页面。

    这样,权限就设置好了。再进行一下改进,因为这里只要登录成功后就会跳转到list页面,这肯定有问题,应该先记录用户要登录的页面,在登录成功后,再跳转到那个页面。

    修改LoginFilters,如下

class LoginFilters {
    def filters = {
        loginCheck(controller: 'post', action: '*') {
            before = {
                if (!session.userId) {
                    if (actionName.equals('create')||actionName.equals('delete')||actionName.equals('update')||actionName.equals('edit')) {
                        def originalRequestParams =[controller:controllerName,action:actionName]
                        originalRequestParams.putAll(params)
                        session.originalRequestParams = originalRequestParams

                        redirect(controller: 'user', action: 'login')
                        return false
                    }
                }
            }
        }
    }
}


    再修改下,UserController里面的login Action,如下

def login = {
        if (request.method == "GET") {
            session.userId = null
            def userInstance = new User()
        }
        else {
            if(params.userId == "admin" && params.password == "admin"){
                def userInstance = new User(userId:params.userId,password:params.password)
                session.userId = userInstance.userId

                def redirectParams =session.originalRequestParams ?session.originalRequestParams :[controller:'post']

                redirect(redirectParams)
            }else {
                flash['message'] =
                    'Please enter a valid user ID and password'
            }
        }
    }


    这样身份验证就完全添加好了。

    接着是RSS功能.

    Grails并没有对RSS或者Atom提供直接支持。你可以通过控制器render方法的XML能力来构造RSS或者ATOM。尽管如此,还是有一个Feeds 插件 (基于流行的 ROME 开发库)来为Grails提供RSS和Atom的生成器 (Grails参考手册13.3 )

    插件可以到http://plugins.grails.org/下载。
    或者使用命令行,到项目根路径下键入grails install-plugin feeds
    然后在,PostController里添加一个Action
def feed = {
            render(feedType:"rss", feedVersion:"2.0") {
                title = "My test feed"
                link = "http://localhost:8080/Blog/post/feed"
                description = "The funky Grails news feed"

                Post.list().each() { post ->
                    entry(post.title) {
                        link = "http://localhost:8080/Blog/post/show/${post.id}"
                        post.body // return the content
                    }
                }
            }
        }    


     然后开始添加Comment,你在保存完Post后,应该发现了,Post的show页面里面就有一个Comment的字段来显示Comment。而Comment本来就有add方法,所以只需要两个整合一下就可以了,将Comment的create.gsp页面的form内容copy到Post的show.gsp页面里面去。在g:form标签里面添加一个属性
controller="comment"

     因为这个页面现在有两个form,而此页面默认的controller是PostController,所以修改此controller为Comment。然后修改一下CommentController里的save Action,重定向修改为
redirect(controller:'post',action:'show',id:commentInstance.post.id)

即保存后还跳转到此post的show.gsp页面。页面结构就先不管了,功能是实现了。很简单吧!(我摸索了差不多1天时间

     最后就是添加AJAX了。
     Grails默认装载Prototype 库,但是通过Plug-in 系统提供像Dojo , Yahoo UI 和 Google Web Toolkit 等其他框架的支持.(Grails中文参考手册).
     这里就使用默认支持的Prototype。在Post的show.gsp页面的head标签里面添加,Prototype支持。
<g:javascript library="prototype" />


     最后就是AJAX实现,就是使用一个标签和render就可以了。将页面里面提交comment的按钮修改为AJAX按钮。同时将g:form里面的属性都去掉就可以了。
<div class="buttons">
            <g:submitToRemote controller="comment" action="save" update="[success:'comments',failure:'error']" value="CreateComment"/>
        </div>

这里的update就是动态刷新用的,成功就刷新id为comments的标签,否则就是id为error的标签。
修改下save Action.将rediect修改为render。这里应该是我对Grails不熟悉的原因。由于在gsp里面列Comment的标签是g:each,我不知道是否可以动态的改变它,我没找到办法,或者就是不可以。我直接在ul上加的comments id。然后在save Action里面组装了一下得到的Comments,返回一个str.
def save = {
        def commentInstance = new Comment(params)
        if(!commentInstance.hasErrors() && commentInstance.save()) {
            flash.message = "Comment ${commentInstance.id} created"
            def comments = Comment.findAllByPost(commentInstance.post)
            def str = ""
            comments.each {str = str + "<li>" + it + "</li>"}
            render(str)
//            redirect(controller:'post',action:'show',id:commentInstance.post.id)
        }
        else {
            render(view:'create',model:[commentInstance:commentInstance])
        }
    }

    这样,整个Blog就搞定了。页面上差异肯定是比较大一点,修改就行了。功能和ruby的基本相同了。有一点不同的应该是RSS那里,ruby会在浏览器的地址栏出现一个rss标签,而这里只能输入地址,应该也是可以的,我刚接触而已,做个实验罢了。如果熟悉Grails,相信15分钟之内是能搞定这个的!

ps:附件不知道会不会乱码,linux下打的包。。。。
  • 大小: 46.2 KB
4
1
分享到:
评论
2 楼 winking6gr 2009-12-03  
在编辑状态下,右键代码的任意位置,选择generate,就可以生成controller等文件。
1 楼 ehow 2009-10-15  
挺好,哥们加油

相关推荐

    Groovy&Grails - 指南.ppt

    Groovy 和 Grails 与 Ruby on Rails 一样,都追求开发效率和简洁性,但它们建立在不同的语言基础之上。Ruby on Rails 是基于 Ruby 语言,而 Grails 则是基于 Groovy。虽然 Grails 受到 Rails 的启发,但它采用了 ...

    Groovy轻松入门—Grails实战基础篇

    Grails则是一个构建于Groovy之上的开源Web应用框架,它借鉴了Ruby on Rails的设计模式,提供了快速开发的能力,强调代码的简洁性和可读性。 在“Groovy轻松入门—Grails实战基础篇”中,我们将探讨以下几个关键知识...

    Apress.Beginning.Groovy.and.Grails.From.Novice.to.Professional.2008.rar

    Grails,则是基于Groovy构建的一个现代Web应用框架,它借鉴了Ruby on Rails的设计理念,致力于提供快速开发的解决方案。Grails的主要优点包括MVC(模型-视图-控制器)架构、GORM(Grails Object Relational Mapping...

    grails快速开发web

    - **实战技巧**:包括 GORM (Groovy Object Relational Mapping) 的使用、如何在 Grails 中实现 Ajax 功能、处理遗留数据库的方法、利用遗留框架以及如何在 Grails 中使用 WebFlow。 - **高效编程系列**:涵盖使用 ...

    Groovy Grail的eclipse插件

    Grails则是一个基于Groovy的开源Web应用框架,它借鉴了Ruby on Rails的设计理念,提供了模型-视图-控制器(MVC)架构模式,简化了开发流程,使开发者能快速创建全功能的Web应用。Grails的特性包括自动化 ORM(对象...

    Grails Grails Grails

    Grails 的设计深受Ruby on Rails的影响,提供了MVC(模型-视图-控制器)架构模式,允许开发者快速构建动态、数据库驱动的Web应用。 **Groovy 语言基础** Groovy 是一种动态类型的、面向对象的编程语言,它可以无缝...

    grails和groovy的电子书-4

    Grails是一个现代的MVC Web框架,它受到Ruby on Rails的启发,建立在稳固的砖石和最佳组件之上。Grails的开发旨在提高Web应用开发的生产效率,并使得使用强大且动态的Groovy语言进行编程变得更加有趣。Grails框架...

    eclipse开发grails插件

    **Grails**是基于Groovy语言的全栈式Web开发框架,它借鉴了Ruby on Rails的设计理念,提供了快速开发的可能。Grails的核心特性包括MVC架构、领域驱动设计(GORM)、自动化构建过程以及丰富的插件系统。通过Eclipse的...

    Groovy need not rails——介绍自己写的一个基于groovy的框架,Webx

    "Groovy need not rails"指的是Groovy并不需要像Ruby on Rails那样的全栈框架,因为Groovy自身就提供了强大的工具和库来构建Web应用程序。Webx是一个基于Groovy的框架,它旨在简化Web应用开发,提供类似于Rails的...

    grails-2.4.4.zip

    Grails 借鉴了Ruby on Rails的设计理念,引入了GORM(Grails Object Relational Mapping)用于数据库操作,以及一系列的插件系统,支持快速构建复杂的Web应用程序。 2. **Groovy语言基础** Grails 采用Groovy作为...

    grails敏捷开发

    它借鉴了Ruby on Rails的许多优秀理念,同时提供了Java平台的强大功能和兼容性。在本文中,我们将深入探讨Grails的安装、应用程序创建、核心概念以及其在敏捷开发中的应用。 ### 1. 安装Grails 安装Grails通常涉及...

    grails使用freemarker.rar

    Grails是一个基于Groovy语言的全栈式Web开发框架,它吸收了Ruby on Rails的设计理念,提供了简洁的语法和强大的功能。 描述中提到“freemarker是一个比较好用的java模板引擎,grails也对它有很好的支持”。这暗示在...

    Grails1.1中文文档

    Grails是一个基于Groovy语言的开源Web应用框架,它借鉴了Ruby on Rails的许多优秀理念,旨在提高开发效率和代码可读性。 文档主要涵盖以下几个核心知识点: 1. **环境配置**:首先,开发者需要了解如何安装和配置...

    grails 配置mongodb数据库

    Grails是一款基于Groovy语言的、高效的Web应用开发框架,它借鉴了Ruby on Rails的许多优秀特性。MongoDB则是一种流行的NoSQL数据库,以其灵活性、高性能和易于扩展性而闻名。 首先,我们需要确保已正确安装了Grails...

    Groovy vs_ JRuby Presentation.ppt

    JRuby则可以使用Ruby的大量库,如Rails框架,以及各种测试和自动化工具。 在高级特性上,Groovy的AST(抽象语法树)转换允许在编译时自定义语言行为,而JRuby则利用Ruby的元编程能力提供类似的功能。 最后,演示...

Global site tag (gtag.js) - Google Analytics