终于干完这一章节,收获很多啊。

和DJANGO有类似,也有不同。

User.groovy:

package com.grailsinaction

class User {

    String loginId
    String password
    Date dateCreated

    static hasOne = [profile: Profile]
    static hasMany = [posts: Post, tags: Tag, following: User]
    static mapping = {posts sort: 'dateCreated'}

    static constraints = {
      loginId size: 3..20, unique: true, nullable: false
      password size: 6..8, nullable:false, validator: { passwd, user -> passwd != user.loginId }
      profile nullable: true
    }
}

Profile.groovy:

package com.grailsinaction

class Profile {
        User user
        byte[] photo
        String fullName
        String bio
        String homepage
        String email
        String timezone
        String country
        String jabberAddress

    static constraints = {
            fullName blank: false
            bio nullable: true, maxSize: 1000
            homepage url:true, nullable: true
            email email: true, blank: false
            photo nullable:true, maxSize: 2 * 1024 * 1024
            country nullable: true
            timezone nullable: true
            jabberAddress email: true, nullable: true
    }
}

Post.groovy:

package com.grailsinaction

class Post {
        String content
        Date dateCreated

    static constraints = {
            content blank: false
    }

        static belongsTo = [user: User]
        static hasMany = [tags: Tag]

        static mapping = { sort dateCreated: "desc"}
}

Tag.groovy:

package com.grailsinaction

class Tag {
        String name
        User user

    static constraints = {
            name blank: false
    }

        static hasMany = [posts: Post]
        static belongsTo = [User, Post]
}

UserIntegrationSpec.groovy:

package com.grailsinaction

import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*

@Integration
@Rollback
class UserIntegrationSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    def "Saving our first user to the database"() {
            given: "A brand new user"
            def joe = new User(loginId: 'Joe', password: 'secret')
            when: "the user is saved"
            joe.save()

            then: "it saved successfully and can be found in the database"
            joe.errors.errorCount == 0
            joe.id != null
            User.get(joe.id).loginId == joe.loginId
        }

        def "Updating a saved user changes its properties"() {
            given: "An existing user"
            def existingUser = new User(loginId: 'Joe', password: 'secret')
            existingUser.save(failOnError: true)
            when: "A property is changed"
            def foundUser = User.get(existingUser.id)
            foundUser.password = 'sesame'
            foundUser.save(failOnError: true)

            then: "The change is reflected in the database"
            User.get(existingUser.id).password == 'sesame'
        }

        def "Deleting an existing user removes it from the database"() {
            given: "An existing user"
            def user = new User(loginId: 'Joe', password: 'secret')
            user.save(failOnError: true)

            when: "The user is deleted"
            def foundUser = User.get(user.id)
            foundUser.delete(flush: true)

            then: "The user is removed from the database"
            !User.exists(foundUser.id)
        }

        def "Saving a user with invalid properties causes an error"() {
            given: "A user which fails several field validations"
            def user = new User(loginId: 'Joe', password: 'tiny')
            when: "The user is validated"
            user.validate()

            then:
            user.hasErrors()

            "size.toosmall" == user.errors.getFieldError("password").code
            "tiny" == user.errors.getFieldError("password").rejectedValue
            !user.errors.getFieldError("loginId")
        }

        def "Recovering from a failed save by fixing invalid properties"() {
            given: "A user that has invalid properties"
            def chuck = new User(loginId: 'chuck', password: 'tiny')
            assert chuck.save() == null
            assert chuck.hasErrors()

            when: "We fix the invalid properties"
            chuck.password = "fistfist"
            chuck.validate()

            then: "The user saves and validates fine"
            !chuck.hasErrors()
            chuck.save()
        }

        def "Ensure a user can follow other users"() {
            given: "A set of baseline users"
            def joe = new User(loginId: 'joe', password: 'password').save()
            def jane = new User(loginId: 'jane', password: 'password').save()
            def jill = new User(loginId: 'jill', password: 'password').save()

            when: "Joe follows Jan & Jill, and Jill follows Jane"
            joe.addToFollowing(jane)
            joe.addToFollowing(jill)
            jill.addToFollowing(jane)

            then: "Follower counts should match follow people"
            2 == joe.following.size()
            1 == jill.following.size()
        }

}

PostIntegrationSpec.groovy:

package com.grailsinaction

import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*

@Integration
@Rollback
class PostIntegrationSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    def "Adding posts to user links post to user"() {
            given: "A brand new user"
            def user = new User(loginId: 'joe', password: 'secret')
            user.save(failOnError: true)

            when: "Several posts are added to the user"
            user.addToPosts(new Post(content: "First post.....w002!"))
            user.addToPosts(new Post(content: "Second post......"))
            user.addToPosts(new Post(content: "Third post...."))

            then: "The user has a list of posts attached"
            3 == User.get(user.id).posts.size()
        }

        def "Ensure posts linked to a user can be retrieved"() {
            given: "A user with several posts"
            def user = new User(loginId: 'joe', password: 'secret')
            user.addToPosts(new Post(content: "First"))
            user.addToPosts(new Post(content: "Second"))
            user.addToPosts(new Post(content: "Third"))
            user.save(failOnError: true)

            when: "The user is retrieved by their id"
            def foundUser = User.get(user.id)
            def sortedPostContent = foundUser.posts.collect {
                it.content
            }.sort()

            then: "The posts appear on the retrieved user "
            sortedPostContent == ['First', 'Second', 'Third']
        }

        def "Exercise tagging several post with various tags"() {
            given: "A user with a set of tags"
            def user = new User(loginId: 'joe', password: 'secret')
            def tagGroovy = new Tag(name:"groovy")
            def tagGrails = new Tag(name:"grails")
            user.addToTags(tagGroovy)
            user.addToTags(tagGrails)
            user.save(failOnError: true)

            when:"The user tags two fresh posts"
            def groovyPost = new Post(content: "A groovy post")
            user.addToPosts(groovyPost)
            groovyPost.addToTags(tagGroovy)

            def bothPost = new Post(content: "A groovy and grails post")
            user.addToPosts(bothPost)
            bothPost.addToTags(tagGroovy)
            bothPost.addToTags(tagGrails)

            then:
            user.tags*.name.sort() == ['grails', 'groovy']
            1 == groovyPost.tags.size()
            2 == bothPost.tags.size()

        }
}

Grails里DOMAIN类的一对一,一对多,多对多关系总结及集成测试的更多相关文章

  1. SQLAlchemy_定义(一对一/一对多/多对多)关系

    目录 Basic Relationship Patterns One To Many One To One Many To Many Basic Relationship Patterns 基本关系模 ...

  2. JPA级联(一对一 一对多 多对多)注解【实际项目中摘取的】并非自己实际应用

    下面把项目中的用户类中有个:一对一  一对多  多对多的注解对应关系列取出来用于学习      说明:项目运行正常 问题类:一对多.一对一.多对多 ============一对多 一方的设置 @One ...

  3. Python进阶----表与表之间的关系(一对一,一对多,多对多),增删改查操作

    Python进阶----表与表之间的关系(一对一,一对多,多对多),增删改查操作,单表查询,多表查询 一丶表与表之间的关系 背景: ​ ​ ​  ​ ​ 由于如果只使用一张表存储所有的数据,就会操作数 ...

  4. mybatis 一对一 一对多 多对多

    一对一 一对多 多对多

  5. SSAS中事实表中的数据如果因为一对多或多对多关系复制了多份,在维度上聚合的时候还是只算一份

    SSAS事实表中的数据,有时候会因为一对多或多对多关系发生复制变成多份,如下图所示: 图1 我们可以从上面图片中看到,在这个例子中,有三个事实表Fact_People_Money(此表用字段Money ...

  6. JPA实体关系映射:@ManyToMany多对多关系、@OneToMany@ManyToOne一对多多对一关系和@OneToOne的深度实例解析

    JPA实体关系映射:@ManyToMany多对多关系.@OneToMany@ManyToOne一对多多对一关系和@OneToOne的深度实例解析 今天程序中遇到的错误一 org.hibernate.A ...

  7. day 69-70 一对一 一对多 多对一联表查询

    day 69 orm操作之表关系,多对多,多对一 多对一/一对多, 多对多{类中的定义方法} day69 1. 昨日内容回顾 1. 单表增删改查 2. 单表查询API 返回QuerySet对象的: 1 ...

  8. 使用NHibernate(7)-- 一对一 && 一对多 && 多对多

    1, 一对一. 对于数据量比较大的时候,考虑查询的性能,肯能会把一个对象的属性分到两个表中存放:比如用户和用户资料,经常使用的一般是Id和用户名,用户资料(学校,籍贯等)是不经常被查询的,所以就会分成 ...

  9. JPA 一对一 一对多 多对一 多对多配置

    1 JPA概述 1.1 JPA是什么 JPA (Java Persistence API) Java持久化API.是一套Sun公司 Java官方制定的ORM 方案,是规范,是标准 ,sun公司自己并没 ...

随机推荐

  1. P3398仓鼠(LCA)

    题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...

  2. [Swift通天遁地]三、手势与图表-(6)创建包含三条折线的线性图表

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  3. Django day25 序列化组件(*****)

    序列化:将变量从内存中存储或传输的过程称之为序列化 1.序列化组件是干什么用的? 对应着表,写序列化的类 2.如何使用序列化组件 Serializer 1) 重命名:用source:xx = seri ...

  4. Sublime Text3 配置 Lua5.3.5开发环境

    所需软件 Sublime Text3 Lua5.3.5 配置过程 解压Lua5.3.5包 官方下载的包内是需要makefile安装的(博主Win10下暂为实现),此处提供自动配置完毕的包:Lua5.3 ...

  5. Python/Django 批量下载Excel

    一.前提 项目上需求的变更总是时时发生的,应对需求的我们,也只能变更我们代码,所以.继前两篇之后,我们的批量下载诞生了 二.安装 本文使用zipstream库进行压缩,安装方式:pip install ...

  6. 微信小程序后台获取用户的opeid

    1.微信小程序后台获取登录用户的openid,首先微信小程序将code传给后台服务器 wx.login({ success: function (res) { var code = res.code ...

  7. vuejs {{}},v-text 和 v-html的区别

    <div id="app"> <p>{{message}}</p> <!-- 输出:<span>通过双括号绑定</spa ...

  8. android:autoLink

    android:autoLink 显示URL链接 TextView识别链接的方式有两种,一种是自动识别链接和HTML解析链接 1)自动识别链接 <!-- android:autoLink=&qu ...

  9. JS中的面相对象

    1.使用Object或对象字面量创建对象 JS中最基本创建对象的方式: var student = new Object(); student.name = "easy"; stu ...

  10. SVN系列学习(四)-TortoiseSVN其他操作

    1.新建分支 第一步:从SVN上CheckOut一份,要作为分支模板的文件 第二步:右击[TortoiseSVN]-选择[Branch/tag] 备注说明,[指明分支路径] 第三步:删除电脑上的ZJH ...