grails how to delete property from object - grails

suppose I have MyClass domain class:
class MyClass {
String prop1
String prop2
String prop3
}
I wonder is there any way to delete for example prop1 property from MyClass object ?

The only way to actually delete the property is to remove it from the source file. However, you can make attempts to access the property exhibit the same behaviour as an attempt to access a non-existent property.
class MyClass {
String prop1
String prop2
String prop3
}
MyClass.metaClass {
// Intercept attempts to get the property
getProp1 = {-> throw new MissingPropertyException("can't get prop1")}
// Intercept attempts to set the property
setProp1 = {throw new MissingPropertyException("can't set prop1")}
}

Related

Is there a way to instantiate a class from an object of it's super class without assigning all the variables manually?

Say I have 2 classes:
class User {
String name;
String age;
DateTime birthDate;
User(this.name);
}
class Teacher extends User {
String className;
Teacher(String name): super(name);
Teacher.fromUser(User user, this.className): super(user.name);
}
Doing the following is easy. But what if the super class has 30 fields? Is there a way to make a constructor that will copy all the variables over without having to do:
Teacher.fromUser(User user) {
this.id = user.id;
this.firstName = user.firstName;
this.lastName = user.lastName;
this.gender = user.gender;
...
No.
There is no way to automatically copy fields from one object to another.
If you have more than one class needing the behavior, you can add a copyFrom(User) on the User class which copies all the fields, and then just call this.copyFrom(user) on the subclasses. Then you will, at least, only have to write the code once.

Access object's properties inside named query

Is it possible to access an object's property inside a named query?
Here is a sample domain class
class Publication {
String title
String author
Date datePublished
Integer numberOfPages
static namedQueries = {
newerPublications {
//Will throw an error, cannot access a variable declared in a dynamic context.
gt 'datePublished', this.datePublished
}
}
}
You can do something like this:
newerPublications { Publication newerThan ->
gt 'datePublished', newerThan.datePublished
}
You would then call it as Publication.newerPublications(referencePublication).list()

Grails custom validater, getting a reference to the field name

I am trying to write a generic custom validator for a property, to make it generic i need a reference to the field name within the closure, the code is as follows
In config.groovy
grails.gorm.default.constraints = {
nameShared(validator: {val, obj, errors->
Pattern p = Pattern.compile("[a-zA-Z0-9-]{1,15}")
Matcher m = p.matcher(val)
boolean b = m.matches()
if(!b)
errors.rejectValue('name', "${obj.class}.name.invalid", "Name is invalid")
})
in My domain class
class Student{
String name
static constraints = {
name(shared:'nameShared')
}
}
class Teacher{
String firstName
String lastName
static constraints = {
firstName(shared:'nameShared')
}
}
I want to use the same validator for both name and firstName, but since i am hardcoding the fieldName in the validator, it will always work for name and not firstName, so i want to know if there is anyway i can get a reference to the fieldname and make the validator generic, please help
You could use the variable propertyName to get the name of the validated property.
From the grails docs:
The Closure also has access to the name of the field that the constraint applies to using propertyName
myField validator: { val, obj -> return propertyName == "myField" }
You could wrap your validator-closure inside another function like this:
def getValidator(myValue) {
return { val, obj, errors ->
// make use of myValue
}
}
myField validator: getValidator('foo')

Grails/GORM not cascading save through entire object hierarchy

I'm having trouble getting saves cascaded down my object hierarchy. Below is the code of my object hierarchy.
class Entity {
static hasMany = [attributes: Attribute]
}
class Attribute extends ValuePossessor {
static belongsTo = Entity
}
abstract class ValuePossessor {
def valueService
Value value
void setValue(val) {
this.value = valueService.Create(val)
this.value.possessor = this
}
}
abstract class Value {
static belongsTo = [possessor: ValuePossessor]
}
class StringValue extends Value {
String value
}
The valueService is simply a service with a big switch statement that creates the correct value type (string, boolean, int, etc.).
Entity e = new Entity()
Attribute attr = new Attribute()
attr.setValue(1)
e.addToAttributes(attr)
e.save()
The above code correctly creates all objects, but fails to save the value object. The entity and attribute are saved, but the value is not. Am I missing some identifier needed to cascade all the way down to the value object?
Figured this out. Apparently there is some magic in the grails dynamic setters. I changed the setValue(val) method to set(val) and it started working. Lesson learned: don't override grails' dynamically added methods because they are built with magic, pixy dust, and unicorn urine.

Adding a method to a domain class

I have a domain class containing a couple of fields. I can access them from my .gsps. I want to add a method to the domain class, which I can call from the .gsps (this method is a kind of virtual field; it's data is not coming directly from the database).
How do I add the method and how can I then call it from the .gsps?
To add a method, just write it out like you would any other regular method. It will be available on the object when you display it in your GSP.
def someMethod() {
return "Hello."
}
Then in your GSP.
${myObject.someMethod()}
If you want your method to appear to be more like a property, then make your method a getter method. A method called getFullName(), can be accessed like a property as ${person.fullName}. Note the lack of parentheses.
Consider class like below
class Job {
String jobTitle
String jobType
String jobLocation
String state
static constraints = {
jobTitle nullable : false,size: 0..200
jobType nullable : false,size: 0..200
jobLocation nullable : false,size: 0..200
state nullable : false
}
def jsonMap () {
[
'jobTitle':"some job title",
'jobType':"some jobType",
'jobLocation':"some location",
'state':"some state"
]
}
}
You can use that jsonMap wherever you want. In gsp too like ${jobObject.jsonMap()}

Resources