Grails: Apply a custom constraint to all fields of an Domain class - grails

In Grails it's possible to define global constraints within the Config.groovy file which can be used to validate all defined constraints from every domain class using
Config.groovy:
grails.gorm.default.constraints = {
'*'(nullable: true)
...
}
Question:
Is it also possible to define a constraint which is only used for the fields of one domain class? I'm thinking about something like this (which isn't working in reality)
class myDomainClass{
fields
...
static constraints = {
'*'(MyCustomCOnstraint:true)
}
}

I don't know if there is a standard solution to that.
In case there is not, you can build a loop inside the constraint closure:
static constraints = {
// use MyCustomCOnstraint:true for fields firstname, lastname and address
['firstname', 'lastname', 'address'].each { property ->
"$property"(MyCustomCOnstraint:true)
}
}

A few things you could take a look at :
a hack for backward compatibility - since grails 2.3.4 I think : in your config.groovy
// Null object error fix for backward compatibility
grails.databinding.convertEmptyStringsToNull = false
This stops converting blanks to nulls - and may cure your issue, there was a reason why this feature was added - for your own app security... so choose wisely.
You could take a look at programming Grails by Burt Beckwith chapter 3 covers custom validation, from install-templates to making extreme custom validation:
import com.myapp.MyUserValidator beans = {
'com.myapp.UserValidator'(MyUserValidator) }
But to be honest I really don't think there is anything is that segment that could help besides the bit that discusses setting up a filter to convert all input blanks to nulls:
convertBlanksToNullsAndTrim
You could reverse that code so that if it is null make it =''. again with the above point in place if is as per default it could get set as null unless point 1 is set in your config.groovy
If it were me I would try the first option to see if it cures current situation

Related

Grails 3.3.2 accessing custom meta constraints

In a grails 2.4.4 project, I was able to define my own custom constraint (called 'supportsToUrl') on a domain property and use it as a tag to control rendering logic in my GSP.
GSP rendering code:
if(domainClass.constraints[p.name].getMetaConstraintValue('supportsToUrl'))
Domain class constraint:
static constraints = {
embedCode(nullable:true, blank:true, unique:false, display:true, supportsToUrl:true)
}
In Upgrading from Grails 3.2.x in section "Grails Validator and ConstrainedProperty API Deprecated" there is discussion about how this functionality has been moved. However, I did not see anything in the new API that refers to meta constraints.
My question is: How do I access custom constraints in Grails 3.3.2?
You could access meta constraints still in Grails 3.3.*
From Validateable trait getConstraintsMap().
Example list of all properties which supports url (supportsToUrl: true)
Set<String> supportsUrlProperties = new HashSet<>()
Map<String, Constrained> constraints = domainObject.getConstraintsMap()
if(constraints) {
constraints.values().each { Constrained constrained ->
DefaultConstrainedProperty propertyToCheck = constrained.properties?.property as DefaultConstrainedProperty
if(propertyToCheck) {
def supportsToUrlConstraint = propertyToCheck.getMetaConstraintValue('supportsToUrl')
if (supportsToUrlConstraint != null && BooleanUtils.isTrue(supportsToUrlConstraint as Boolean)) {
supportsUrlProperties.add(propertyToCheck.getPropertyName())
}
}
}
}
Be aware, that it sees only constraints from domain/entity (abstract or not) which are marked with this Validateable trait. Class hierarchy won't apply - when root/super class implements it, then top class's constraints still are not visible, until you mark it also as Validateable.
So based on the ConstrainedDelegate class, I think the short answer is that it's not possible. ConstrainedDelegate does not expose the metaConstraints map or the attributes map of DefaultConstrainedProperty. I will leave the question open though in the hopes that someone more knowledgeable with the Grails architecture roadmap can explain why.
In the meantime, I was able to hack together a solution by re-purposing the format constraint and comparing the format against my predefined tags. Although I'd love to hear other ideas on how to achieve my original goal as this is pretty clearly not how format was intended to be used.

using angular factory in multiple controllers

I am using angular ui grid. At first I implemented this in a controller and it works fine after all my customization. As I am using multiple grids I cannot write a long controller each time. So, I converted it to factory. I kept the common function in factory and column definition and data in controller. Now when I use this factory in more than 1 controllers, the last controller is overriding all others.
1) Is it correct to make this grid in a factory?
2) If yes how do I overcome this problem?
3) By using factory for this grid, my gridObj.gridApi.pagination.on is throwing error(gridObj is the singleton object that I am returning).
Any suggestion is welcome. Thanks a lot in advance.
You should use a Directive instead. Factories create a single Instant (see Angular Provider Documentation and wont create a private scope, which you need to not override your data.
Note: All services in Angular are singletons.
But Directives provide a private scope and create new instances every time they are called in HTML if you want them to.
//directive
scope: { // this option creates isolated scopes
something : '=',
},
I created a Plunkr showcasing a possible setup. For some more written details please see my answer from few days ago.
Your HTML might look like this afterwards
<my-grid options="all.firstOptions" class="grid"></my-grid>
Where my-grid is your directive and options="" are your special settings (and whatever else you wish to use in the directive). In your directive you declare the default settings and merge them with the special ones.
scope.gridOptions = {
data: scope.options.data, //private scoped from options : '=',
columnDefs: scope.options.colDef || defaultColDef, // optional setting or default setting
// ... some more default data
};
If you have any specific questions, let me know.

Can one constraint on a command object check the result of another?

This is a simple example that doesn't work, I'm wondering if there is a way to validate a inside the validator block of b if it hasn't already been validated.
Example how I thought it would work:
static constraints =
{
a nullable: false
b validator: { val, obj ->
if(obj.errors.hasFieldError('a'))
{
return false
}
}
}
Note: in this scenario obj.errors.hasFieldError('a') returns false even if a is null.
I don't think there's any guarantee of the order the constraints are checked, and it's unlikely that it would have anything to do with the order specified in the constraints block.
However, in addition to the common one-arg custom validator that passes you the current value for that field and the two-arg validator you show where you also get access to the domain class instance, there's a three-arg variant (unfortunately it doesn't seem to be covered in the Grails reference docs ...) where the third argument is the Spring Errors instance. If you define a three-arg validator, GORM ignores any return value since it's assumed that you'll be working directly with the Errors instance, calling one or more of the different rejectValue methods yourself for any validation issues.
So you could remove from the constraints block any standard validations that you want to run yourself and use this approach instead. You can find more information about working with the Errors object in the Spring docs.

Difference between two action signatures in grails

In grails we can define an action using 2 ways:-
def actionname()
{
}
and
def actionname = {
}
What is the difference between the two styles? When I tried to insert a spring security annotation above the action (second style) it said "#Secured" not applicable to field.
What does this mean? Is it because of closure?
The Grails reference docs 7.The Web Layer mentions the use of closures for controller actions in earlier versions of Grails, the preference is now to use methods. However, both are supported. It goes on to list some benefits of using methods instead.
Personally, I use methods in all my controllers and have also come across the issue with annotations such as #Secured that only work on methods and not the closures.
In earlier versions of Grails option 2 (actions as closures) was the only supported style. Grails 2.x introduced the actions-as-methods style and this is now the recommended approach, but the closure style is still supported for backwards compatibility and you'll see it if you are working on an app (or plugin) that was originally written on Grails 1.x.
The first is normal method definition with undefined return type.
The second is an assigment of a closure to a property 'actionname'.
That is why you get "#Secured" not applicable to field message, because this annotation is for methods only.
Shuttsy is correct that that the first way is now a preffered way to define actions in Grails.
This is an agreeable way of defining methods in Groovy at minimal level having the structure above.
The second way of defining is not refering to a method definition rather it's somehow a rule like closure constraints that governs a given class or method. Like when it is used in domain class .
Example
class Person {
String name
Person parent
static belongsTo = [ supervisor: Person ]
static mappedBy = [ supervisor: "none", parent: "none" ]
static constraints = { supervisor nullable: true }
//this allowed for methods only and why you got an error in above cases
#override
def toString(){
return name.toString()
}
}
#Secured annotation accept list of roles (String[])
it is used only for a method definition based on
toString() method inside the class ...i just give u a scenario of the two ..
#Secured annotation since spring security 2.0 supports method only. As a result, you have to convert closures to real methods if you want to apply the security annotation for it. Read more #Secured Annotation.

Is there any way to chain messages together in Grails' message.properties file?

In Grails there is a message.properties file. In this file message are defined like this:
exampleClass.fieldOne.label=Field One
otherExampleClass.fieldOne.label=Field One
I want the ability to use both messages even though they are textually the same. I would like to define them like this:
exampleClass.fieldOne.label=Field One
otherExampleClass.fieldOne.label=${message(code: 'exampleClass.fieldOne.label')}
... but that just make a a call to otherExampleClass.fieldOne.label return the string ${message(code: 'exampleClass.fieldOne.label')} instead of the desired string Field One.
In the message.properties I think that you cannot do it, but maybe with a convention and modifying the templates of the Grails you can achieve it. So my idea is:
Define a convention for your messages (for example, initialize the message with some special char)
exempleClass.fieldOne.label=FieldOne
otherExampleClass.fieldOne.label=#exempleClass.fieldOne.label
Create a TagLib to handle the message
class MyTagLib {
static namespace = "my"
def inheritedMessage = { attrs, body ->
String message = g.message(attrs)
if(message.startsWith("#")) {
//get the other message...
}
out << message
}
}
And finally install templates and change the <g:message/> for <my:inheritedMessage/> or whatever you call it.
For step 2, another approach is to override g.message(), with the benefit of not need the step 3 and make available for all parts of your app the modification. The con is that it will have to be good documented and disseminated or can cause some confusion in other devs.
EDIT
To cover all messages I think the better approach is to customize the messageResource used by Grails. Here is a question that covers how to do it with Spring, to get the messages from the database, could be a start point. And here is a question that shows how to replace the bean in Grails.

Resources