I have a domain object called User:
class User{
String username;
String firstName;
String lastName;
Zipcode zip;
}
I also have a Zip Code object:
class Zipcode {
String zip;
String city;
String state;
Float lat;
Float long;
}
The zipcode table should never be modified as it contains static reference data prepopulated
A user belon开发者_运维百科gs to one zipcode. The user enters the zipcode as part of the User creation.
How should I model the domain objects relationship? I would like like to make sure that GORM does not attempt to update zipcodes. I would like to make sure that the user only enters valid zipcode numbers. (Which are found in the zipcode table) How do I configure the constraints on the User object? In the controller, I do the following:
def userInstance = new User(params) // where params are form values
How do I set the proper zipcode on the object?
You would not let GORM manage the zip
property (and restrict GORM from doing so at a second stage), at all.
That's what mfloryan's approach tells, too; however, his approach doesn't separate concerns, properly (separation of concerns paradigm): In the MVC (Model-View-Controller) pattern, it's not the controllers' task to "model" the data model, but it's the task of the data access layer (which is - in case of GORM - the domain classes theirselves).
Thus, the User
class would be implemented like that:
class User {
String userName
String firstName
String lastName
String zip
ZipCode retrieveZipCode() {
ZipCode.findByZip(zip)
}
static constraints = {
zip nullable: false, blank: false, matches: /^\d{5}/,
/* not tested at my machine: */
validator: {
if(!retrieveZipCode(it)) {
return false
}
}
}
}
Note the retrieveZipCode()
method. It's not called getZipCode()
as, otherwise, Hibernate would throw an exception about a "missing setter method". You can also experiment with adding a zipCode
property, a getZipCode()
method (that does nothing or, alternatively, throws an exception), and adding the zipCode
property to the transinients
definition. - Everything of this (in any combination) will not work.
Also note the constraints
definition: It matches when the zip
consists of exactly five digits. (I believe that's the format of ZIP codes there in the USA.)
It should also make sure that the database contains an entry for the user's ZIP code (syntax not tested).
I've changed the ZipCode
class slightly (partly, to avoid a compilation error):
class ZipCode {
String zip;
String city;
String state;
Float latitude;
Float longitude;
}
And finally, there's an integration test:
class UserTests extends GroovyTestCase {
def testUserCreation() {
User user = new User(
userName: "foo", firstName: "bar",
lastName: "baz", zip: "12345")
assert user.validate()
assert user.retrieveZipCode()
user.save()
}
}
Thanks
This sounds like more of an UI issue. Do a Zipcode
object lookup in the controller and set the the object located on the user. Otherwise, I can't see how a Zipcode
could have been altered upon creation of a user.
save = {
params.zip.id = Zipcode.findByZip(params.zip)
def userInstance = new User(params)
}
or
save = {
def userInstance = new User(params)
userInstance.zip = Zipcode.findByZip(params.zip)
}
You should include some validation logic (if the zip is incorrect) and also consider renaming params.zip
to params.userProvidedZip
or something like that.
use Domain event callback
transient beforeUpdate = {
// check to make sure that the zip code value remains the same
// and is never changed...
}
精彩评论