How to associate new domain class using .properties? - grails

I have the following classes:
class Employer {
static hasMany = [employees: Employee]
}
class Employee {
String name
static belongsTo = [employer: Employer]
}
I try to save some JSON from the front end (the actual code is a bit more dynamic):
params = {
employer: 1,
name: 'Test'
}
def save = {
def employee = new Employee()
employee.properties = params;
employee.save()
}
However, the save fails because the employer cannot be set from the id. (Failed to convert property value of type 'java.lang.Integer' to required type 'Employer') Is there a way to make that work?

The structure of your JSON is incorrect. It would need to be something more like:
'employer':{
'class':'Employer','id':1
}

Related

Groovy: Accessing properties in Parent class

This has to be something really easy, but am pretty new to Grails & Groovy. I am writing a Grails application in version 2.4.3.
There's a class called UserInfo
class UserInfo extends UserDetails {
String userID = ""
static constraints = {
userID blank:false
}
}
Now the UserDetails class:
class UserDetails {
String userName = ""
String userType = "" // 'Admin' or 'Guest' or 'IT' or 'Supervisor'
...................
//Lot more Informations
....................
static constraints = {
userName blank:false
userType blank:false
}
}
And now in another controller class i want to get the User Type information.
def getUserData = {
def type = []
int count = 0
UserInfo.each {
type [i] = it.userType; // Error: No such property: operator for class: UserInfo
i++;
}
}
The goal here is to get list of UserTypes ('Admin' or 'Guest' or 'IT' or 'Supervisor') and the total numbers of each user type.
For e.g., Admin = 230, Guest = 120, .........
The code above doesn't do that and in fact gives an error. I want to use the data above and plot a X - Y Graph.
Ideally i should have the data in a def in an array model as shown below.
def type = []
type << [totalNum: new Integer("230"), userType: 'Admin']
type << [totalNum: new Integer("120"), userType: 'Guest']
............................................................
............................................................
Once i have populated all the data into a def, then i could use Google Visualization to draw the graph easily.
As of now i still don't know how to extract the data from each instance of UserInfo class and then get it to a def.
Appreciate your help!
You are missing the list() method here:
UserInfo.list().each {...}
I don't think it's possible with the syntax you're using. UserInfo.each refers to a colosure over static members of the UserInfo class. However if you want to enumerate things, this can be done with the following syntax.
class UserInfo {
enum UserType {
Admin, Guest, IT
}
}
Enumerating over these then becomes
def getUserData = {
def types = []
def count = 0
UserInfo.UserType.each {
types << it
count++
}
}
However, in grails, with your original class, you're just missing a findAll() or list() call for a domain object. This however will produce duplicates if you have more than one of each user type.
def getUserData = {
def types = []
def count = 0
UserInfo.findAll().each{ UserInfo it ->
types << it.userType
count++
}
}

How to write constraints for hasMany properties in grails

I have three classes in grails application
class Category {
String name
}
class Application {
String name
static hasMany =[specialCategoryies:SpecialCategory]
}
class SpecialCategory {
Category category
Integer points
static belongsTo =[application:Application]
}
Here while I am saving the applicationInstance I don't want save duplicate
specialCategories values like ..specialCategories does not have same
category value again ..
application.addToSpecialCategoryies(newSpecialCategory(category:Category.get(1),points:2))
application.addToSpecialCategoryies(newSpecialCategory(category:Category.get(1),points:3))
here i application instance should rise error that category value repeated..
so how define constraints for hasMany properties in domain class......?
suggest how to write constraints to avoid duplicate values of category
You might try using a custom validator in your Application constraints section. For example, one way to check for duplicate property values is to collect the values into an array and compare them to the corresponding unique array (with duplicated elements removed):
class Application {
String name
static hasMany =[specialCategoryies:SpecialCategory]
static constraints = {
specialCategoryies validator: { specialCategories, obj ->
def specialCategoriesIdArray = specialCategories.collect {it?.category?.getId()}
return (specialCategoriesIdArray.size() == specialCategoriesIdArray.unique().size())?true:'application.validator.specialcategoryduplicate.error'
}
}
}
When trying to save a special category with an existing category, it will throw a validation error when saving. You can test with the following:
def cat1 = new Category(name:"Cat 1").save(flush:true)
def cat2 = new Category(name:"Cat 2").save(flush:true)
def app = new Application()
app.name = "Test"
app.addToSpecialCategoryies(new SpecialCategory(category: Category.get(1), points:2))
app.addToSpecialCategoryies(new SpecialCategory(category: Category.get(2), points:2))
app.addToSpecialCategoryies(new SpecialCategory(category: Category.get(1), points:3))
if ( app.save(flush:true) ){
log.info "Saved!"
} else {
log.error "NOT Saved. Error:"
app.errors.each {
log.error it
}
}

Grails GORM query multiple cascading one to many relationship levels

In Grails I have these 4 domain classes:
package com.whatever.ts4
class A_class {
String aName
static hasMany = [b_class: B_class]
}
package com.whatever.ts4
class B_class {
String bName
A_class a_class
static hasMany = [c_class: C_class]
static belongsTo = [A_class]
}
package com.whatever.ts4
class C_class {
String cName
B_class b_class
static hasMany = [d_class: D_class]
static belongsTo = [B_class]
}
package com.whatever.ts4
class D_class {
Long rowNumber
String dataValue
C_class c_class
static belongsTo = [C_class]
}
Simple ER diagram:
A_class 1=>many B_class 1=>many C_class 1=>many D_class
I'm successfully populating them in BootStrap.groovy
Now,given an single A_class id, I need to obtain a set with these columns:
aName, bName, cName, rowNumber, dataValue
Can I do that using namedQueries?
I’ve tried putting this in the A_class domain class:
static namedQueries = {
myNamedQuery { aid ->
createAlias b_class,'b'
createAlias 'b.c_class','c'
createAlias 'c.d_class','d'
eq 'id',aid
}
}
I like the idea of a named query, because this result set will need to be returned for different A_class id’s. I can utilize a Service to prep the data and call it via the Controller which will render it as JSON (I digress). But, perhaps there is a Groovier way?
You don't need named query for this kind of action. You will obtain all information that you need just by taking it from A_class entity. For example:
def a_class_entity = A_class.get(id)
def b_names = a_class_entity.b_class.bName // set of all bNames
//<-- Not sure if flatten() works with spread collection fields, but it should -->
def c_names = a_class_entity.b_class.c_class.flatten().cName // collection of all cNames
def rowNumbers = a_class_entity.b_class.c_class.d_class.flatten().rowNumber // collection of all rowNumbers
def dataValues = a_class_entity.b_class.c_class.d_class.flatten().dataValue // collection of all dataValues

grails - how to save ArrayList in db

I use grails-1.3.2 and hbase plugin.
I have some difficulty in creating one-to-Many association with
hbase (i can work with hibernate), so
i decided to try create one-to-Many association with using ArrayList.
Here are my domain classes and controllers:
class Contacts {
String con
static constraints = {}
}
class ContactsController {
def create = {
def contact = new Contacts()
contact.con = params.con
contact.save(flush:true)
}
}
class User {
String firstname
String lastname
// static hasMany = [contact: Contacts]
static ArrayList<Contacts> contact
static constraints = {}
}
class UserController{
def create = {
def user = new User()
user.properties = params
user.save(flush: true)
}
def addContact = {
def user = User.get(params.userID)
def contact = Contacts.get(params.contactID)
user.contact.add(contact)
user.save(flush:true)
}
}
In addContact action user.contact = null, so it can not work.
In user does nor appear contact field.
Can someone help me understand what i have to do for saving ArrayList in db?
I don't know anything about hbase, but the static contact property of the User class looks very suspicious. The fact that this property is static, implies that every user has the same contact list, which seems unlikely to be the desired behaviour.
In a standard GORM domain model - assuming you want each User to have their own contact list - this would be defined
class User {
String firstname
String lastname
static hasMany = [contact: Contacts]
}
Although it looks like we're also defining a static property here, it's actually just the definition of how the Contact and User classes are related (AKA mapping) that is static. The contact property that is dynamically added to the User class is non-static.
Aside
I recommend renaming the Contacts class to Contact and the contact property to contacts. The GORM mapping would then look like this:
class User {
String firstname
String lastname
static hasMany = [contacts: Contact]
}

Better way to discover relationship dynamically when saving a new record? (otherSide fails)

Given this relationship:
class A {
String name
static hasMany = [b:B]
}
class B {
String name
static belongsTo = [a:A]
}
I have an record b that I want to save. I've already discovered via working Grails reflection (omitted in the code example below) that it needs to be an instance of class B. Beyond that, record b only knows:
it has a relation "a"
relation "a"'s key
Since it's a dynamic case, we do not know and must discover:
relation "a" is to an instance of class A (so we can call A.find(a's key))
the "other side" of the relation - class A's perspective - is relation "b" (so we can call .addToB(b))
So how do I save b to the database? Here's how I'm doing it:
class AssocTests extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
// I don't know this part, but it's in the DB
def a = new A(name:"al")
a.save()
}
void testAssociation() {
// I want to create a new B such that name="bob"
// I also had to discover "class B" using (working) Grails reflection
// but omitted it for this example.
def b = new B(name:"bob")
// ... and the relation is as "given" below
def given = [a:[name:"al"]]
// So I need to call A.find([name:"al"]).addToB(b). But "A" and
// "addToB" are unknown so need to be found via reflection
def gdc = new DefaultGrailsDomainClass(B)
given.each { give ->
def prop = gdc.getPropertyByName(give.key)
if (prop.isAssociation() && !prop.isOwningSide()) {
println "I want to use otherSide, but it's ${prop.otherSide}"
def os = reallyGetOtherSide(B, give)
def object = os.parent.find(
os.parent.newInstance(give.value))
object."${os.method}"(b)
}
}
def bFound = B.findByName("bob")
assertEquals "al", bFound.a.name
}
def reallyGetOtherSide(clazz, relation) {
def parent=clazz.belongsTo[relation.key]
def addTo=parent.hasMany.find { (clazz == it.value) }.key
[parent:parent, method:"addTo${addTo.capitalize()}"]
}
}
...with otherSide returning null, unfortunately. This can't be the best way to do this, can it?
If I understood you correctly, You can refer to these docs here. You can try the following:
`new A(name:"Gatwick")
.addToB(new B(name:"BA3430"))
.addToB(new B(name:"EZ0938"))
.save()`

Resources