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

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.

Related

Updating dynamically computed property in polymer.dart

I have a scenario where I have a property that is data-bound using polymer.dart, but it does not have its own backing field. Instead it is dynamically evaluated at run-time by logic which is dependent on a lot of other internal conditions. So when other logic dictates I want to tell the data-binding to update the value. In C#/XAML the NotifyPropertyChange does not require you to pass in old and new value so it is easy to solve this. But in polymer.dart we do need to pass old and new value always, which is not possible for a dynamically evaluated property (or at least not preferable for performance reasons). How would we handle this in polymer.dart?
Here is a pseudo example. The question is what I should put in the ??? fields?
class MyBoundClass extends Observable {
void run() {
... logic, sets values in several internal non-observable objects...
notifyPropertyChange(#status, ???, ???);
}
String get status {
result = ... logic, evaluates values from several internal non-observable objects...
return result;
}
}
I guess one solution would be to simply introduce another backing field in MyBoundClass. But what I really want is just to update the binding and I don't see why it required to pass the old value. It seems to me that if you just want to update the binding, the old value is not relevant?
Passing null as old value should do.

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

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

How to define a Result class which can be treated as boolean but has methods

I'm working on adding further feature for a authentication module, for some reason, I cant change the interface, so the result should be used in some if..else condition.
I think I may need to define a Result class and return it's instance as result, this result can be treated as boolean so that the original projects which using this method will not be influenced and I can get the further info by calling method (for example: the reason of why validate is false). I think the following way can match my goal by return true or false.define_method(:reason, proc[]{return reason}) but I think it's not a best way to do it.
Any idea is good idea, thanks
Only false and nil are false values in Ruby, instance of your result class will definitely be true.
true and false are unique in Ruby. They are the only instance of TrueClass and FalseClass, respectively. Defining singleton methods on them will affect all other places using true or false. This may work in single threaded programs, but possibly not for multi threaded programs.
If the authentication API that you cannot change accepts only boolean values, I don't think you have good way to add further features while keeping backwards compatibility.

Causing type conversion of a GORM field to fail validation

I have a grails domain class with an Integer property such as:
class MyDomainClass {
Integer i
static constraints = {
i(min: 0, max 5,
validator: {
// Something that fails when type conversion was used.
}
}
}
If i is set to a non-integer, e.g., 3.1 it will set i to 3 due to type conversion. But what I want to do is to either disable type conversion for i, or preferably fail validation when was originally set via type conversion.
Note: I want this to work both via explicit setting of the value, and via the default properties constructor.
Can this be done?
In your cusom validator you should be able to access the original value of i from the request parameters. To do this you'll first need to get the current HttpServletRequest. There's a Spring/Grails helper class that allows you to get the current request from anywhere, though this is not a particularly recommended practice
You can then test yourself whether this value is really an Integer, e.g.
static constraints = {
i(min: 0, max 5,
validator: {
try {
def originalValue = getRequestParam('i')
return true
} catch (NumberFormatException ex) {
return false
}
}
)
}
By the time validator is executed value is already casted.
I think the easiest way is to create a custom setter.
In custom setter you may take the value, do with it what you want and if it is not an Integer throw an error. You can even simulate validation exception if you want.
This approach should cover all your use cases, unless you are explicitly accessing the field of the class by using .# operator.
EDIT:
you will have to make sure, that in your controller you are not doing:
params.getInteger('paramName')
because the cast might happen in there, and even your custom setter won't help.

Distinguishing between Grails domain-class fields and getBlah() methods via GrailsDomainClassProperty

I'm writing a Groovy script (as part of a Grails plugin) and I want to get a list of properties for a GrailsDomainClass that a user of my plugin might define. I can do this using domainClass.properties (where domainClass is a GrailsDomainClass).
However, suppose a user has the grails domain class:
class Example {
String name
static constraints = {
}
def getSomeNonExistingProperty(){
return "Not-a-real-property"
}
}
In this case, domainClass.properties returns a list with both name and someNoneExistingProperty
I understand that this is because of Grails is generating a read-only property on-the-fly for use where someone has a getBlah() method. That's great, but in my script I want to perform some actions with the "real" properties only (or at least non read-only properties).
That is, I would like some way of distinguishing or identifying someNonExistingProperty as a read-only property, or, alternatively, as a property generated by Grails and not entered explicitly as a field in the domainClass by the user of my plugin.
I've looked at the GrailsDomainClassProperty Class and it has a range of methods providing information about the property. However, none of them appear to tell me whether a property is read-only or not, or to allow me to distinguish between a field defined in the domainClass and a field created on-the-fly by Grails as a result of a "getSomeNonExistingProperty()" method.
Am I missing something obvious here? Is there a way of getting a list of just the explicitly user-defined fields (eg name, in the above example)?
I believe transient properties are what you are trying to exclude
I've run into this problem a few times, and instead of trying to work around it I typically just end up renaming my getX() method. It's probably the easiest option.
Edit:
Alternatively, I wonder if you could use reflection to see which methods are defined on the class, and while iterating over your properties see if the property has an explicit getter defined, and omit it. I'm not very familiar with reflection when it comes to Groovy and Grails, especially with the dynamic methods, but it's a possible route of investigation.

Resources