Grails GORM: groovy maps - grails

Having the following domain class:
class Word {
Map translations
static hasMany = [translations: String]
String toString(){
id
}
}
And some instances saved in grails bootstrap:
def word1 = new Word(translations: [en:"game"]);
word1.save(failOnError: true, flush: true)
def word3 = new Word(translations: [en:"gate"]);
word3.save(failOnError: true, flush: true)
def word2 = new Word(translations: [en:"life"]);
word2.save(failOnError: true, flush: true)
It's not enabled to get translations field correctly. For example:
//input
println Word.findAll().each {
println it.translations
}
//output
[:]
[:]
[:]
[1, 2, 3]
What's wrong?

The doc says:
If you want a simple map of string/value pairs GORM can map this with the following:
class Author {
Map books // map of ISBN:book names
}
def a = new Author()
a.books = ["1590597583":"Grails Book"]
a.save()

It should be
static hasMany = [translations: Map]
instead of
static hasMany = [translations: String]

Related

Field values rendered null when using HTTP GET call in grails

This is domain class of Person :
package com.sample
class Person {
String id
String name
Integer age
Address address
static hasMany = [pets:Pet, alias: String, aliases : Alias]
static mapWith = "mongo"
static constraints = {
address nullable:true
pets nullable :true
}
}
This is the domain class of Address :
package com.sample
class Address {
String address
static mapWith = "mongo"
static constraints = {
address maxSize: 1000
}
}
This is ShowPerson method in PersonController:
def showPerson(String name,String age){
if(Person.findByAgeAndName(age,name) != null) {
render Person.findByAgeAndName(age,name) as JSON
}
else {
def addobj = new Address(address: "kondapur")
addobj.save(flush:true)
def pet1 = new Pet(name : "Dog", breed : "A")
pet1.save(flush:true)
def alias1 = "ALIAS1"
def alias2 = "ALIAS2"
def list = ["A"]
def aliases1 = new Alias(aliasname : [list])
aliases1.save(flush:true)
def person = new Person(name : name, age : age, address : addobj, pets : [pet1], alias : [alias1, alias2], aliases : [aliases1])
person.save()
render person as JSON
}
}
Initially there are no persons in DB(which impliesPerson.findByAgeAndName(age,name) == null) Hence it creates a new object and saves it in database). So when I click on the url
> http://localhost:8080/TestJson/showPerson/sample/23
The output now is :
Now when I reclick on the same url (implies Person.findByAgeAndName(age,name) != null) Hence it gets from the database):
The output now is :
In database the address is saved as :
In database the person is saved as :
Can someone tell me how can I get the address (encircled in red) as not null and get the corresponding value when I try to get a saved object from database (i.e in this case kondapur and not null)
Grails JSON marshaller by default doesn't add nested classes, you have to add one line of code:
def showPerson(String name,String age){
JSON.use('deep')// <============================== Add this line
if(Person.findByAgeAndName(age,name) != null) {
render Person.findByAgeAndName(age,name) as JSON
}
else {
def addobj = new Address(address: "kondapur")
addobj.save(flush:true)
def pet1 = new Pet(name : "Dog", breed : "A")
pet1.save(flush:true)
def alias1 = "ALIAS1"
def alias2 = "ALIAS2"
def list = ["A"]
def aliases1 = new Alias(aliasname : [list])
aliases1.save(flush:true)
def person = new Person(name : name, age : age, address : addobj, pets : [pet1], alias : [alias1, alias2], aliases : [aliases1])
person.save()
render person as JSON
}
}

Saving related entity in grails

I have a problem with saving form values from two domain classes
One class is
class Ip {
String inetAddress
String dns
String os
String toString(){
"${inetAddress}"
}
Hoster hoster
static constraints = {
....
and the second one is just
class Hoster {
static HOSTER_OPTIONS = ["Name1", "Name2", "Name3"]
String name;
String toString(){
"${name}"
}
List ips = new ArrayList()
static hasMany = [ips : Ip]
static constraints = {
name(unique: true, blank: false, inList: HOSTER_OPTIONS)
}
I have a Controller where I handle the data from a form
def systems = new Ip()
systems.inetAddress = params.ip
systems.dns = params.dns
systems.os = params.os
systems.hoster.name = params.hoster
def result = systems.save(flush: true, failOnError: true)
But I didn't get it managed that the data is saved.
You're not associating correctly your domain classes in the controller:
systems.hoster.name = params.hoster
Instead of setting the name, you need to set the instance that exists in the database:
systems.hoster = Hoster.findByName(params.hoster)

Inheritance and data binding on Grails

I have a problem to use data binding with inherit models. That's my code:
class Member {
int age
static belongsTo = [Family]
static constraints = {}
}
class Parent extends Member {
String name
static constraints = {}
}
class Family {
String name
List members
static hasMany = [members: Member]
static constraints = {}
}
def test(){
def bindingMap = [name: 'toto', members:[[age: 18, name: '1'],[age: 18]]]
def family = new Family()
family.properties = bindingMap
family.save(flush: true)
def get = Family.get(family.id)
// here family only contains Member and no Parent, as expected...
}
With this code, as you can see, I'm not able to create Parent with data binding.
Anyone have an idea?
Thanks

grails domain dirtyPropertyNames for child object

def names = domain.dirtyPropertyNames
for (name in names) {
def originalValue = domain.getPersistentValue(name)
def newValue = domain."$name"
}
But if i have a relation of 1-1 with other domain
how can i access dirtyPropertyNames for that other domain
def dirtyProperties = domain?.otherDomain?.dirtyPropertyNames
for (name in dirtyProperties ) {
def originalValue = domain?.otherDomain?.getPersistentValue(name)
def newValue = domain?.otherDomain?."$name"
}
But i am getting
No such property: dirtyPropertyNames for class: otherDomain
This seems not to be an issue when tested against Grails 2.2.4 and 2.3.0.
How have you tailored the 1:1 relationship?
Here is a sample, hope that helps:
class Book {
String name
String isbn
static hasOne = [author: Author]
}
class Author {
String name
String email
Book book
}
//Save new data
def book = new Book(name: 'Programming Grails', isbn: '123')
book.author = new Author(name: "Burt", email: 'test', book: book)
book.save(flush: true)
//Sanity check
println Book.all
println Author.all
//Check dirty properties of association
def book = Book.get(1)
book.author.name = 'Graeme'
def dirtyProperties = book?.author?.dirtyPropertyNames
for (name in dirtyProperties ) {
println book?.author?.getPersistentValue(name) //Burt
println book?.author?."$name" //Graeme
}
Although, wrt Grails 2.3.0 you can persist a 1-1 relation as done below unlike above:
def author = new Author(name: "Burt", email: 'test')
def book = new Book(author: author, name: 'PG', isbn: '123').save(flush: true)

Grails - Trying to remove objects, but they come back

I have two domain classes, Job and Description, in a simple one to many relationship:
Job.groovy
class Job {
static hasMany = [descriptions: Description]
static mapping = {
descriptions lazy: false
}
}
Description.groovy
class Description {
static belongsTo = [job: Job]
}
I have two controller actions:
def removeDescriptionFromJob(Long id) {
def jobInstance = Job.get(id)
System.out.println("before remove: " + jobInstance.descriptions.toString())
def description = jobInstance.descriptions.find { true }
jobInstance.removeFromDescriptions(description)
jobInstance.save(flush: true)
System.out.println("after remove: " + jobInstance.descriptions.toString())
redirect(action: "show", id: id)
}
def show(Long id) {
def jobInstance = Job.get(id)
System.out.println("in show: " + jobInstance.descriptions.toString())
}
This is what gets printed when I submit a request to removeDescriptionFromJob:
before remove: [myapp.Description : 1]
after remove: []
in show: [myapp.Description : 1]
Why does the Description get removed in the removeDescriptionFromJob action, only to come back immediately afterwards in the show action?
removeFromDescriptions did remove the relationship of jobInstance from description, but the entity description still exists.
System.out.println("after remove: " + jobInstance.descriptions.toString())
would result no o/p since the relation is non-existing. In place of the above line try to get the description object directly like:
System.out.println("after remove: " + Description.get(//id you just disassociated))
You would get the description successfully.
To avoid that, you need to add the below mapping property to Job to remove all the orphans once an entity is detached from parent.
descriptions cascade: "all-delete-orphan"
Like:
class Job {
static hasMany = [descriptions: Description]
static mapping = {
descriptions lazy: false, cascade: "all-delete-orphan"
}
}
GORM Bible - A must-read.

Resources