Null or false value in grails - grails

I have a domain class in which one of its fields is of type Boolean. When I retrieve it, how can I differentiate whether it's set to false or it's null ?
Thanks

if(field == null) will work as expected.

Here's a simple example that demonstrates how to test for all 3 possible values of a Boolean
class Person {
Boolean isMale = false
Boolean isFemale = true
Boolean isAdult = null
}
def p = new Person()
assert !p.isMale
assert p.isFemale
assert p.isAdult == null
You can run this code in the Groovy console to verify the expected behaviour

Related

Logic error in null clause

hi I have the following function :
def signup(String name){
def x =Human.where{name == name}
if(x != null)
{
def myhuman=new Human(name: name)
if(myhuman.save() && myhuman.validate())
{
redirect(url:"https//localhost:8080")
}
}
else
{
return
}
}
It works fine. I can create people with different names and I can't create a person with the same name, however I was wondering in that if why do we check for x!=null, shouldn't we check for x == null because we first look if such a person exists and if does not we create it. I tried with x==null and I can't ever create Human, can someone explain?
You check for x != null because you can not perform operations on a null object now can you? In fact it's more Groovy to do the following:
if (!x) {
// Logic
}
This works because of the Groovy Truth.
If x == null validates to true, then you proceed as normal performing whatever operations you need. However, since in your case x is not null, x == null will validate to false and skip the if block. This isn't specific to Grails, it's general programming.
You can use an Elvis operator, if the user does not exist you create a new one.
When a Human exist, it has an id, so you check if has an id, if not, you save it and do the redirect.
You don't need to validate the object, the save method validates the object before saving it, and if it is not validated, returns false.
Human human = Human.findByName(name)?: new Human(name: name)
if(!human.id && human.save()){
redirect(url:"https//localhost:8080")
}else{
return
}

Add Filters based on some condition java 8

I need to filter a list of employees based of some parameter like firstName , lastName etc etc. These parameters are user defined user can choose all filter or a combination of filters.
public List<Employee> getFilterList(String firstName,String lastName)
{
List<Employee> empList = empRepository.getEmployees();
Stream<Employee> empStream=empList.stream();
if(firstName!=null)
{
empStream= empStream.filter(e-> e.getFirstname().equals(firstName))
}
if(lastName!=null)
{
empStream= empStream.filter(e-> e.getlastName().equals(lastName))
}
return empStream.collect(Collectors.toList());
}
Is this a correct way of doing this?
Note: the above code is working fine i am just looking for another better approach (if any).
Case 1: getFilterList(null,null) return list of all employees
Case 2: getFilterList("abc",null) return list of all employees with first name abc.
It shows list empList according to the parameter of firstName filter or filtering according to the parameter lastName, the code pattern are almost same. So I came up with the following code.
public List<Employee> getFilterList(String firstName,String lastName){
List<Employee> empList = empRepository.getEmployees();
return empList.stream().filter(getPredicateBiFun.apply(firstName,Employee::getFirstName))
.filter(getPredicateBiFun.apply(lastName,Employee::getLastName))
.collect(Collectors.toList());
}
It seems more like Java8 style. And here is a static property getPredicateBiFun you see which can get the corresponding Predicate<Employee> expressions according to the parameters. So it's just a BiFunction and a good pattern for what we want.
private static BiFunction<String, Function<Employee, String>, Predicate<Employee>> getPredicateBiFun = (name, getNameFun) -> employee -> name == null ? true : name.equals(getNameFun.apply(employee));
That's all :)
You could also do it this way:
List<Predicate<Employee>> predicateList = new ArrayList<>();
predicateList.add(emp -> firstName == null || (emp.firstName != null && emp.firstName.equals(firstName)));
predicateList.add(emp -> lastName == null || (emp.lastName != null && emp.lastName.equals(lastName)));
empStream.filter(emp -> {
Stream<Predicate<Employee>> predicateStream = predicateList.stream();
return predicateStream.map(predicate -> predicate.test(emp)).reduce((a, b) -> a && b).get();
}).collect(Collectors.toList());
Based on user's choice, you need to create predicateList by adding predicates.
predicateStream.map(predicate -> predicate.test(emp)) returns a Stream<Boolean>. This stream contains values which is result of applying a predicate (ie predicate.test(emp)) on emp instance. Then reduce((a, b) -> a && b) checks if all results in stream were true or not. In the end true or false is returned, on the basis of which filter decides whether an emp object should be selected or not.
Note that Stream<Predicate<Employee>> predicateStream is created for each Employee object in empStream, which might involve some overhead.
Not sure if this is the most optimal way, but it gets rid of the ifs:
List<Employee> empList = empRepository.getEmployees();
return empList.stream()
.filter(e -> firstName == null || e.getFirstname().equals(firstName))
.filter(e -> lastName == null || e.getlastName().equals(lastName))
.collect(Collectors.toList());
Struggled on the excat same thing. For anyone searching for another way:
empList.stream()
.filter(firstName != null ? e -> e.getFirstName().equals(firstName) : e -> true)
.filter(lastName != null ? e -> e.getLastName().equals(lastName) : e -> true)
.collect(Collectors.toList());
Using a ternery operation to apply the filter or not (if not, just set to true in my case)
Note that the second condition takes presidance over the first and if both firstName and lastName are null, you return the list of the Employee. A lot of the conditionals that you have put are therefore evaluated even though their evaluation is not required. I would have done this in along following lines:
return firstName == null && lastName == null ?
empList :
(lastName != null ?
empList.stream().filter(emp -> emp.lastname.equals(lastName) :
empList.stream().filter(emp -> emp.firstName.equals(firstName))
).collect(Collectors.toList());

Grails: Comparing two unsaved domain class objects always returns false

I need to compare several domain class objects while they are still unsaved, however, I always keep getting a false result from the comparison. Turns out even the following comparison will return false:
new DomainClass().equals(new DomainClass())
Since both are brand new objects they should both have identical data and should be equal to each other. Unfortunately the equals method (or the == operator) returns false. Is there another correct way of performing this comparison?
Your code same with this:
a = new DomainClass();
b = new DomainClass();
a.equals(b)
So clearly the test must return false as far as a and b are not referencing same object.
If you want value based comparing:
Iterate over the fields and compare them one by one
Or check here for a more formal way of doing it.
you can use 'spaceship operator' (<=>) which work like compareTo()
or you can override equals() method in your DomainClass that make able to use this code
new DomainClass().equals(new DomainClass())
to override equals() you can use #EqualsAndHashCode annotation
this annotation automatically generate equals() and hashcode() methods
So, you class will look like this:
#EqualsAndHashCode
class DomainClass(){
String field1
String filed2
etc
}
and your generated equals method will look like this:
public boolean equals(java.lang.Object other)
if (other == null) return false
if (this.is(other)) return true
if (!(other instanceof DomainClass)) return false
if (!other.canEqual(this)) return false
if (field1 != other.field1) return false
if (field2 != other.field2) return false
// etc
return true
}
For more details look at this http://groovy.codehaus.org/api/groovy/transform/EqualsAndHashCode.html

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

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

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
}

Resources