Making Grails data-binding interpret empty String values ("") as zero (0) - grails

This question is about altering how the Grails data-binding handles string-to-integer conversion.
Consider the following domain object:
class Foo {
String name
Integer price
}
Furthermore, assume that the domain object is populated from HTTP request parameters:
def foo = new Foo(params).save()
The save() method above will fail if params.price == "" (empty string). I'd like to change this behaviour globally so that an empty string is parsed as zero (0) when converting from a string to an integer in Grails data-binding. How do I achieve that?

added a filter see the setion 5.5.1 Events and Auto Timestamping in the grails documentation (http://grails.org/doc/1.1.x/index.html)
def beforeInsert = {
if (price == '') { price = 0}
}

Instead of changing the data binding why not just write your own setter? In the setter test to see if the string is empty, if it is set price to 0. If it isn't do a normal integer conversion.

try this constraint instead
static constraints = {
price(validator: {val, obj ->
if (val == '' || val == 0) {
obj.price = 0
return true
} else if (val < 1) {
return false;
}
})
}

import org.grails.databinding.BindUsing
class Foo {
String name
#BindUsing({ obj, source ->
source["price"] ?: 0
})
Integer price
}

Related

adding objects to list if it doesn't contain it

I'm trying to add object to a list only if it wasn't added already .. like this:
for (var interest in poll.poll.interests) {
InterestDrop n = new InterestDrop(interest, false);
print(interest);
print(dropInterestsList);
print(dropInterestsList.contains(n));
if (!(dropInterestsList.contains(n))){
dropInterestsList.add(n);
}
}
but this always return false and add the object even when its already there ... how to solve this?
ANSWER:
class InterestDrop {
String name;
bool isClicked;
InterestDrop(this.name, this.isClicked);
bool operator == (o) => o is InterestDrop && name == o.name && isClicked == o.isClicked;
int get hashCode => hash2(name.hashCode, isClicked.hashCode);
}
You need to override the equality operator in your custom class.
From the docs:
The default behavior for all Objects is to return true if and only if
this and other are the same object.
So your contains method will only return true if your array contains the exact object you are comparing against.
You need to do something like this:
class InterestDrop {
operator ==(InterestDrop other) => identifier == other.identifier;
}

Sorting list or getAll in Grails

I wanted to implement a default sort order in my domain class and immediately found it didn't work with the getAll method. No biggie, I just used list instead. The thing is that the default sort order in a domain class does not allow you specify multiple sort fields (as seen here).
My goal is to sort all Foo objects first by the name of their Bar object, then by their own name.
class Foo {
String name
String Bar
}
class Bar {
String name
}
How can I implement this in the domain class so I don't have to specify a long/nasty comparator every time I call .list()?
One of my attempts:
static Comparator getComparator() {
def c = { a, b ->
def result = a.bar.name.compareTo( b.bar.name );
if ( result == 0 ) {
result = a.name.compareTo( b.name );
}
}
return c as Comparator
}
Then I could just call Foo.list(Foo.getComparator())... if I could get it to work.
Update:
I think I am really close here, just having trouble with implementing two comparisons in the same sort closure.
Foo.list().sort{ a, b ->
def result = a.bar.name <=> b.bar.name;
// Things mess up when I put this if statement in.
if( result == 0 ) {
a.name <=> b.name
}
}
Disco!
class Foo { // My domain class
// ...
static Comparator getComparator() {
def c =[
compare: { a, b ->
def result = a.bar.name <=> b.bar.name;
if( result == 0 ) {
result = a.name <=> b.name
}
return result
}
] as Comparator
}
// ...
}
And implemented like this in my controller:
Foo.list().sort( Foo.getComparator() )
PS:
The above works, but Jeff Storey posted some code in his answer after I discoed, and his code works and is much nicer than mine so use it :)
In your case, would it make sense to have Foo implement Comparable and the implementation could do the comparison as you described? Then when you sort the objects in a list, because they are Comparable, they will sort properly.
If it does not make sense for you to implement Comparable though, you will need to specify a comparator to sort by.
Here's some sample code based on your comments:
edit:
class Person implements Comparable<Person> {
String firstName
String lastName
int compareTo(Person other) {
int lastNameCompare = lastName <=> other.lastName
return lastNameCompare != 0 ? lastNameCompare : firstName <=> other.firstName
}
String toString() {
"${lastName},${firstName}"
}
}
def people = [new Person(firstName:"John",lastName:"Smith"), new Person(firstName:"Bill",lastName:"Jones"), new Person(firstName:"Adam",lastName:"Smith")]
println "unsorted = ${people}"
println "sorted = ${people.sort()}"
This prints:
unsorted = [Smith,John, Jones,Bill, Smith,Adam]
sorted = [Jones,Bill, Smith,Adam, Smith,John]
To further simplify the above post (I would have commented on it but I don't have the rep yet), you can chain the groovy compare operators using the elvis operator:
class Person implements Comparable<Person> {
String firstName
String lastName
int compareTo(Person other) {
return lastName <=> other.lastName ?: firstName <=> other.firstName
}
String toString() {
"${lastName},${firstName}"
}
}
def people = [new Person(firstName:"John",lastName:"Smith"), new Person(firstName:"Bill",lastName:"Jones"), new Person(firstName:"Adam",lastName:"Smith")]
println "unsorted = ${people}"
println "sorted = ${people.sort()}"
This will give you the same result because 0 is considered false in groovy's eyes, which will make it look at the next conditional in the chain.

Validating a group of fields in grails domain object

I have a command object that captures a feedback form with 3 textareas.
class FeedbackCommand {
String textarea1
String textarea2
String textarea3
String username
static constraints = {
textarea1(nullable:true, blank:true)
textarea2(nullable:true, blank:true)
textarea3(nullable:true, blank:true)
username(nullable:false, blank:false)
}
}
I'd like to ensure that at least ONE of the textareas is filled out.
I came up with adding a fake flag field as a 'constraint' field, and then doing a bunch of object checks in the custom validator for that field. If after looking around in myself and i dont find what I want, I throw an error.
Right now, I'm doing this:
class FeedbackCommand {
String textarea1
String textarea2
String textarea3
boolean atLeastOne = true
String username
static constraints = {
textarea1(nullable:true, blank:true)
textarea2(nullable:true, blank:true)
textarea3(nullable:true, blank:true)
atLeastOne(validator: { boolean b, FeedbackCommand form, Errors err ->
if (b) {
if ( (form.textarea1==null || form.textarea1?.isAllWhitespace()) &&
(form.textarea2==null || form.textarea2?.isAllWhitespace()) &&
(form.textarea3==null || form.textarea3?.isAllWhitespace()))
{
// They havent provided ANY feedback. Throw an error
err.rejectValue("atLeastOne", "no.feedback")
return false
}
}
return true
})
username(nullable:false, blank:false)
}
}
Is there a better way to
validate a related/group of fields (at least one can't be blank, 2 should have values, etc)?
a groovier way to express "at least one shouldnt be null/blank" rather than my gross if-statement block?
Thanks
The Extended Validation plugin also adds support for instance validators, which allow to define constraints over several field without defining an artificial flag field or without repeating the validator for each field involved.
validate a related/group of fields (at least one can't be blank, 2 should have values, etc)?
Try this:
if ( (form.textarea1?.trim() ? 1 : 0) +
(form.textarea2?.trim() ? 1 : 0) +
(form.textarea3?.trim() ? 1 : 0) < 2) {
err.rejectValue("atLeastTwo", "no.feedback")
return false
}
a groovier way to express "at least one shouldnt be null/blank" rather than my gross if-statement block?
This is slightly Groovier...
if (!( (form.textarea1?.trim() ?: 0) ||
(form.textarea2?.trim() ?: 0) ||
(form.textarea3?.trim() ?: 0) )) {
err.rejectValue("atLeastOne", "no.feedback")
return false
}
WRT validating a group of fields, you could assign the validator closure to one of the fields. You don't need any extra/ficticious field.
If it's going to be used often, create a plugin
http://www.zorched.net/2008/01/25/build-a-custom-validator-in-grails-with-a-plugin/
or use a plugin for constraints
http://grails.org/plugin/constraints
About grooviness I'm not an expert. But the safe navigator operator ?. makes unnecessary to ask for null
if ( form.textarea1?.isAllWhitespace() &&
form.textarea2?.isAllWhitespace() &&
form.textarea3?.isAllWhitespace() )
{
// They havent provided ANY feedback. Throw an error
err.rejectValue("atLeastOne", "no.feedback")
return false
}
You can use the min-criteria plugin for that.
http://www.grails.org/plugin/min-criteria

ASP.Net MVC : Get query values with no key

I have URL: http://site.com/page.aspx?update
how do I check if that update value is present?
HttpValueCollection treats that as an entity with null key. I have tried:
var noKeyValues = Request.QueryString.GetValues(null);
if (noKeyValues != null && noKeyValues.Any(v=>v==update)) ...
but it gives me a frowny line, because GetValues' argument is decorated with [NotNull].
so I end up doing:
var queryValuesWithNoKey =
Request.QueryString.AllKeys.Select((key, index) => new { key, value = Request.QueryString.GetValues(index) }).Where(
item => item.key == null).Select(item => item.value).SingleOrDefault();
if (queryValuesWithNoKey != null && queryValuesWithNoKey.Any(v => v.ToLower() == "update")) live = true;
not the most elegant workaround. Is there a better way to get key-less value from query string?
You can use
Request.QueryString[null]
to retrieve a comma separated list of keys with no values. For instance, if your url is:
http://mysite/?first&second
then the above will return
first,second
In your case, you could just do something like:
if(Request.QueryString[null] == "update")
{
// it's an update
}
if that's the only key you would use
Request.QueryString.ToString() to get the "update" value
I know I'm late to the party, but this a function that I use for this kind of task.
internal static bool HasQueryStringKey(HttpRequestBase request, string key)
{
// If there isn't a value, ASP will not recognize variable / key names.
string[] qsParts = request.QueryString.ToString().Split('&');
int qsLen = qsParts.Length;
for (int i = 0; i < qsLen; i++)
{
string[] bits = qsParts[i].Split('=');
if (bits[0].Equals(key, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
You may need to update it so that it is case sensitive, or uses different arguments depending on your purposes, but this has always worked well for me.

Groovy - Type testing?

I'm really brand new to Groovy and I'm trying to get something done. I've written some Groovy code (which works just fine) which receives some text. This text should be an integer (between 0 and 10). It may just happen a user enters something different. In that case I want to do some specific error handling.
Now I'm wondering, what's the best / grooviest way to test if a string-typed variable can be casted to an integer?
(what I want to do is either consume the integer in the string or set the outcome of my calculation to 0.
Thanks!
The String class has a isInteger() method you could use:
def toInteger (String input) {
if (input?.isInteger()) {
return input.toInteger()
}
return 0
}
use groovy contains
if ( x?.isInteger()) {
return (0..10).contains(x)
} else {
return false
}
Is this what you're saying?
Integer integer = 0
try {
integer = (Integer) string
assert integer > 0
assert integer < 10
catch(e) {
integer = 0
}
There are lots of ways this can be done in groovy, if you're comfortable with regular expressions, this is about as concise as you can get:
def processText(String text) {
text ==~ /(10|\d)/ ? text.toInteger() : 0
}
assert 0 == processText("-1")
(0..10).each {
assert it == processText("$it")
}
assert 0 == processText("11")
I'm a little unsure what you mean by "specific error handling" if the user does something different.
If this is a web application, I'd take a look at grails and the constraints that you can put on the fields of a domain object, that would let you easily express what you're trying to do.
You have the grails tag on your question, so if you are using Grails, you might consider making this an Integer property on a domain class. The param may come in as text, but you can bind it to an integer property with a default value of 0:
class MyDomain {
Integer whatever = 0
static constraints = {
whatever( min:0, max:10)
}
}

Resources