终于干完这一章节,收获很多啊。
和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() } }