Meeting the relations
In Hibernate, and therefore in Grails, persistent objects can be given relationships to other persistent objects. Grails supports the following types of relationships:
- One-to-one — where one instance of a class can have a relationship to a single instance of another class. For example, a person can have only one heart, so the relationship between person and heart would be one-to-one.
- One-to-many — where one instance of a class can have a relationship to a number of instances of another class. For example, a person can have many telephone numbers.
- Many-to-one — the other side of one-to-many, where many instances of a class have relationships to one single instance of another class. For example, many children can have the same father.
- Many-to-many — where many instances of a class can be related to many instances of another class. For example, a child can have many parents, and a parent can have many children.
Relating roles and users
So far, you have a Role
class and a User
class, and you can create users and roles in the application. However, there is no relationship between the two classes; so you have no way of knowing which role a user is in. Scaffolding allows you to manage relationships between objects. All you need to do is create the relationships in the domain. You can create the relationship between the Role
class and the User
class by adding the highlighted code given here to the Role.groovy
class:
package app class Role { static hasMany = [users: User] String name static constraints = { name(blank: false, size: 1..20) } public String toString() { return name } }
The relationship between a Role
and a User
is one-to-many, which is defined by the hasMany
property. You have also added a constraint to the name of a role to make sure that it is not empty, and is not more than 20 characters. The toString
method on Role
has been overridden, so that the scaffolding can present meaningful role options when creating a user.
You should also associate the User
class with the Role
class:
package app class User { String username String title String firstName String lastName String password Date dateCreated Date lastModified Role role static constraints = { username(blank: false, size: 4..20, unique:true) title(blank:false, inList:["", "Dr", "Miss", "Mr", "Mrs"]) firstName(blank: false, size:1..20) lastName(blank: false, size:1..30) password(blank: false, size:6..20, password:true) role() dateCreated(nullable: true) lastModified(nullable: true) } }
A role will apply to many users, but a user can belong only to one role. By simply adding a property of the type Role
to the User
class, you have created the other side of the many-to-one relationship between roles and users. You can then control where role information is displayed in the user scaffolding by adding it as a constraint.
The effect of making these changes on the scaffolding is that when a new user is created, you are prompted to select the role that they belong to. Additionally, if you edit a role, you will be allowed to add a new user to the role.
Ordering fields through constraints
Finally, it would be a good idea to hide the passwords of our users on the User List page. By default, the scaffolding for the list action displays only six columns. The first column is always the database ID of the object, which is rendered as a link to the view action. The other five columns are taken in the order specified by the constraints on the domain class. In our example, we can show the users' roles and hide the users' passwords by swapping the order of the role and password in the constraints for the User
class. So,
password(blank: false, size:6..20, password:true) role()
becomes:
role() password(blank: false, size:6..20, password:true)
Once this change is made, you can see that passwords are no longer displayed on the User List page: