Setting groovy getter/setter methods via constructor in grails domain class - grails

I have a grails unit test that has code similar to below and is appears that setting fields via getter/setter methods doesn't work with constructors (even though it actually works with non-domain classes).
I understand that the following works with properties:
class Person {
def firstName
def lastName
def getFullName() {
return "$firstName $lastName"
}
def setFullName(name) {
firstName = name.split(" ")[0]
lastName = name.split(" ")[1]
}
}
def = new Person(fisrtName: "Joe", lastName: "Bloggs")
But when I do the following the first and last name fields don't get set:
def = new Person(fullName: "Joe Bloggs")
Is there a way to set fields via methods in a groovy contstructor?

What version of groovy are you using? This works fine for me with groovy 1.8.6 and I think it's worked for that way for a very long time:
class Person {
def firstName
def lastName
def getFullName() {
return "$firstName $lastName"
}
def setFullName(name) {
firstName = name.split(" ")[0]
lastName = name.split(" ")[1]
}
}
def p1 = new Person(firstName: "Joe", lastName: "Bloggs")
def p2 = new Person(fullName: "Joe Bloggs")
assert p1.firstName == p2.firstName
assert p1.lastName == p2.lastName
Updated:
Just tried this on grails 2.0.3. You need to be more explicit in your method signatures for grails to work. I changed the method signature for the getter to be String and the setter to be void and it worked. It did not work with just def. Grails 2 is much more strict about matching signatures than previous versions of grails were and I'm betting that this is part of it.
Also, you should specify that the fullName "property" is transient as it isn't a real property that should get persisted in the database. Here's the domain and test class that work for me in grails 2.0.3:
Person.groovy:
package com.example
class Person {
String firstName
String lastName
static transients = ["fullName"]
String getFullName() {
return "$firstName $lastName"
}
void setFullName(String name) {
firstName = name.split(" ")[0]
lastName = name.split(" ")[1]
}
}
PersonTests.groovy:
package com.example
import grails.test.mixin.*
import org.junit.*
/**
* See the API for {#link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions
*/
#TestFor(Person)
#Mock([Person])
class PersonTests {
void testFullName() {
Person p1 = new Person(firstName: "Joe", lastName: "Bloggs").save(failOnError: true)
Person p2 = new Person(fullName: "Joe Bloggs").save(failOnError: true)
assert p1.firstName == p2.firstName
assert p1.lastName == p2.lastName
assert p1.fullName == p2.fullName
}
}

This is caused by because
See 'bindable' here

Related

Grails search from one to many is not working

Here are my domain class,
class Company {
String name
static hasMany = [groups:CompanyGroup]
}
class CompanyGroup{
String name
static belongsTo = [company:Company]
}
I receive params that contain name of CompanyGroup and I want to get the result of company that have the CompanyGroup found.
I did like this,
def groupList = account.companies.groups.flatten()
def groupResult = groupList.findAll{
it.name ==~ /(?i).*${params.keyword}.*/
}
I got the Companygroups that have name from params.key from above code. So I want to render company list that have these group like this,
def com = Company.withCriteria{
eq("groups", groupList)
}
render [companies : com]
It doesn't work!
def com = Company.withCriteria{
inList("groups", groupList)
}

Grails: Legacy DB - Record with composite Id won't update

I'm having problems trying to update a record on a Grails 2.3.7 Project
I don't want to modify the fields that are part of the composite Id, I just want to update the other fields.
Just one class, few properties, but every time I try to update, it throws me the "not unique error" when this lines runs:
personInstance.validate()
if (personInstance.hasErrors()) {
respond personInstance.errors, view:'create'
return
}
My class looks like this:
class Person implements Serializable {
static constraints = {
name(unique: lastName)
}
static mapping = {
id generator: 'assigned'
id composite: ["name", "lastName"]
}
//Override equals and hashcode methods
boolean equals(other) {
if (!(other instanceof Person)) {
return false
}
other.name == name && other.lastName == lastName
}
int hashCode() {
def builder = new HashCodeBuilder()
builder.append name
builder.append lastName
builder.toHashCode()
}
String name
String lastName
String description
}
And the controller action:
def update() {
def personInstance = Person.get(new Person(name:params.name, lastName:params.lastName))
personInstance.properties = params
personInstance.validate()
if (personInstance.hasErrors()) {
respond personInstance.errors, view:'create'
return
}
personInstance.save flush:true
request.withFormat {/*etc...*/}
}
When I use validate(), it throws me a Grails unique key error, when I avoid validation its a BD not unique PK error.
Is like Grails didn't know if I want to do an insert or an update when I personInstance.validate().
Is there a way to manage this in a correct way that I'm not seeing?
Or am I forced to avoid validation?
am I doing something wrong?
Thanks in advance.
I believe the GORM mapping DSL expects just one id definition. Try combining your two id lines into just this one:
id generator: 'assigned', composite: ["name", "lastName"]
Also, in addition to implementing Serializable, your domain class should override equals and hashCode, as described under "Composite Primary Keys" here: http://grails.org/doc/latest/guide/single.html#identity

Equals object criteria query

If I have two domain classes like this:
class Company{
string Name
string address
}
class User {
string firstName
string lastName
Company company
}
How can I get all the users from company named Google using criteria query? Something like this:
def company = Company.findByName("Google")
def c = User.createCriteria()
def usersByCompany = c.list {
eq("company", company)
}
You can declare a block inside your closure to filter any field in the Company:
def usersOfGoogle = User.createCriteria().list() {
company {
eq('name', 'Google')
}
}
I just don't remember if it works only for relationships (belongsTo & hasMany), maybe you will need to change your domain class:
class User {
static belongsTo = [company : Company]
}

Deserialize a JSON object with support for embedded associations

Is there an easy way to deserialize a JSON string to a domain class with support of embedded association; belongsTo and hasMany
{
name: "Customer",
contact: {
name: "Contact"
}
}
class Customer {
name
Contact contact
}
class Contact {
String name
static belongsTo = [customer:Customer]
}
in my controller I would like to do the following
def save() {
def customer = new Customer(request.JSON)
customer.save();
}
Now i'm forced to do
def save() {
def contact = new Contact(request.JSON.contact);
def customer = new Customer(request.JSON);
customer.contact = contact;
customer.save();
}
Have you tried using JsonSlurper?
Example usage:
def slurper = new JsonSlurper()
def result = slurper.parseText('{"person":{"name":"Guillaume","age":33,"pets":["dog","cat"]}}')
assert result.person.name == "Guillaume"
assert result.person.age == 33
assert result.person.pets.size() == 2
assert result.person.pets[0] == "dog"
assert result.person.pets[1] == "cat"
Ref: http://groovy.codehaus.org/gapi/groovy/json/JsonSlurper.html
you can try this
Test test
def result = new JsonSlurper().parseTest('yourString')
test = result
Try this will work.

Why One-to-one relationship dosen't work?

I'm trying to create a very simple relationship between two objects. Can anybody explain me why I can't find the Company object via findBy method?
class Company {
String name
String desc
City city
static constraints = {
city(unique: true)
}
}
class City {
String name
static constraints = {
}
}
class BootStrap {
def init = { servletContext ->
new City(name: 'Tokyo').save()
new City(name: 'New York').save()
new Company(name: 'company', city: City.findByName('New York')).save()
def c = Company.findByName('company') // Why c=null????!
}
def destroy = {
}
}
A field called desc conflicts with the database keyword for descending sort. Per default a field is nullable:false in Grails. So first rename that field to for example description and then provide one or mark that field as nullable:true in your constraints.
class BootStrap {
def init = { servletContext ->
new City(name: 'Tokyo').save()
new City(name: 'New York').save()
new Company(name: 'company', city: City.findByName("New York")).save()
assert Company.findByName('company') != null
}
}
Remember that you can always check for the errors that prevent Grails from saving your objects to the database easily:
def invalidCompany = new Company() // missing required name property
if (!invalidCompany.validate())
invalidCompany.errors.each { println it }

Resources